Synaplan
開源 AI 平台,供企業使用:自行託管的 AI 代理、符合 GDPR 的聊天機器人小工具、RAG 知識庫、WhatsApp 與 Outlook AI、MCP、多模型路由。Docker、Kubernetes 或託管於 Germ
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Tveris connects to a shipping documentation desk's inbox, reads every email, classifies it into five queues, compares each draft bill of lading against its shipping instruction field by field, and hands the team only the few that a person actually has to decide.
The comparison is deterministic code, never an LLM. AI reads documents and sorts mail; plain rules decide whether two values match, so every verdict is reproducible and can be explained down to the line it came from.
Built by The Minions for the Agentic AI Cybersecurity Hackathon 2026 (GDEX × ANON × UTAR), Track 02 — Secure Logistics & Digital Trust.
| Link | |
|---|---|
| 🌐 Live prototype | tveris.vercel.app |
| 🎬 Demo video | Watch the 4-minute demo |
| 📊 Pitch deck | Tveris pitch deck |
| 📄 Proposal | Tveris proposal (PDF) |
| 💻 Source code | github.com/eyahia1712/Tveris |
| ⚡ Run it yourself | Four commands |
A documentation desk receives 500–1,000 emails a day in one shared mailbox: SI and draft BL checks, new shipping instructions, invoice questions, automated notices and spam. Two things go wrong, every day.
PORT OF LOADING (装货港) in the next one. A missed consignee
change means cargo released to the wrong company, amendment fees, and delay.On the organisers' 520-email dataset, 78 emails need a person. The other 442 are sorted, checked or quarantined automatically — and each of the 78 arrives with its evidence and a drafted reply already written.
InboxSource interfaceThe pipeline never knows where the mail came from.
Subject lines are recycled thread titles, so the body decides, not the subject.
.txt, .xlsx, .docx and text PDFs are parsed deterministicallyEvery document is identified by its content, not its filename: a file named
_BL.txt that is really a commercial invoice is caught and escalated.
Shipper · Consignee · Notify party · Port of loading · Port of discharge · Container count · Gross weight (kg)
POL, Load Port, PORT OF LOADING (装货港))N/A, TBA, ____MT, ??? — are treated as missing,
never as data131,058 KG equals 131058; SINGAPORE, SINGAPORE (SGSIN) equals SINGAPOREAn LLM never decides that two values match. Zero formatting false alarms on the full dataset, enforced by a test.
Human-in-the-loop is a first-class screen, not an afterthought.
The team works from a short queue, not from an inbox.
The dashboard: how many emails need you, the five queues, where the BLs go wrong, and the work itself. Every number leads to the emails behind it.
The inbox map: the mailbox at the centre, five queues around it, and the document check opened into Mismatch (red), Needs review (amber) and No mismatch (green). Click a group to grow its emails, click an email to grow its SI, BL, verdict and seven fields.
One email, end to end: SI against BL with the source label of every value, the documents as they were read, the full pipeline trace, the classification rationale, the drafted reply and the review form.
| Page | What it is |
|---|---|
| / | The landing page: the problem, the product, how it works, FAQ |
| /dashboard | What needs you now — queues, defects by field, the work list, search |
| /inbox | The inbox map and the queue view, with replay |
| /emails/[id] | One email: comparison, documents, trace, reply, review form |
| /report | The printable discrepancy report the brief asks for |
| /connect | Sources: sample inbox, Gmail, Claude, Outlook |
| /docs | Architecture, how to run it, self-evaluation |
520 emails · 250 attachments · no AI key required
| Measure | Result |
|---|---|
| Emails classified | 520 / 520, no processing failures |
| Document checks | 129 — 46 mismatch, 20 needs review, 63 no mismatch |
| Trap cases escalated with the correct reason | 20 / 20 — 5 wrong document types, 5 missing attachments, 2 corrupt PDFs, 3 image-only scans, 5 blank SI values |
| False alarms from formatting | 0 — every flagged field still differs after normalisation |
| Formats read | TXT, XLSX, DOCX, PDF (text), PDF (image-only, via Claude vision) |
| Full run time | ~500 ms on the rule engine |
npm run process -- --source http://localhost:8080 --submit runs the same
pipeline against the organisers' server and posts the official self-evaluation.
flowchart LR
IN["📥 Inbox<br/>sample · Gmail"] --> P1
subgraph P["⚙️ Pipeline, per email"]
direction LR
P1["Classify<br/>Claude + rules"] --> P2["Read<br/>docs + vision"] --> P3["Extract<br/>7 fields"] --> P4["Compare<br/>plain code"] --> P5["Decide<br/>+ draft reply"]
end
P5 --> UI["🖥️ App + store<br/>dashboard · report"]
UI -. "human review" .-> P4
lib/pipeline/) — pure TypeScript, no framework dependency. It
runs identically in the web server, the CLI and the tests. Every stage writes
an event, so a failure is visible and retryable per email.lib/ai/claude.ts) — Claude (claude-opus-5 by default) with
schema-validated structured outputs and a server-side fallback. Used for
classification, vision and unfamiliar layouts. Never for comparison.lib/store/) — Postgres when DATABASE_URL is set, atomic JSON
files otherwise. A committed snapshot means a fresh deployment opens on a
fully processed inbox.lib/viz/, components/viz/) — the data builder, the d3-force
layout and the canvas are three separate layers. Nodes keep stable "homes",
so opening one branch never reshuffles the rest of the map.lib/server/jobs.ts) — whole-inbox runs happen in the background
with live progress; retry and review work per email.Scaling path: every email is independent, so today's 8-way worker pool
becomes a queue (Cloud Tasks or Pub/Sub) with stateless workers, Gmail push
notifications (users.watch) replace polling, and a run moves from one JSON
document to one row per email.
| Layer | Technology | Why |
|---|---|---|
| App | Next.js 16, React 19, TypeScript (strict) | One deployable for UI, API and background jobs |
| AI | Claude via @anthropic-ai/sdk, structured outputs, PDF vision | Classification with a rationale; reads scanned documents |
| Documents | exceljs, mammoth, unpdf | Real parsing where the layout is known — no AI needed |
| Graph | d3-force + HTML/SVG canvas | Force layout with stable homes and wedge-packed clusters |
Gmail API, OAuth2 (gmail.readonly + gmail.send) | Live inboxes; token in an AES-256-GCM encrypted httpOnly cookie | |
| Data | Postgres (pg) or JSON files | Cloud database in production, zero setup locally |
| Cloud | Docker → Google Cloud Run (+ Cloud SQL), or Vercel | Scales to zero; the same image runs anywhere |
| Quality | Vitest, ESLint, zod at every API boundary | 23 tests, including the full 520-email inbox |
npm install
cp .env.example .env.local # optional: ANTHROPIC_API_KEY for AI + vision
npm run process # process the bundled sample inbox
npm run dev # http://localhost:3000
npm test # 23 tests, including all 520 emails
Without an API key Tveris still runs, on the rule engine. Everything works except the three image-only scans, which go to review as unreadable.
Against the organisers' server: docker compose up --build on their side,
then set TVERIS_SOURCE_URL=http://localhost:8080.
Gmail: create a "Web application" OAuth client in Google Cloud, enable the
Gmail API, add <your-url>/api/gmail/callback as a redirect URI, and set
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET and TVERIS_SECRET.
gcloud run deploy tveris --source . --region asia-southeast1 --allow-unauthenticated \
--set-env-vars TVERIS_PUBLIC_URL=https://<service-url> \
--set-secrets ANTHROPIC_API_KEY=anthropic-key:latest,DATABASE_URL=tveris-db:latest \
--min-instances 1 --no-cpu-throttling
--no-cpu-throttling keeps background runs alive between requests. On Vercel,
set DATABASE_URL to a managed Postgres — the serverless filesystem is not
writable, so the JSON store cannot be used there.
Every service is one environment variable away; nothing needs a code change.
| Service | Off | On |
|---|---|---|
| Hosting | Local next start | Cloud Run (Dockerfile) or Vercel |
| Database | JSON files under data/ | Postgres — set DATABASE_URL |
| AI | Rule engine only | Claude API — set ANTHROPIC_API_KEY |
| Bundled sample inbox | Gmail API — set the three Google variables | |
| Scheduler | Manual runs | Cloud Scheduler → /api/cron, set CRON_SECRET |
state cookie and verifies the Google ID token.Every line of the brief maps to something that runs.
| The brief asks for | Tveris does it |
|---|---|
| Classify each email | Five queues, every email placed with a reason |
| Extract the seven fields | By meaning, from txt, xlsx, docx, PDF and scans |
| Compare SI against draft BL | Deterministic rules, SI as the reference |
| Flag discrepancies | 46 caught, each with both values and its source line |
| Handle what it cannot read | 20 escalated with a reason, never guessed |
| Produce a discrepancy report | /report, printable, plus a submission.json export |
AI. Claude (claude-opus-5) via the Anthropic API, with structured outputs. It
classifies every email and gives a rationale, reads scanned pages with vision, and
maps layouts the parser has not seen. A rule engine classifies independently and any
disagreement is surfaced. Claude is never asked whether two values match — that is
plain code, so a verdict is reproducible.
Cloud. Each service is one environment variable away; no code changes between a laptop and production.
| Service | In use |
|---|---|
| Hosting | Vercel (live) · Dockerfile targets Google Cloud Run |
| Database | PostgreSQL when DATABASE_URL is set, JSON files otherwise |
| AI | Anthropic API — ANTHROPIC_API_KEY |
| Gmail API, OAuth 2.0 read + send, token AES-256-GCM encrypted in the user's cookie | |
| Scheduling | /api/cron for Cloud Scheduler or Vercel Cron — CRON_SECRET |
human, and the comparison recomputes under the same
rules — so a review can become a caught mismatch. That is the feedback loop a real
desk would use daily.Each one was found against real data and is now covered by a test.
| Challenge | Fix |
|---|---|
| Three BLs were scans with no text layer | Claude vision reads the page; escalated as unreadable when AI is off |
PDF text glued label to value (…Intermediate ConsigneeCERIEX) | Longest matching label wins, so the value starts in the right place |
____MT compared equal to itself and passed | Underscores normalised away; blanks classed as missing |
One port written four ways (SGSIN, SINGAPORE (SGSIN)…) | Ports canonicalised, but a code alone never proves the port |
| Subject lines are recycled thread titles | Classify on the body and attachments, not the subject |
| The cloud has no writable disk | Postgres when configured, JSON otherwise; a processed snapshot ships in the repo |
| Metric | Result |
|---|---|
| Emails classified | 520 / 520, no processing failures |
| Document checks | 129 |
| Mismatches caught at draft stage | 46 |
| Escalated with a reason, never guessed | 20 |
| False alarms from formatting | 0 |
| Difficult cases handled correctly | 20 / 20 |
| Full re-check of the inbox | ~0.5 s |
| Automated tests | 23, over the whole dataset |
users.watch replaces polling, so a document is checked
seconds after it arrives.InboxSource
interface; roles, permissions and an audit log make it multi-user.Four students from Lincoln University College. Tveris was designed, built, tested and deployed for the Agentic AI Cybersecurity Hackathon 2026.
| Member | Role | Institution | GitHub | |
|---|---|---|---|---|
| Eya Hia | Team lead — full-stack & AI pipeline | Lincoln University College | @eyahia1712 | eya-hia |
| Shah Rabbi Hasan Foyej | Documents — parsing & field extraction | Lincoln University College | @foyej-14 | foyej |
| Abu Sadat Md Sayem | Cloud — deployment & DevOps | Lincoln University College | @abuxadat | abusadatmdsayem |
| Lwin Win | Frontend — dashboard & inbox map | Lincoln University College | @lwinwin786-web | lwin-win |
/docs in the running app — architecture, how to run it, self-evaluation.env.example — every environment variable, with what it switches onlib/pipeline/pipeline.test.ts — the checker's behaviour, stated as tests
over the whole sample inboxTveris · The Minions · Agentic AI Cybersecurity Hackathon 2026 · GDEX × ANON × UTAR