ai: Settings → AI (local endpoints only, with tests), the AI stack, voicemail transcripts
ci / check (push) Successful in 1m0s
ci / images (push) Successful in 26s

This commit is contained in:
iamdoubz committed 2026-10-21 18:37:13 -05:00
1 parent 274242ce32
commit a26a5ca740
25 files changed
+4889 -5

No files matched your search

+20
View File
@@ -9,6 +9,17 @@ const range = (from: number, to: number) =>
.refine(([a, b]) => a <= b, 'range start must be <= end')
.default([from, to]);
/** An OpenAI-style API on this server or the local network (apps/api/src/ai/client.ts checks). */
export const AiEndpointSchema = z.object({
url: z.url({ protocol: /^https?$/ }),
model: z.string().trim().min(1).max(200),
});
export const AiTtsEndpointSchema = AiEndpointSchema.extend({
voice: z.string().trim().min(1).max(100),
});
export type AiEndpoint = z.infer<typeof AiEndpointSchema>;
export type AiTtsEndpoint = z.infer<typeof AiTtsEndpointSchema>;
export const SettingsSchemas = {
'general.companyName': z.string().trim().min(1).max(100).default('My Company'),
// The api replaces this default with env TZ (services/settings.ts).
@@ -84,6 +95,11 @@ export const SettingsSchemas = {
'provisioning.lanOnly': z.boolean().default(false),
'provisioning.enabled': z.boolean().default(true),
'system.restartRequired': z.boolean().default(false),
// Local AI (spec 10). The api replaces the null defaults with AI_* env values (services/settings.ts).
'ai.llm': AiEndpointSchema.nullable().default(null),
'ai.stt': AiEndpointSchema.nullable().default(null),
'ai.tts': AiTtsEndpointSchema.nullable().default(null),
'ai.voicemailTranscripts': z.boolean().default(false),
// Not in 02 §3's table but used by the generator (03 §3).
'system.transportHash': z.string().nullable().default(null),
};
@@ -109,6 +125,10 @@ export type SettingsDto = {
smtp: (Omit<SmtpInput, 'password'> & { hasPassword: boolean }) | null;
};
/** POST /api/ai/test: one endpoint tried with a tiny request. `audio`: the TTS test, a data: URL. */
export type AiTestResult =
{ ok: true; ms: number; detail: string; audio?: string } | { ok: false; error: string };
/** GET /api/system/warnings: shown as the dashboard banner (05 §2). */
export type Warning = { code: string; message: string; link: string };
+2
View File
@@ -16,4 +16,6 @@ export type VoicemailDto = {
callerName: string | null;
durationS: number;
receivedAt: string;
/** Speech to text (Settings → AI); null when off, failed, or not done yet. */
transcript: string | null;
};