mirror of
https://github.com/temetro/temetro.git
synced 2026-08-31 21:08:38 +00:00
backend: AI chat agent with Veil PHI safeguard (providers, /chat, import)
Real LLM chat replacing the mock, backend-centric per the plan: - Multi-provider API-key mode (OpenAI / Anthropic / Gemini via the AI SDK) plus local Ollama (OpenAI-compatible endpoint). Provider is derived from the picked model id; the matching stored key is used. New user_ai_settings table holds per-user config with provider API keys encrypted at rest (AES-256-GCM, src/lib/crypto.ts, keyed by AI_CREDENTIALS_KEY). - POST /api/ai/config (get/put, secrets never returned), POST /api/ai/test (Ollama ping / key presence), POST /api/ai/import (approved migration commit, re-validated server-side, reuses the audited patient service). - POST /api/chat: streamText agent with tools (getPatient, getPatientLabs, searchPatients, previewImport). Real record data streams to the clinician as custom data parts (cards) while the model sees only Veil-redacted results. - Veil (src/services/ai/veil.ts): de-identifies patient identifiers to tokens before external calls, resolves tokens on tool args, and rehydrates the final answer. Bypassed for local Ollama. External mode runs non-streamed so the rehydrated text is correct. Every call is audited (provider + Veil level). - Shared role-scoping helpers extracted to src/lib/role-scope.ts (reused by the patient routes and chat tools so visibility rules match). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
CREATE TABLE "user_ai_settings" (
|
||||
"user_id" text PRIMARY KEY NOT NULL,
|
||||
"mode" text DEFAULT 'local' NOT NULL,
|
||||
"provider" text DEFAULT 'anthropic' NOT NULL,
|
||||
"ollama_base_url" text DEFAULT 'http://localhost:11434' NOT NULL,
|
||||
"ollama_model" text DEFAULT 'llama3.1' NOT NULL,
|
||||
"default_model" text DEFAULT 'claude-sonnet-4-6' NOT NULL,
|
||||
"default_effort" text DEFAULT 'medium' NOT NULL,
|
||||
"veil_level" text DEFAULT 'full' NOT NULL,
|
||||
"api_keys_cipher" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "user_ai_settings" ADD CONSTRAINT "user_ai_settings_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -92,6 +92,13 @@
|
||||
"when": 1781279151289,
|
||||
"tag": "0012_wonderful_terrax",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "7",
|
||||
"when": 1781364502603,
|
||||
"tag": "0013_strange_medusa",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user