Lalabase
티켓·문서·근무시간·고객대화를 한 곳에 모아 KI로 검색, 소프트웨어 기업 고객 프로젝트용, 오픈소스로 자체 서버·독일 클라우드에 배포
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An AI voice agent on Vaani answers every incoming call to Aangan Studio, day or night. This repo is
everything that happens after the call: a webhook receives the finished call, a pipeline extracts and
qualifies the enquiry, designers are emailed and claim leads, and Nikhil gets a dashboard of what the
system costs and what it generates.
Scope is incoming phone calls only. WhatsApp and the web form are not built.
Decisions already made live in CLAUDE.md. Source material is in source/.README 전문 보기 ↗An AI voice agent on Vaani answers every incoming call to Aangan Studio, day or night. This repo is everything that happens after the call: a webhook receives the finished call, a pipeline extracts and qualifies the enquiry, designers are emailed and claim leads, and Nikhil gets a dashboard of what the system costs and what it generates.
Scope is incoming phone calls only. WhatsApp and the web form are not built.
Decisions already made live in CLAUDE.md. Source material is in source/.
source/pricing.md is
reference only and is never imported by app code or copied into the voice-agent pack.is_historical = true), never mixed into live metrics..env.local. .env.example lists names only.Next.js (App Router, TypeScript) on Vercel · Supabase Postgres · Gemini Flash · Resend · GitHub. INR formatting, Asia/Kolkata time, working hours 10:00 to 19:00 IST.
npm install
cp .env.example .env.local # then fill in values; never commit this file
npm run dev
Migrations are in supabase/migrations/, placeholder seed data in supabase/seed.sql.
Run them in order in the Supabase SQL editor (or with the Supabase CLI: supabase db push).
All tables have row level security on with no policies, so only the server (service-role key) can touch data.
npm test # unit tests; migration tests run the SQL in an in-process Postgres (PGlite)
npm run typecheck
npm run lint
npm run build
crm.objects.contacts.read/write, crm.objects.deals.read/write, crm.objects.owners.read,
crm.schemas.deals.read/write, crm.schemas.contacts.read. A missing scope returns a 403 whose message names it.
The service key is used exactly like the old private-app token (sent as a Bearer token); verified on a free account..env.local as HUBSPOT_ACCESS_TOKEN (and the numeric hub id as HUBSPOT_PORTAL_ID). Never paste it
anywhere else, and rotate it immediately if it is ever shown in a chat or screenshot.npm run hubspot:setup # dry run, read-only
npm run hubspot:setup -- --apply --adopt-default # free plan: reuse the EMPTY default pipeline
The setup is idempotent, never deletes anything, and refuses to rewrite a pipeline that already has deals.
POST /api/webhooks/vaani verifies the signature, then for each call: stores it (idempotent on the call id), removes
caller identifiers, asks Gemini to fill a structured record, applies Nikhil's rubric in plain code
(src/lib/pipeline/rubric.ts, unit-tested), and queues the HubSpot write (contact, deal, note, tasks) in an outbox with
retries so a HubSpot outage never loses a call.
Outcomes: qualified, qualified with flags, declined (with reason code, kept for review), deferred (with revisit date), escalation (existing-client complaint or lost follow-up), incomplete (missed or dropped call).
Assumptions to replace: Vaani's real payload and signature format have not been seen. The adapter
(src/lib/vaani/adapter.ts) and signature check (src/lib/vaani/signature.ts) are written against an invented sample in
fixtures/vaani/FAKE-sample-call.json.
Privacy limit: phone numbers, emails and the caller's own name are removed before Gemini. Other people's names (a referrer, a designer) are kept, because the referral source is a field we need.
Runs the 20 historical phone enquiries through the real pipeline with no phone and a mock HubSpot, and compares each with the intended outcome. Calls are split into 10 prompt examples and 10 held-out calls.
npm run replay # offline, hand-labelled extractions: tests the rules and wiring
npm run replay -- --extractor=gemini # BILLED: runs the real model (needs GEMINI_API_KEY and GEMINI_MODEL in .env.local)
The offline run does not measure Gemini's accuracy (the labels were written by hand from the same transcripts).
Only --extractor=gemini does. A page for the Replay Lab arrives with the console in Phase 4.
voice-agent/; follow voice-agent/SETUP.md)POST /api/cron/tick (secret required) runs every minute from a Supabase pg_cron job named aangan-tick: re-runs stuck calls,
pushes queued writes to HubSpot, sends due emails, auto-assigns. To stop it: select cron.unschedule('aangan-tick');npm run designers:sync -- --apply links real HubSpot users as designers. npm run phase3:smoke and npm run email:test are live tests.Sign in at /login with DASHBOARD_PASSWORD (set it in .env.local and in Vercel; with no password set, nobody gets in). The public page / stays
the historical-replay dashboard; the console shows live calls only and is private because it holds caller details.
/calls/<id>, which redirects to the signed-in transcript page. Access is checked three times: a proxy before anything renders, the layout, and every data read and action.voice-agent/ has everything to paste into Vaani: prompt.md (the system prompt, with five examples adapted from the
prompt-example half of the historical calls), greeting.md, five knowledge files, and SETUP.md (step by step, with eight test calls).
tests/voice-agent.test.ts guards it: no figure from the internal pricing guide, no currency symbols, the exact approved pricing reply,
the AI-and-recording greeting, one question at a time, every must-have field, the 15-minute complaint rule, and that no held-out call is used as an example.
Four calls show the whole system. There is no inbound phone number yet, so every call starts from Vaani > Agents > aangan-test > Start Test > Audio, which rings the tester's own phone. Wait about two minutes after each call, then look in three places: the dashboard (the Vercel link), HubSpot > Deals (pipeline "Aangan Enquiries"), and the designer's inbox.
Before you start: the designer must be on duty (designers.on_duty), and the every-minute aangan-tick job must be running.
Calls made outside 10:00-19:00 IST are held and their email is sent at 10:00 IST, which is the after-hours rule working, not a fault.
Say: "I want interior design for my 3BHK in Baner, about 1,150 sq ft, whole home. I'm the owner and I'd like it done by March."
Give normal details (for example Wakad, 900 sq ft), then ask "How much will it cost?" twice.
price_asked. The transcript contains no figure.Say: "I'm in Nashik" (anywhere outside Pune and PCMC).
Say: "My designer hasn't replied in five days."
npm run replay runs the 20 labelled historical calls (10 used as prompt examples, 10 held out) through the pipeline and prints the match rate.
These are historical, human-handled enquiries, so they are kept out of the live metrics and out of HubSpot.
npm run replay -- --extractor=gemini measures Gemini's real accuracy (last run: 20/20, 10/10 on the held-out half).
The Phase 4 console (declined-review queue, sync health, designer on-duty toggle) is not built. Gemini is on the free tier and Resend uses its test sender, so use test data only until both are upgraded.