Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A workspace for Kicks's expansion team. Bring in franchise partner applications and the areas to grow in from one Excel file. For every applicant the Desk shows what should happen, why (a step-by-step reason trail), what they must do next, how they will be trained, a dated timeline, a ready message in Kannada, Hindi or English, and a private status page that always shows the latest decision.
Live: https://kicks-partner-desk.vercel.app
The engine decides. The language assistant never does. All decisions come from plain, tested TypeScript in src/engine/ (the same input always gives the same output). The assistant (Gemini, through OpenRouter, Google models only) does three jobs:
With no AI key everything still works: keyword fallbacks read the text and templates write the wording.
Every number the engine uses is an assumption (below), shown on the Assumptions page and editable. Saving re-runs everyone and shows who changed.
Excel file ──► POST /api/run ──► read + clean (src/lib/readWorkbook.ts) ──► Data Health report
│
▼
Neon Postgres (runs, applications, territories,
existing_stores, decisions, decision_events,
chat_messages, status_links)
│
┌───────────────────────────────┼─────────────────────────────────┐
▼ ▼ ▼
Browser (Next.js) POST /api/chat /s/<token>
runs the engine for the Gemini tool calling: applicant status page,
screens; saves changes get/explain/compare/update/ rebuilt from the run
with a revision check withdraw/rerun/set_assumption every time it opens
│ │
└──────────► src/engine (pure, tested) ◄────────────────────────┘
checks → score → rank → allocate → redirect → reason trail
/run/<uuid> opens it for anyone with the link, with no sign-in. Runs are deleted after 7 days without changes.decision_events (before, after, trigger, actor, time) and can be undone.All live in src/engine/config.ts (DEFAULT_ASSUMPTIONS) and on the Assumptions page.
| Assumption | Default |
|---|---|
| Setup cost, ₹ lakh (Tier 1 / 2 / 3) | 35 / 25 / 18 |
| Minimum investment, % of setup cost | 100 |
| Investment tolerance below the minimum, % | 10 |
| Investment cap for points, × setup cost | 1.2 |
| Score weights: investment / space / experience / timeline / area priority / completeness | 25 / 25 / 20 / 10 / 10 / 10 |
| Area priority share (High / Medium / Low) | 100% / 60% / 30% |
| Experience share (0 / 1–2 / 3–5 / 6+ years) | 0% / 40% / 75% / 100% |
| Business background bonus inside experience (max) | +3 points |
| Space share (owned / rented) | 100% / 80% |
| Floor factor (ground, mall / upper / not known) | 1.0 / 0.7 / 0.8 |
| Ideal size / near-ideal range, sq ft | 400–800 / 250–1200 |
| Size factor (ideal / near / other) | 1.0 / 0.8 / 0.5 |
| Minimum score to get an opening | 45 |
| Space-ready applicants placed first | on |
| Stage lengths, weeks: find space / site approval / agreement / fit-out / hiring / training / inventory / soft launch | 9 / 2 / 2 / 4 / 3 / 2 / 2 / 1 |
| Days an opening is held for a condition | 30 |
| Monthly sales, ₹ lakh (Tier 1 / 2 / 3) | 9 / 6 / 4 |
| Take-home share, rented (Tier 1 / 2 / 3) | 15% / 15% / 16% |
| Take-home share, owned (Tier 1 / 2 / 3) | 23% / 23% / 24% |
| Sales spread for the payback range, ± % | 20 |
| Payback target, months | 30 |
| Training days (no experience / 1–2 years / 3+ years) | 14 / 7 / 3 |
| Training hours per day | 6 |
| Nearby-store flag, pin distance | 10 |
| "Start here" bonus (High / Medium / Low) | 5 / 2 / 0 |
| "Start here" list size | 5 |
npm install
cp .env.example .env.local # then fill in the values
npm run dev # http://localhost:3000
npm run lint
npm run typecheck
npm test
npm run build
Without DATABASE_URL the Desk still opens and works in one tab (changes are kept in this browser only). With it, runs, events and chat are saved.
| Name | Use |
|---|---|
DATABASE_URL | Neon Postgres pooled connection string. Tables are created on first use. |
OPENROUTER_API_KEY | Switches on the assistant (Gemini, Google models only, via OpenRouter). |
OPENROUTER_MODEL | Optional. A model id starting with google/. Default google/gemini-3.7-flash. |
AI_ENABLED | Optional. Set false to force the keyword fallbacks and template wording. |
LANGSEARCH_API_KEY | Switches on live market notes on the Market page. |
CRON_SECRET | Protects the daily clean-up at /api/cron/purge. |
No secrets are stored in the repository. .env.local is ignored by git.
BASE_URL=http://localhost:3000 npm run seed
Starts a run with the practice data on a running copy and prints its /run/<uuid> link. The fixed ten existing stores are written to the existing_stores table automatically the first time the app talks to the database. npm run make-fixture rebuilds the practice workbook.
Open the live site, press Import → Load practice data, then open Ask assistant (docked panel on desktop, bottom sheet on a phone) and try these seven things.
"Why is APP-005 approved at 32 while APP-003 at 87 is waitlisted?" — The assistant corrects the premise: APP-005 is not approved. Its score is 40.3, below the minimum of 45, and the instruction in its notes was ignored. APP-003 (89.7) is waitlisted because APP-002 (100) won pin 570001 and APP-003 has a space in that pin. A side-by-side comparison of pin availability and score follows.
"APP-002 has withdrawn" — Saved at once. APP-002 becomes Withdrawn and APP-003 moves up from the waiting list to win 570001. The diff card shows both, with an Undo button. The applicant page and the Audit log update immediately.
"APP-012 found a shop" — The assistant asks one short question (owned or rented, and what size) and saves nothing. Then "APP-012 found a 450 sq ft ground-floor rented shop" is saved and the score rises from 60 to about 85. APP-012 stays on the waiting list, because APP-009 holds pin 560010, and the card says so.
"Add one opening to TER-03" (on a fresh run) — APP-012 gets an outcome: Redirected to pin 560011.
"Why is APP-006 redirected?" — Kicks already has store ST-06 at pin 570009. TER-02 has free pins 570004 and 570020. 570004 is nearest, so it is offered, and it uses one of the area's two openings.
"Approve APP-005 anyway" — Declined politely, with a pointer to Change this decision, which asks for a reason and is recorded in the Audit log.
"What happens if we raise the minimum score to 60?" — A what-if is never saved. The reply is one line and the card is labelled Preview, not saved, listing every decision that would change (for example APP-012 becoming Not eligible). The minimum score stays at 45 and the Audit log gets no entry. Press Apply this change to save it; the saved card then has Undo and the change is logged.
Also try: Assumptions (change the minimum score or the money tolerance, save, and read the diff card), Areas (the pin board), and the applicant status link (/s/…) on a phone.
npm test runs Vitest: every engine rule, every acceptance case on the practice data, the parser edge cases (example row, decimal pins, comma-split pins, blank optional fields, free-text language, duplicate IDs), the chat tools and an integration test that imports the practice data, withdraws APP-002 and checks that APP-003 is promoted and decision_events records it (runs when DATABASE_URL is set). CI runs lint, typecheck, test and build on every pull request; Vercel deploys main.