Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
A small demo of an AI decision layer for truck breakdowns. When a truck throws a fault code, Breakdown Desk:查看完整 README ↗
A small demo of an AI decision layer for truck breakdowns.
When a truck throws a fault code, Breakdown Desk:
FaultEvent.stop_now / limp_to_shop / schedule_later), decides whether a tow is needed, picks the shops to ask and checks whether the repair is recoverable under warranty.Every step streams live to a dashboard through Supabase Realtime.
Six layers, run in order by lib/pipeline.ts, following Elmeeda's ontology:
Signals → Units → Decisions → Actions → Counterparties → Records
| Layer | Code | What it does |
|---|---|---|
| Signals | app/api/signals/[source], lib/adapters/* | Webhook per source (geotab, samsara, driver) → FaultEvent |
| Units | lib/units.ts | Truck, current load, warranty coverage |
| Decisions | lib/decisions/* | Severity, tow need, shop set, warranty recoverability |
| Actions | lib/pipeline.ts | Call capable shops for quotes |
| Counterparties | lib/counterparties.ts, lib/actions.ts | Shops answer in parallel, quote_accept, then templated booking, driver SMS and warranty claim (pending) |
| Records | lib/records.ts | Repair order and claim line (stand-in for the fleet's maintenance system or TMS) |
The core logic is in lib/decisions/severity.ts:
stop_now. The LLM is not called.stop_now result, or an LLM confidence below 0.7, is marked as needing approval.limp_to_shop, so it is never auto-approved. A driver report with no milepost stops before shop selection and asks dispatch to confirm the location instead of guessing one.rule, llm or human), its reason and its inputs.lib/llm.ts is the only file that calls an AI provider (OpenAI, structured JSON output). Everything else is rules and templates.
| Button | Source | Expected path |
|---|---|---|
| Oil pressure critical | Geotab | Rule → stop_now, tow, needs approval |
| DPF warning | Samsara | LLM → limp_to_shop, under warranty → OEM dealer |
| Slow tire leak | Driver SMS | schedule_later, auto-approved |
Next.js (App Router) + TypeScript + Tailwind, Supabase (Postgres + Realtime), OpenAI SDK, deployed on Vercel. No orchestration framework. No user login (see Security notes).
npm install
In the Supabase dashboard, open SQL Editor and run these two files in order:
supabase/schema.sql creates the tables, the security settings and the Realtime publication for incident_events.supabase/seed.sql adds the trucks, the shops along I-80, the warranty policies and the loads.schema.sql drops and recreates its tables, so you can re-run both files to reset everything.
cp .env.example .env.local
Then fill in .env.local:
| Variable | Where to find it |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase → Project Settings → API |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Same page (anon / public key). The browser uses it to subscribe to the live feed. |
SUPABASE_SERVICE_ROLE_KEY | Same page (service role). Server only. Never expose it. |
OPENAI_API_KEY | platform.openai.com |
OPENAI_MODEL | Optional. Defaults to gpt-4o-mini. |
SIGNALS_WEBHOOK_SECRET | Any long random string, e.g. openssl rand -hex 32. Required to call /api/signals/*; the webhook rejects every call while it is unset. |
npm run dev
Open http://localhost:3000 and click a scenario button. The layer bar and the live feed fill in as the pipeline runs (with about 400 ms between steps so it stays readable). Approve pending actions from the incident panel. Reset clears incidents but keeps the reference data.
npm test
Vitest covers the safety logic with no database or OpenAI calls: driver keyword classification and location parsing, the severity rule floors, the "LLM can escalate but never downgrade" guarantee, the approval thresholds, and which drafted actions auto-approve. The Supabase writes and the live LLM call are exercised by the demo scenarios rather than unit tests.
The scenario buttons replay fixed payloads through /api/scenarios/[id]. To send your own payload, call the webhook with the shared secret:
curl -X POST http://localhost:3000/api/signals/driver -H 'content-type: application/json' -H "x-webhook-secret: $SIGNALS_WEBHOOK_SECRET" -d '{"channel":"sms","receivedAt":"2026-10-02T03:02:16Z","driver":{"name":"Marcus Hale"},"unitNumber":"4590","message":"Left rear drive tire is losing air slowly, about 3 psi an hour. Still rolling fine on I-80 E near MP 284."}'
The call returns 202 { incidentId } right away, and the pipeline keeps running in the background. See lib/mockPayloads.ts for example Geotab and Samsara payloads.
| Method | Route | Purpose |
|---|---|---|
POST | /api/signals/[source] | Ingest a fault (geotab, samsara or driver). Needs the x-webhook-secret header |
POST | /api/scenarios/[id] | Run one of the three demo scenarios (oil, dpf, tire) from the dashboard |
GET | /api/incidents/[id] | Incident with its truck, load, decisions, actions, records and events |
POST | /api/actions/[id]/approve | Human approval of a pending action |
POST | /api/reset | Clear runtime data |
This is a demo, and these are the trade-offs made on purpose:
incident_events (the live feed) and nothing else./api/signals/* accepts arbitrary payloads, so it requires a shared secret (x-webhook-secret) and fails closed when none is configured.The app deploys to Vercel as a standard Next.js app. Set the same environment variables in the Vercel project settings.