Worktree ai assistant#410
Open
Martinxmaina wants to merge 8 commits into
Open
Conversation
LLM-wiki RAG knowledge base, autonomous reply with confidence gating, human-in-the-loop escalation, editable prompts. Anthropic-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…calation Adds the customer-facing AI assistant engine (spec §1–§7, §12–§14): - migration 027: ai_assistant_config, knowledge_base_entries, ai_reply_log, and conversations.ai_handling/ai_escalated_at/ ai_escalation_reason (account-scoped, RLS, is_account_member gating) - src/lib/ai/: pure prompt/guardrails/decide (+ tests), anthropic forced-tool wrapper, config/knowledge-base/admin-client data access, send (sender_type='bot') + escalate, and the maybeReplyToInbound orchestrator (+ mocked tests) - webhook: fire-and-forget AI dispatch gated on !flowConsumed - send route: manual agent reply sets ai_handling=false (human takeover) - types + ANTHROPIC_API_KEY / unpdf deps Fail-safe to human on any doubt/error; autonomous send only when the model self-reports confidence and guardrails + daily cap pass. typecheck/lint/test(526)/build all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Admin-gated (requireRole('admin') + canEditSettings + RLS), rate-limited,
input-bounded dashboard endpoints (spec §10):
- GET/PUT /api/ai/config (seeds default row; returns apiKeyConfigured
boolean, never the key)
- GET/POST /api/ai/knowledge ; PATCH/DELETE /api/ai/knowledge/[id]
- POST /api/ai/knowledge/upload (.txt/.md direct, PDF via unpdf,
runtime=nodejs, 10MB cap, 422 on extraction failure)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…hand-off UX UI layer for the assistant (spec §8, §9): - Settings → "AI Assistant": enable toggle, system-prompt editor, handoff message, escalation-keyword chips, persona (business name + logo upload via the existing account storage helper), model dropdown, daily reply cap; admin+ gated (RequireRole). Shows an "API key not configured" notice from the server-reported boolean. - KnowledgeBaseManager: CRUD + enable toggle + file import (.txt/.md/PDF), with a token-size meter vs a 150k soft budget (the RAG-upgrade signal). - Inbox: "🙋 Needs human" badge on escalated conversations, "AI" tag on bot-sent messages, and Take over / Hand back to AI header controls (reuse the existing conversations.update path; optimistic + realtime). typecheck + lint(0 errors) + test(526) + build all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial review (security + correctness) before PR surfaced one
blocking bug and several hardening items:
- CRITICAL: loadHistory included the just-inserted inbound row, which
buildMessages then appended again → two consecutive `user` turns →
Anthropic 400 → every reply silently escalated (AI never answered).
Exclude the trigger message (.neq('id', messageId)); add a regression
test that exercises real conversation history (the gap that hid it).
- Account-scope the orchestrator's conversation fetch (defence in depth
on the RLS-bypassing service-role client).
- Clear ai_escalated_at / ai_escalation_reason on a human reply so the
"Needs human" badge drops once handled (send route).
- Validate logo_url is http(s) only (reject javascript:/data:).
- Reject oversized uploads via Content-Length before buffering the body.
Also: normalize the new src/lib/ai + /api/ai + AI settings files to the
repo .prettierrc; document ANTHROPIC_API_KEY / AI_DEFAULT_MODEL in
.env.local.example and add a CI placeholder.
typecheck + lint(0 errors) + test(527) + build all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
KES, UGX, TZS, RWF, BIF, SSP, ETB, SOS, CDF, DJF — all valid ISO-4217 so Intl.NumberFormat renders them. Extends the single CURRENCIES list; no other change needed (deals picker, dashboard, pipelines all read it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- migration 028: accounts.logo_url (name already exists; RLS unchanged — accounts_update already gates admin+) - sidebar brand row now shows the account logo + name (falls back to the default icon/name) - Settings → Branding tab (admin+) to edit name + logo, saving via the existing PATCH /api/account (extended to accept logo_url, http(s)-only); refreshProfile() updates the sidebar live - useAuth/Account carry logo_url Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fetchProfile join selected accounts.logo_url explicitly, so on any DB where migration 028 hasn't run yet PostgREST 400s the whole profile fetch — breaking login/profile load. Select accounts(*) instead so the column is picked up when present and simply absent otherwise, matching the existing pre-021 defensiveness. Logo lights up once 028 is applied. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What changed
Test plan
npm run typecheckclean.npm run lint— no new errors beyond the pre-existing backlog.npm run buildsucceeds.Related