Skip to content

Worktree ai assistant#410

Open
Martinxmaina wants to merge 8 commits into
ArnasDon:mainfrom
Martinxmaina:worktree-ai-assistant
Open

Worktree ai assistant#410
Martinxmaina wants to merge 8 commits into
ArnasDon:mainfrom
Martinxmaina:worktree-ai-assistant

Conversation

@Martinxmaina

Copy link
Copy Markdown

Summary

What changed

Test plan

  • npm run typecheck clean.
  • npm run lint — no new errors beyond the pre-existing backlog.
  • npm run build succeeds.
  • Feature / fix manually exercised in the browser (or the reason it can't be).

Related

Martinxmaina and others added 8 commits June 25, 2026 18:27
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>
@Martinxmaina
Martinxmaina requested a review from ArnasDon as a code owner July 19, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant