Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Aangan reception Voice AI
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Mesa School, Case 03: Aangan Studio unanswered enquiries. A voice AI desk built around Vaani.
Aangan Studio (interior design for homes and small offices, Pune, 60 people, 14 designers, founder Nikhil Deshpande) gets about 200 enquiries a month. About 48% get no response within 48 hours, about 33% arrive outside 10am to 7pm, and the front desk is 2 people. The case says an enquiry answered within an hour converts at 4x the rate of one answered next day. Nikhil wants every enquiry answered within 5 minutes, day or night, and worthwhile enquiries to reach designers with everything already asked.檢視完整 README ↗Mesa School, Case 03: Aangan Studio unanswered enquiries. A voice AI desk built around Vaani.
Aangan Studio (interior design for homes and small offices, Pune, 60 people, 14 designers, founder Nikhil Deshpande) gets about 200 enquiries a month. About 48% get no response within 48 hours, about 33% arrive outside 10am to 7pm, and the front desk is 2 people. The case says an enquiry answered within an hour converts at 4x the rate of one answered next day. Nikhil wants every enquiry answered within 5 minutes, day or night, and worthwhile enquiries to reach designers with everything already asked.
This project covers incoming phone calls only. Vaani answers the call live, asks the qualifying questions, and when the call ends it posts the call to this app. The app extracts the details, scores the lead against Nikhil's five criteria, checks the agent's own lines with guardrails, attaches an internal estimate for the designer only (never quoted to the client), notifies designers on Telegram, stores the record, and shows everything on a dashboard for Nikhil and the front desk.
/api/vaani-webhook.{callId, callerName, phone, startedAt, durationSec, transcript, recordingUrl, bookedSlot?}.policy/qualified.md, policy/services.md, policy/pricing.md; their numbers in policy/rubric.json. Code: rubric (lib/rubric.js), internal pricing (lib/pricing.js), guardrails (lib/guardrails.js), cost (lib/cost.js)./.app/api/vaani-webhook/route.js POST, called by Vaani after each call
app/api/calls/route.js GET list, GET ?id= detail (?demo=1 adds sample calls)
app/api/stats/route.js GET KPIs (?includeDemo=1 to count sample calls)
lib/handlers/ the (req, res) handlers behind those routes
lib/nextAdapter.js runs a (req, res) handler inside a Next.js route handler
lib/dashboardData.js data for the server-rendered pages, read straight from the store
lib/ extract, gemini, rubric, pricing, cost, store, telegram, demo, process
app/page.js dashboard (server rendered, Ant Design)
app/calls/[id]/page.js one call, server rendered
app/loading.js skeleton shown while a page streams
components/ dashboard pieces (KPI cards, calls table, call detail, cost and value)
Next.js 14 (App Router) with Ant Design 5. Styles are rendered on the server through
@ant-design/nextjs-registry, so the first paint is complete without client JavaScript.
Dashboard state lives in the URL: ?samples=1 shows sample calls, ?count=1 counts them in the
numbers, ?call=<id> opens a call in the side panel. Node 18 or newer.
npm install
npm run dev # http://localhost:3000, hot reload
npm run build && npm start # production build on http://localhost:3000
npm run check # prettier, eslint, unit + regression + smoke tests
npm run test:e2e # Selenium against `next start` (builds first if needed)
npm run lighthouse # builds, starts on :3900, prints mobile and desktop scores
Send a test call:
curl -X POST http://localhost:3000/api/vaani-webhook \
-H 'Content-Type: application/json' \
-d '{"callId":"c1","callerName":"Test","phone":"+91 90000 00000","startedAt":"2026-10-10T15:00:00Z","durationSec":200,"transcript":"Caller: 2 BHK flat in Kothrud, 950 sq ft, budget 9 lakh, start in 1 month."}'
All are optional. With none set, the app runs on rules only, skips Telegram, and stores in memory.
| Variable | Purpose | If not set |
|---|---|---|
WEBHOOK_SECRET | Shared secret Vaani sends in the x-webhook-secret header | Webhook accepts any caller |
GEMINI_API_KEY | Enables Gemini extraction and brief | Rules only |
GEMINI_MODEL | Gemini model name | gemini-flash-latest |
TELEGRAM_BOT_TOKEN | Bot that posts handoff notes | Notification skipped |
TELEGRAM_CHAT_ID | Designers group chat id | Notification skipped |
UPSTASH_REDIS_REST_URL | Durable storage | In-memory (not durable on Vercel) |
UPSTASH_REDIS_REST_TOKEN | Durable storage | In-memory |
DEMO_DATA | off hides the 8 synthetic demo calls | Demo calls shown (never counted in KPIs unless toggled) |
VOICE_COST_PER_MIN | Rupees per voice minute (assumption) | 6 |
LLM_COST_PER_CALL | Rupees of LLM cost per call (assumption) | 0.5 |
policy/pricing.md. Calls where the agent slips are flagged for review on the dashboard.https://<your-vercel-domain>/api/vaani-webhook, method POST, JSON body.x-webhook-secret: <same value as WEBHOOK_SECRET>.lib/handlers/vaani-webhook.js if they differ. transcript can be a string (Caller: ... lines) or an array of {speaker, text}. An optional answeredAfterSec is read if Vaani reports ring time; otherwise a live Vaani pickup counts as answered within 5 minutes.vercel.json sets the framework to Next.js, so Vercel builds with next build and serves the
pages and the /api/* route handlers. In the Vercel project settings the Framework Preset should
read Next.js (vercel.json makes this automatic). The webhook URL stays /api/vaani-webhook.
Ship a preview first, check it, then promote:
vercel # preview deployment from this branch
# open the preview URL: dashboard loads, toggles work, POST a test call to <preview>/api/vaani-webhook
vercel --prod # only after the preview checks out
vercel env add WEBHOOK_SECRET production
vercel env add GEMINI_API_KEY production
vercel env add TELEGRAM_BOT_TOKEN production
vercel env add TELEGRAM_CHAT_ID production
vercel env add UPSTASH_REDIS_REST_URL production
vercel env add UPSTASH_REDIS_REST_TOKEN production
vercel --prod # redeploy so the env vars take effect
Out of scope for this build. Both could feed the same pipeline: a WhatsApp Business API webhook or the website form handler would post {callerName, phone, transcript: <message text>} to a sibling endpoint that calls processCall from lib/process.js, so scoring, pricing, Telegram and the dashboard are reused. A channel field would be added to records and KPIs.
policy/rubric.json holds the numbers from Nikhil's qualified.md, services.md and pricing.md. If those files change, change this one to match.VOICE_COST_PER_MIN and LLM_COST_PER_CALL with real Vaani and Gemini pricing.lib/demo.js are synthetic and are marked DEMO DATA everywhere.| Layer | Command | What it covers |
|---|---|---|
| Unit | npm run test:unit | rubric, pricing, guardrails, cost, extraction, Gemini key rotation, Telegram, webhook, calls and stats handlers |
| Regression | npm run test:regression | 7 fixed calls (test/fixtures/calls.json) must keep the reviewed outcomes in test/fixtures/golden.json. Update with node scripts/make-golden.js only after reviewing a change |
| Smoke | npm run test:smoke | starts next start (building first if needed) and hits the dashboard, a call page and every API route once |
| End to end (Selenium) | npm run test:e2e | 12 browser tests of the dashboard against next start (Chrome, headless). Needs pip install selenium. Set BASE_URL to test a deployed copy |
| Everything | npm run check | prettier check, eslint, then all tests except Selenium |
Every dashboard element has a data-testid. <body> gets data-ready="true" after hydration and loses it while a toggle or refresh is re-rendering on the server, so Selenium waits are explicit.
Tests clear all integration env vars first and block the network, so they never call Vaani, Gemini, Telegram or Upstash.
Format with npm run format, lint with npm run lint.