@umituz/web-ai 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/{ABTesting-DDqNhHtP.d.ts → AIErrors-B2ogd1PB.d.ts} +14 -1
  2. package/dist/{ABTesting-DWBtKTMQ.d.cts → AIErrors-C5EasV_c.d.cts} +14 -1
  3. package/dist/{ProviderConfig-a55tLhWT.d.cts → ProviderConfig-DIFa9nmG.d.cts} +10 -1
  4. package/dist/{ProviderConfig-a55tLhWT.d.ts → ProviderConfig-DIFa9nmG.d.ts} +10 -1
  5. package/dist/chat/index.cjs +114 -23
  6. package/dist/chat/index.cjs.map +1 -1
  7. package/dist/chat/index.d.cts +4 -4
  8. package/dist/chat/index.d.ts +4 -4
  9. package/dist/chat/index.js +114 -23
  10. package/dist/chat/index.js.map +1 -1
  11. package/dist/{chat.service-DBKq9I2c.d.cts → chat.service-CL1qtYxe.d.cts} +7 -7
  12. package/dist/{chat.service-RQn8UTXD.d.ts → chat.service-q05GnhEm.d.ts} +7 -7
  13. package/dist/content/index.cjs +393 -186
  14. package/dist/content/index.cjs.map +1 -1
  15. package/dist/content/index.d.cts +7 -8
  16. package/dist/content/index.d.ts +7 -8
  17. package/dist/content/index.js +393 -186
  18. package/dist/content/index.js.map +1 -1
  19. package/dist/core/index.cjs +112 -15
  20. package/dist/core/index.cjs.map +1 -1
  21. package/dist/core/index.d.cts +5 -33
  22. package/dist/core/index.d.ts +5 -33
  23. package/dist/core/index.js +111 -16
  24. package/dist/core/index.js.map +1 -1
  25. package/dist/{create-ai-DGZFBOA1.d.cts → create-ai-DOI9jD3v.d.cts} +4 -21
  26. package/dist/{create-ai-BhNaz86i.d.ts → create-ai-DXEoke8-.d.ts} +4 -21
  27. package/dist/hooks/index.cjs +359 -169
  28. package/dist/hooks/index.cjs.map +1 -1
  29. package/dist/hooks/index.d.cts +6 -6
  30. package/dist/hooks/index.d.ts +6 -6
  31. package/dist/hooks/index.js +359 -169
  32. package/dist/hooks/index.js.map +1 -1
  33. package/dist/index-DIHz8_OJ.d.ts +48 -0
  34. package/dist/index-DKHNcMbl.d.cts +48 -0
  35. package/dist/index.cjs +245 -94
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +6 -6
  38. package/dist/index.d.ts +6 -6
  39. package/dist/index.js +244 -95
  40. package/dist/index.js.map +1 -1
  41. package/dist/{provider.factory-COsnprLH.d.cts → provider.factory-BxsfK4WW.d.cts} +1 -1
  42. package/dist/{provider.factory-CpWFyjbw.d.ts → provider.factory-DfDfk0dK.d.ts} +1 -1
  43. package/dist/providers/index.cjs +281 -124
  44. package/dist/providers/index.cjs.map +1 -1
  45. package/dist/providers/index.d.cts +11 -12
  46. package/dist/providers/index.d.ts +11 -12
  47. package/dist/providers/index.js +281 -124
  48. package/dist/providers/index.js.map +1 -1
  49. package/dist/wizard/index.d.cts +1 -1
  50. package/dist/wizard/index.d.ts +1 -1
  51. package/package.json +4 -1
  52. package/dist/index-DjX9ZKuM.d.cts +0 -14
  53. package/dist/index-DxLvE588.d.ts +0 -14
@@ -1,15 +1,91 @@
1
+ // src/core/errors/ai-error-types.ts
2
+ var AIErrorType = /* @__PURE__ */ ((AIErrorType2) => {
3
+ AIErrorType2["INVALID_API_KEY"] = "INVALID_API_KEY";
4
+ AIErrorType2["MISSING_CONFIG"] = "MISSING_CONFIG";
5
+ AIErrorType2["NETWORK_ERROR"] = "NETWORK_ERROR";
6
+ AIErrorType2["ABORT_ERROR"] = "ABORT_ERROR";
7
+ AIErrorType2["RATE_LIMIT_ERROR"] = "RATE_LIMIT_ERROR";
8
+ AIErrorType2["SERVER_ERROR"] = "SERVER_ERROR";
9
+ AIErrorType2["CLIENT_ERROR"] = "CLIENT_ERROR";
10
+ AIErrorType2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
11
+ return AIErrorType2;
12
+ })(AIErrorType || {});
13
+
1
14
  // src/core/errors/ai-error.ts
2
- var AIError = class extends Error {
15
+ var KNOWN_ERROR_TYPES = new Set(Object.values(AIErrorType));
16
+ function mapCodeToType(code) {
17
+ switch (code) {
18
+ case "VALIDATION_ERROR":
19
+ case "CLIENT_ERROR":
20
+ return "CLIENT_ERROR" /* CLIENT_ERROR */;
21
+ case "INVALID_API_KEY":
22
+ return "INVALID_API_KEY" /* INVALID_API_KEY */;
23
+ case "MISSING_CONFIG":
24
+ case "PROVIDER_UNAVAILABLE":
25
+ return "MISSING_CONFIG" /* MISSING_CONFIG */;
26
+ case "PROVIDER_QUOTA_EXHAUSTED":
27
+ case "RATE_LIMIT_ERROR":
28
+ return "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */;
29
+ case "NETWORK_ERROR":
30
+ case "TIMEOUT":
31
+ return "NETWORK_ERROR" /* NETWORK_ERROR */;
32
+ case "ABORT_ERROR":
33
+ case "ABORTED":
34
+ return "ABORT_ERROR" /* ABORT_ERROR */;
35
+ case "SERVER_ERROR":
36
+ case "PROVIDER_ERROR":
37
+ case "NO_RESULT":
38
+ return "SERVER_ERROR" /* SERVER_ERROR */;
39
+ default:
40
+ return "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
41
+ }
42
+ }
43
+ function mapMessageToCode(message, fallback = "UNKNOWN") {
44
+ const lower = message.toLowerCase();
45
+ if (lower.includes("validation")) return "VALIDATION_ERROR";
46
+ if (lower.includes("quota")) return "PROVIDER_QUOTA_EXHAUSTED";
47
+ if (lower.includes("unavailable")) return "PROVIDER_UNAVAILABLE";
48
+ if (lower.includes("timeout") || lower.includes("aborted")) {
49
+ return lower.includes("aborted") ? "ABORTED" : "TIMEOUT";
50
+ }
51
+ if (lower.includes("parse") || lower.includes("json")) return "PARSE_ERROR";
52
+ if (lower.includes("no result")) return "NO_RESULT";
53
+ if (lower.includes("network") || lower.includes("fetch")) return "NETWORK_ERROR";
54
+ return fallback;
55
+ }
56
+ var AIError = class _AIError extends Error {
3
57
  type;
58
+ code;
4
59
  cause;
5
60
  metadata;
6
- constructor(type, message, cause, metadata = {}) {
7
- super(message);
61
+ constructor(typeOrMessage, messageOrCode, cause, metadata = {}) {
62
+ let effectiveType;
63
+ let effectiveMessage;
64
+ let effectiveCode;
65
+ if (KNOWN_ERROR_TYPES.has(typeOrMessage)) {
66
+ effectiveType = typeOrMessage;
67
+ effectiveMessage = messageOrCode ?? "";
68
+ effectiveCode = effectiveType;
69
+ } else {
70
+ effectiveMessage = typeOrMessage;
71
+ effectiveCode = messageOrCode ?? "UNKNOWN";
72
+ effectiveType = mapCodeToType(effectiveCode);
73
+ }
74
+ super(effectiveMessage);
8
75
  this.name = "AIError";
9
- this.type = type;
76
+ this.type = effectiveType;
77
+ this.code = effectiveCode;
10
78
  this.cause = cause;
11
79
  this.metadata = metadata;
12
80
  }
81
+ static from(error, fallbackCode = "UNKNOWN") {
82
+ if (error instanceof _AIError) return error;
83
+ if (error instanceof Error) {
84
+ const code = mapMessageToCode(error.message, fallbackCode);
85
+ return new _AIError(error.message, code, error);
86
+ }
87
+ return new _AIError(String(error), fallbackCode, error);
88
+ }
13
89
  toString() {
14
90
  const statusPart = typeof this.metadata.status === "number" ? ` (HTTP ${this.metadata.status})` : "";
15
91
  return `${this.name} [${this.type}]: ${this.message}${statusPart}`;
@@ -18,6 +94,7 @@ var AIError = class extends Error {
18
94
  return {
19
95
  name: this.name,
20
96
  type: this.type,
97
+ code: this.code,
21
98
  message: this.message,
22
99
  metadata: this.metadata
23
100
  };
@@ -118,12 +195,16 @@ var ProviderFactory = class {
118
195
  let wake = null;
119
196
  let finished = false;
120
197
  let failure;
198
+ const controller = new AbortController();
199
+ const onAbort = () => controller.abort();
200
+ request.signal?.addEventListener("abort", onAbort);
201
+ const effectiveRequest = { ...request, signal: controller.signal };
121
202
  const notify = () => {
122
203
  const resolve = wake;
123
204
  wake = null;
124
205
  resolve?.();
125
206
  };
126
- const completion = this.chatStream(request, {
207
+ const completion = this.chatStream(effectiveRequest, {
127
208
  onChunk: (chunk) => {
128
209
  queue.push(chunk);
129
210
  notify();
@@ -139,18 +220,23 @@ var ProviderFactory = class {
139
220
  notify();
140
221
  }
141
222
  );
142
- while (!finished || queue.length > 0) {
143
- if (queue.length === 0 && !finished) {
144
- await new Promise((resolve) => {
145
- wake = resolve;
146
- });
147
- }
148
- while (queue.length > 0) {
149
- yield queue.shift();
223
+ try {
224
+ while (!finished || queue.length > 0) {
225
+ if (queue.length === 0 && !finished) {
226
+ await new Promise((resolve) => {
227
+ wake = resolve;
228
+ });
229
+ }
230
+ while (queue.length > 0) {
231
+ yield queue.shift();
232
+ }
233
+ if (failure) throw failure;
150
234
  }
151
- if (failure) throw failure;
235
+ await completion;
236
+ } finally {
237
+ controller.abort();
238
+ request.signal?.removeEventListener("abort", onAbort);
152
239
  }
153
- await completion;
154
240
  }
155
241
  async generateJson(request) {
156
242
  const effective = request.model || request.tier ? request : { ...request, tier: this.defaultTier };
@@ -420,9 +506,12 @@ var ChatService = class {
420
506
  };
421
507
  }
422
508
  async getConversations() {
509
+ if (this.storage && "getConversations" in this.storage && typeof this.storage.getConversations === "function") {
510
+ return this.storage.getConversations();
511
+ }
423
512
  return [];
424
513
  }
425
- async sendMessage(input) {
514
+ async sendMessage(input, signal) {
426
515
  const userMessage = {
427
516
  ...messageFormatter.toChatMessage(input.text, "user"),
428
517
  type: input.type ?? "text",
@@ -431,13 +520,14 @@ var ChatService = class {
431
520
  const aiResponse = await this.generateAIResponse(
432
521
  input.companionId,
433
522
  input.text,
434
- []
523
+ [],
524
+ signal
435
525
  );
436
526
  return { userMessage, aiResponse };
437
527
  }
438
- async generateAIResponse(companionId, userMessage, context = []) {
528
+ async generateAIResponse(companionId, userMessage, context = [], signal) {
439
529
  const result = await this.run({
440
- ...this.buildRequest(userMessage, context)
530
+ ...this.buildRequest(userMessage, context, signal)
441
531
  });
442
532
  return {
443
533
  ...messageFormatter.toChatMessage(result.text, "assistant"),
@@ -453,12 +543,12 @@ var ChatService = class {
453
543
  }
454
544
  };
455
545
  }
456
- async generateStreamingResponse(userMessage, context, onChunk) {
457
- const request = this.buildRequest(userMessage, context);
546
+ async generateStreamingResponse(userMessage, context, onChunk, signal) {
547
+ const request = this.buildRequest(userMessage, context, signal);
458
548
  const result = await this.runStream(request, { onChunk });
459
549
  return result.text;
460
550
  }
461
- buildRequest(userMessage, context) {
551
+ buildRequest(userMessage, context, signal) {
462
552
  const messages = messageFormatter.toCoreMessages(context);
463
553
  messages.push({ role: "user", content: userMessage });
464
554
  return {
@@ -467,7 +557,8 @@ var ChatService = class {
467
557
  model: this.config.model,
468
558
  tier: this.config.tier,
469
559
  temperature: this.config.temperature,
470
- maxTokens: this.config.maxTokens
560
+ maxTokens: this.config.maxTokens,
561
+ ...signal !== void 0 ? { signal } : {}
471
562
  };
472
563
  }
473
564
  resolveSystemPrompt() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/errors/ai-error.ts","../../src/providers/base/provider.types.ts","../../src/content/domain/limits/ProviderTimingConfig.ts","../../src/providers/factory/provider.factory.ts","../../src/core/calculations/random-base36-suffix.ts","../../src/core/constants/identifier.constants.ts","../../src/chat/utils/chat-id-generator.ts","../../src/chat/utils/message-formatter.ts","../../src/chat/utils/prompt-strategy.ts","../../src/chat/services/chat.service.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["\nimport { AIErrorType } from \"./ai-error-types\";\n\nexport interface AIErrorMetadata {\n readonly status?: number;\n readonly url?: string;\n readonly [key: string]: unknown;\n}\n\nexport class AIError extends Error {\n public readonly type: AIErrorType;\n public readonly cause?: Error;\n public readonly metadata: AIErrorMetadata;\n\n constructor(\n type: AIErrorType,\n message: string,\n cause?: Error,\n metadata: AIErrorMetadata = {},\n ) {\n super(message);\n this.name = \"AIError\";\n this.type = type;\n this.cause = cause;\n this.metadata = metadata;\n }\n\n override toString(): string {\n const statusPart =\n typeof this.metadata.status === \"number\" ? ` (HTTP ${this.metadata.status})` : \"\";\n return `${this.name} [${this.type}]: ${this.message}${statusPart}`;\n }\n\n toJSON(): {\n name: string;\n type: AIErrorType;\n message: string;\n metadata: AIErrorMetadata;\n } {\n return {\n name: this.name,\n type: this.type,\n message: this.message,\n metadata: this.metadata,\n };\n }\n}\n","\nimport type {\n GenerationResult,\n ProviderHealth,\n StreamCallbacks,\n StructuredGeneration,\n StructuredTextRequest,\n TextRequest,\n TextTier,\n} from \"../../core/types\";\nimport type {\n GeneratedContent,\n ImageGenerationRequest,\n ImageToVideoRequest,\n TextGenerationRequest,\n VideoGenerationRequest,\n VideoToVideoRequest,\n} from \"../../content/domain/config/ProviderConfig\";\n\n/**\n * What a provider can serve. Replaces the old single `'multimodal'` type flag:\n * a provider declares exactly the capabilities it implements, and the factory\n * walks providers by capability when routing or failing over.\n */\nexport type ProviderCapability = \"text\" | \"image\" | \"video\";\n\n/** Cost estimation input — any generation request shape the fleet knows. */\nexport type CostEstimateRequest =\n | TextGenerationRequest\n | ImageGenerationRequest\n | VideoGenerationRequest;\n\nexport interface IProviderBase {\n readonly id: string;\n readonly name: string;\n readonly capabilities: ReadonlyArray<ProviderCapability>;\n healthCheck(): Promise<ProviderHealth>;\n estimateCost(request: CostEstimateRequest): Promise<number>;\n}\n\n/**\n * A provider that can turn conversations into text. This is the surface the\n * factory's `chat`/`chatStream` walk; model choice per quality tier is the\n * provider's own business (each maps neutral tiers onto its catalogue).\n */\nexport interface ITextProvider extends IProviderBase {\n generate(request: TextRequest): Promise<GenerationResult>;\n generateStructured<T>(request: StructuredTextRequest): Promise<StructuredGeneration<T>>;\n stream(request: TextRequest, callbacks: StreamCallbacks): Promise<GenerationResult>;\n resolveModel(tier: TextTier): string;\n}\n\n/**\n * A provider that generates media. Kept as B's media surface — image/video\n * request and result shapes are already provider-neutral.\n */\nexport interface IMediaProvider extends IProviderBase {\n generateImage(request: ImageGenerationRequest): Promise<GeneratedContent>;\n generateVideo(request: VideoGenerationRequest): Promise<GeneratedContent>;\n imageToVideo(request: ImageToVideoRequest): Promise<GeneratedContent>;\n videoToVideo(request: VideoToVideoRequest): Promise<GeneratedContent>;\n}\n\nexport type AnyProvider = ITextProvider | IMediaProvider;\n\nexport function isTextProvider(provider: AnyProvider): provider is ITextProvider {\n return provider.capabilities.includes(\"text\");\n}\n\nexport function isMediaProvider(provider: AnyProvider): provider is IMediaProvider {\n return provider.capabilities.includes(\"image\") || provider.capabilities.includes(\"video\");\n}\n","\nexport const ProviderTimingConfig = {\n DEFAULT_TIMEOUT_MS: 30_000,\n DEFAULT_RETRY_ATTEMPTS: 3,\n\n FAL_TIMEOUT_MS: 120_000,\n FAL_RETRY_ATTEMPTS: 2,\n\n GEMINI_TIMEOUT_MS: 60_000,\n GEMINI_RETRY_ATTEMPTS: 3,\n\n GROQ_TIMEOUT_MS: 30_000,\n GROQ_RETRY_ATTEMPTS: 3,\n\n HEALTH_CHECK_TTL_MS: 5 * 60 * 1000,\n\n RETRY_BACKOFF_BASE_MS: 1_000,\n} as const;\n","\nimport type {\n GenerationResult,\n ProviderHealth,\n StreamCallbacks,\n StructuredGeneration,\n StructuredTextRequest,\n TextRequest,\n TextTier,\n} from \"../../core/types\";\nimport { AIError, AIErrorType } from \"../../core/errors\";\nimport type {\n AnyProvider,\n IMediaProvider,\n ITextProvider,\n ProviderCapability,\n} from \"../base/provider.types\";\nimport { isTextProvider } from \"../base/provider.types\";\nimport type {\n GeneratedContent,\n ImageGenerationRequest,\n ImageToVideoRequest,\n VideoGenerationRequest,\n VideoToVideoRequest,\n} from \"../../content/domain/config/ProviderConfig\";\nimport type {\n ITextGenerator,\n TextGenerationOptions,\n} from \"../../content/domain/interfaces/ITextGenerator\";\nimport { ProviderTimingConfig } from \"../../content/domain/limits/ProviderTimingConfig\";\n\nexport interface ProviderFactoryConfig {\n /** Provider ids in preference order; unlisted providers follow in registration order. */\n priority?: ReadonlyArray<string>;\n fallbackEnabled?: boolean;\n /** Tier used when a request names neither a model nor a tier. */\n defaultTier?: TextTier;\n}\n\ninterface HealthCheckCache {\n health: ProviderHealth;\n timestamp: number;\n}\n\n/**\n * Composition-aware registry and router. Replaces both ancestors at once:\n * B's ProviderFactory (health TTL cache, priority fallback walk, media\n * dispatch) and A's singleton configureProvider (via createAI). Adds the\n * provider-neutral `chat`/`chatStream` text surface with full usage\n * propagation, and keeps B's ITextGenerator string facade so the ported\n * content services compile unchanged.\n */\nexport class ProviderFactory implements ITextGenerator {\n private readonly providers = new Map<string, AnyProvider>();\n private readonly healthCache = new Map<string, HealthCheckCache>();\n private readonly priority: ReadonlyArray<string>;\n private readonly fallbackEnabled: boolean;\n readonly defaultTier: TextTier;\n\n constructor(config: ProviderFactoryConfig = {}) {\n this.priority = config.priority ?? [];\n this.fallbackEnabled = config.fallbackEnabled ?? true;\n this.defaultTier = config.defaultTier ?? \"balanced\";\n }\n\n register(provider: AnyProvider): void {\n this.providers.set(provider.id, provider);\n }\n\n getProvider(id: string): AnyProvider | undefined {\n return this.providers.get(id);\n }\n\n getAllProviders(): AnyProvider[] {\n return Array.from(this.providers.values());\n }\n\n getByCapability(capability: ProviderCapability): AnyProvider[] {\n return this.getAllProviders().filter((provider) =>\n provider.capabilities.includes(capability),\n );\n }\n\n getTextProviders(): ITextProvider[] {\n return this.getAllProviders().filter(isTextProvider);\n }\n\n hasTextProvider(): boolean {\n return this.getByCapability(\"text\").length > 0;\n }\n\n /* ---------- neutral text surface ---------- */\n\n /**\n * Single-chat entry point: resolves a healthy text provider by priority,\n * injects the default tier when the request names neither model nor tier,\n * and walks the fallback chain on failure. Providers map tiers onto their\n * own models, so switching Groq→Anthropic is a config change.\n */\n async chat(request: TextRequest): Promise<GenerationResult> {\n const effective: TextRequest =\n request.model || request.tier ? request : { ...request, tier: this.defaultTier };\n return this.executeWithFallback(\"text\", (provider) =>\n (provider as ITextProvider).generate(effective),\n );\n }\n\n async chatStream(\n request: TextRequest,\n callbacks: StreamCallbacks,\n ): Promise<GenerationResult> {\n const effective: TextRequest =\n request.model || request.tier ? request : { ...request, tier: this.defaultTier };\n\n let lastError: unknown;\n // onError is withheld until every provider has failed — a successful\n // fallback would otherwise have already reported a spurious error.\n const attemptCallbacks: StreamCallbacks = {\n onChunk: callbacks.onChunk,\n onComplete: callbacks.onComplete,\n };\n\n const providers = this.getByCapability(\"text\");\n if (providers.length === 0) {\n throw this.noProviderError(\"text\");\n }\n\n const ordered = this.orderByPriority(providers);\n for (const provider of ordered) {\n if (!this.isProviderHealthy(provider.id)) continue;\n try {\n return await (provider as ITextProvider).stream(effective, attemptCallbacks);\n } catch (error) {\n lastError = error;\n this.markDegraded(provider.id);\n if (!this.fallbackEnabled) {\n callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n }\n\n const failure = new AIError(\n AIErrorType.SERVER_ERROR,\n `All providers failed for capability 'text'`,\n lastError instanceof Error ? lastError : undefined,\n );\n callbacks.onError?.(lastError instanceof Error ? lastError : failure);\n throw failure;\n }\n\n /** AsyncGenerator adapter over chatStream — A's familiar consumption shape. */\n async *streamText(request: TextRequest): AsyncGenerator<string> {\n const queue: string[] = [];\n let wake: (() => void) | null = null;\n let finished = false;\n let failure: unknown;\n\n const notify = (): void => {\n const resolve = wake;\n wake = null;\n resolve?.();\n };\n\n const completion = this.chatStream(request, {\n onChunk: (chunk) => {\n queue.push(chunk);\n notify();\n },\n }).then(\n () => {\n finished = true;\n notify();\n },\n (error) => {\n failure = error;\n finished = true;\n notify();\n },\n );\n\n while (!finished || queue.length > 0) {\n if (queue.length === 0 && !finished) {\n await new Promise<void>((resolve) => {\n wake = resolve;\n });\n }\n while (queue.length > 0) {\n yield queue.shift() as string;\n }\n if (failure) throw failure;\n }\n await completion;\n }\n\n async generateJson<T>(\n request: StructuredTextRequest,\n ): Promise<StructuredGeneration<T>> {\n const effective: StructuredTextRequest =\n request.model || request.tier ? request : { ...request, tier: this.defaultTier };\n return this.executeWithFallback(\"text\", (provider) =>\n (provider as ITextProvider).generateStructured<T>(effective),\n );\n }\n\n /* ---------- content-layer string facade (ITextGenerator) ---------- */\n\n async generateText(prompt: string, options: TextGenerationOptions = {}): Promise<string> {\n const result = await this.chat({\n messages: [{ role: \"user\", content: prompt }],\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n });\n return result.text;\n }\n\n generateTextStream(prompt: string, options: TextGenerationOptions = {}): AsyncGenerator<string> {\n return this.streamText({\n messages: [{ role: \"user\", content: prompt }],\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n });\n }\n\n /* ---------- media surface ---------- */\n\n async generateImage(request: ImageGenerationRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"image\", (provider) =>\n (provider as IMediaProvider).generateImage(request),\n );\n }\n\n async generateVideo(request: VideoGenerationRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"video\", (provider) =>\n (provider as IMediaProvider).generateVideo(request),\n );\n }\n\n async imageToVideo(request: ImageToVideoRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"video\", (provider) =>\n (provider as IMediaProvider).imageToVideo(request),\n );\n }\n\n async videoToVideo(request: VideoToVideoRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"video\", (provider) =>\n (provider as IMediaProvider).videoToVideo(request),\n );\n }\n\n /* ---------- health ---------- */\n\n async checkProviderHealth(providerId: string, forceRefresh = false): Promise<ProviderHealth> {\n const provider = this.providers.get(providerId);\n if (!provider) {\n return \"unavailable\";\n }\n\n const cached = this.healthCache.get(providerId);\n const now = Date.now();\n const ttl = ProviderTimingConfig.HEALTH_CHECK_TTL_MS;\n\n if (!forceRefresh && cached && now - cached.timestamp < ttl) {\n return cached.health;\n }\n\n try {\n const health = await provider.healthCheck();\n this.healthCache.set(providerId, { health, timestamp: now });\n return health;\n } catch {\n this.healthCache.set(providerId, { health: \"unavailable\", timestamp: now });\n return \"unavailable\";\n }\n }\n\n isProviderHealthy(providerId: string): boolean {\n const cached = this.healthCache.get(providerId);\n if (!cached) {\n return true;\n }\n return cached.health === \"healthy\" || cached.health === \"degraded\";\n }\n\n async refreshAllHealth(): Promise<void> {\n await Promise.all(\n Array.from(this.providers.keys()).map((id) => this.checkProviderHealth(id)),\n );\n }\n\n /* ---------- internals ---------- */\n\n private async executeWithFallback<T>(\n capability: ProviderCapability,\n fn: (provider: AnyProvider) => Promise<T>,\n ): Promise<T> {\n const providers = this.getByCapability(capability);\n if (providers.length === 0) {\n throw this.noProviderError(capability);\n }\n\n let lastError: unknown;\n for (const provider of this.orderByPriority(providers)) {\n if (!this.isProviderHealthy(provider.id)) {\n continue;\n }\n\n try {\n return await fn(provider);\n } catch (error) {\n lastError = error;\n this.markDegraded(provider.id);\n if (!this.fallbackEnabled) {\n throw error;\n }\n }\n }\n\n throw new AIError(\n AIErrorType.SERVER_ERROR,\n `All providers failed for capability '${capability}'`,\n lastError instanceof Error ? lastError : undefined,\n );\n }\n\n private orderByPriority(providers: AnyProvider[]): AnyProvider[] {\n if (this.priority.length === 0) {\n return providers;\n }\n const ordered: AnyProvider[] = [];\n for (const providerId of this.priority) {\n const provider = providers.find((p) => p.id === providerId);\n if (provider) ordered.push(provider);\n }\n for (const provider of providers) {\n if (!this.priority.includes(provider.id)) {\n ordered.push(provider);\n }\n }\n return ordered;\n }\n\n private markDegraded(providerId: string): void {\n const cached = this.healthCache.get(providerId);\n if (cached) {\n this.healthCache.set(providerId, { health: \"degraded\", timestamp: cached.timestamp });\n }\n }\n\n private noProviderError(capability: ProviderCapability): AIError {\n return new AIError(\n AIErrorType.MISSING_CONFIG,\n `No provider registered for capability '${capability}' — create one with createAI() and include its config block`,\n );\n }\n}\n","\nconst BASE_36_RADIX = 36;\nconst DECIMAL_OFFSET = 2;\n\nexport function generateRandomBase36Suffix(\n length: number,\n random: () => number = Math.random,\n): string {\n if (length <= 0) return \"\";\n const raw = random().toString(BASE_36_RADIX).slice(DECIMAL_OFFSET);\n if (raw.length >= length) return raw.slice(0, length);\n\n let result = raw;\n while (result.length < length) {\n result += random().toString(BASE_36_RADIX).slice(DECIMAL_OFFSET);\n }\n return result.slice(0, length);\n}\n","\nexport const MESSAGE_ID_PREFIX = \"msg-\" as const;\nexport const CHAT_MESSAGE_ID_SUFFIX_LENGTH = 9;\nexport const CACHE_KEY_TYPE_COMPLETION = \"completion\" as const;\nexport const CACHE_KEY_TYPE_CHAT = \"chat\" as const;\nexport const CACHE_KEY_TYPE_RESPONSE = \"response\" as const;\nexport const SYSTEM_PROMPT_CACHE_PREFIX = \"system-prompt\" as const;\n\nexport const USER_ROLE = \"user\" as const;\nexport const ASSISTANT_ROLE = \"assistant\" as const;\nexport const SYSTEM_ROLE = \"system\" as const;\n\nexport const QUEUE_PRIORITY_USER_REQUEST = 10;\nexport const DEFAULT_RETRY_MAX_ATTEMPTS = 3;\nexport const DEFAULT_RETRY_INITIAL_DELAY_MS = 1000;\nexport const DEFAULT_RETRY_MAX_DELAY_MS = 10000;\nexport const DEFAULT_RETRY_BACKOFF_MULTIPLIER = 2;\nexport const DEFAULT_RETRY_JITTER_FACTOR = 0.1;\n","\nimport { generateRandomBase36Suffix } from \"../../core/calculations/random-base36-suffix\";\nimport {\n MESSAGE_ID_PREFIX,\n CHAT_MESSAGE_ID_SUFFIX_LENGTH,\n} from \"../../core/constants/identifier.constants\";\n\nconst ID_PART_DELIMITER = \"-\";\n\nexport class ChatIdGenerator {\n private counter = 0;\n private readonly randomLength: number;\n\n constructor(randomLength: number = CHAT_MESSAGE_ID_SUFFIX_LENGTH) {\n this.randomLength = randomLength;\n }\n\n next(sender: string): string {\n this.counter += 1;\n const random = generateRandomBase36Suffix(this.randomLength);\n return [\n MESSAGE_ID_PREFIX,\n Date.now(),\n sender,\n this.counter,\n random,\n ].join(ID_PART_DELIMITER);\n }\n}\n\nexport const chatIdGenerator = new ChatIdGenerator();\n","\nimport type { IMessageFormatter } from \"../interfaces\";\nimport type { ChatMessage } from \"../entities\";\nimport type { ChatMessage as CoreChatMessage } from \"../../core/types\";\nimport type { ChatIdGenerator } from \"./chat-id-generator\";\nimport { chatIdGenerator as defaultIdGenerator } from \"./chat-id-generator\";\nimport { ASSISTANT_ROLE, USER_ROLE } from \"../../core/constants/identifier.constants\";\n\nexport class MessageFormatter implements IMessageFormatter {\n constructor(private readonly idGenerator: ChatIdGenerator = defaultIdGenerator) {}\n\n /** Maps chat-domain history to neutral core messages; system senders are\n * dropped — the system prompt travels on the request's own slot. */\n toCoreMessages(messages: ReadonlyArray<ChatMessage>): CoreChatMessage[] {\n const coreMessages: CoreChatMessage[] = [];\n for (const message of messages) {\n if (message.sender === \"system\") continue;\n coreMessages.push({\n role: message.sender === \"user\" ? USER_ROLE : ASSISTANT_ROLE,\n content: message.content,\n });\n }\n return coreMessages;\n }\n\n toChatMessage(content: string, sender: ChatMessage[\"sender\"]): ChatMessage {\n return {\n id: this.idGenerator.next(sender),\n sender,\n content: content.trim(),\n timestamp: new Date().toISOString(),\n type: \"text\",\n };\n }\n}\n\nexport const messageFormatter = new MessageFormatter();\n","\nimport type { ChatConfig } from \"../entities\";\n\nexport interface SystemPromptStrategy {\n resolve(config: ChatConfig): string | undefined;\n}\n\nexport const DEFAULT_PROMPT_STRATEGY: SystemPromptStrategy = {\n resolve: (config) => {\n if (config.systemPrompt && config.systemPrompt.length > 0) {\n return config.systemPrompt;\n }\n return undefined;\n },\n};\n","\nimport type {\n IChatService,\n SystemPromptStrategy,\n} from \"../interfaces\";\nimport type {\n ChatMessage,\n ChatConfig,\n ChatConversation,\n SendMessageInput,\n SendMessageResult,\n IChatStorage,\n ChatTokenUsage,\n} from \"../entities\";\nimport type { GenerationResult, StreamCallbacks, TextRequest } from \"../../core/types\";\nimport { AIError, AIErrorType } from \"../../core/errors\";\nimport type { ITextProvider } from \"../../providers/base/provider.types\";\nimport { ProviderFactory } from \"../../providers/factory/provider.factory\";\nimport { messageFormatter } from \"../utils/message-formatter\";\nimport { DEFAULT_PROMPT_STRATEGY } from \"../utils/prompt-strategy\";\n\nconst DEFAULT_CONFIG: ChatConfig = {\n temperature: 0.8,\n maxTokens: 500,\n};\n\n/**\n * Conversation engine over the neutral text surface. Accepts either a\n * single ITextProvider or a ProviderFactory (which brings tier defaults,\n * health checks, and fallback across providers). Model choice is tier-based:\n * `config.tier ?? provider default` — no hardcoded model names anywhere.\n */\nexport class ChatService implements IChatService {\n private config: ChatConfig = DEFAULT_CONFIG;\n private promptStrategy: SystemPromptStrategy = DEFAULT_PROMPT_STRATEGY;\n private storage: IChatStorage | null = null;\n\n constructor(\n private readonly engine: ITextProvider | ProviderFactory,\n ) {}\n\n initialize(config: ChatConfig): void {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n updateConfig(config: Partial<ChatConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n setPromptStrategy(strategy: SystemPromptStrategy): void {\n this.promptStrategy = strategy;\n }\n\n setStorage(storage: IChatStorage): void {\n this.storage = storage;\n }\n\n async getConversation(conversationId: string): Promise<ChatConversation | null> {\n const storage = this.requireStorage();\n const messages = await storage.getMessages(conversationId);\n if (messages.length === 0) return null;\n const last = messages[messages.length - 1];\n const first = messages[0];\n const companionId = String(first.metadata?.[\"companionId\"] ?? \"unknown\");\n const companionName = String(first.metadata?.[\"companionName\"] ?? \"Unknown\");\n return {\n id: conversationId,\n companionId,\n companionName,\n lastMessage: last,\n messageCount: messages.length,\n updatedAt: last.timestamp,\n };\n }\n\n async getConversations(): Promise<ChatConversation[]> {\n return [];\n }\n\n async sendMessage(input: SendMessageInput): Promise<SendMessageResult> {\n const userMessage: ChatMessage = {\n ...messageFormatter.toChatMessage(input.text, \"user\"),\n type: input.type ?? \"text\",\n ...(input.imageUrl !== undefined ? { imageUrl: input.imageUrl } : {}),\n };\n\n const aiResponse = await this.generateAIResponse(\n input.companionId,\n input.text,\n [],\n );\n\n return { userMessage, aiResponse };\n }\n\n async generateAIResponse(\n companionId: string,\n userMessage: string,\n context: ReadonlyArray<ChatMessage> = [],\n ): Promise<ChatMessage> {\n const result = await this.run({\n ...this.buildRequest(userMessage, context),\n });\n\n return {\n ...messageFormatter.toChatMessage(result.text, \"assistant\"),\n metadata: {\n companionId,\n model: result.model,\n usage: {\n input_tokens: result.usage?.inputTokens,\n output_tokens: result.usage?.outputTokens,\n total_tokens: result.usage?.totalTokens,\n },\n finishReason: result.finishReason,\n },\n };\n }\n\n async generateStreamingResponse(\n userMessage: string,\n context: ReadonlyArray<ChatMessage>,\n onChunk: (chunk: string) => void,\n ): Promise<string> {\n const request = this.buildRequest(userMessage, context);\n const result = await this.runStream(request, { onChunk });\n return result.text;\n }\n\n private buildRequest(\n userMessage: string,\n context: ReadonlyArray<ChatMessage>,\n ): TextRequest {\n const messages = messageFormatter.toCoreMessages(context);\n messages.push({ role: \"user\", content: userMessage });\n return {\n messages,\n systemPrompt: this.resolveSystemPrompt(),\n model: this.config.model,\n tier: this.config.tier,\n temperature: this.config.temperature,\n maxTokens: this.config.maxTokens,\n };\n }\n\n private resolveSystemPrompt(): string | undefined {\n const prompt = this.promptStrategy.resolve(this.config);\n return prompt && prompt.length > 0 ? prompt : undefined;\n }\n\n private async run(request: TextRequest): Promise<GenerationResult> {\n if (this.engine instanceof ProviderFactory) {\n return this.engine.chat(request);\n }\n return this.engine.generate(request);\n }\n\n private async runStream(\n request: TextRequest,\n callbacks: Pick<StreamCallbacks, \"onChunk\">,\n ): Promise<GenerationResult> {\n if (this.engine instanceof ProviderFactory) {\n return this.engine.chatStream(request, callbacks);\n }\n return this.engine.stream(request, callbacks);\n }\n\n private requireStorage(): IChatStorage {\n if (!this.storage) {\n throw new AIError(\n AIErrorType.MISSING_CONFIG,\n \"ChatService.getConversation requires setStorage() to be called first.\",\n );\n }\n return this.storage;\n }\n}\n\nexport function extractTokenUsage(message: ChatMessage): ChatTokenUsage | null {\n const meta = message.metadata;\n if (!meta) return null;\n const usage = meta[\"usage\"];\n if (!usage || typeof usage !== \"object\") return null;\n const u = usage as Record<string, unknown>;\n const inputTokens = readNumber(u, [\"input_tokens\", \"prompt_tokens\"]);\n const outputTokens = readNumber(u, [\"output_tokens\", \"completion_tokens\"]);\n const totalTokens = readNumber(u, [\"total_tokens\"]);\n if (inputTokens === null || outputTokens === null || totalTokens === null) {\n return null;\n }\n return {\n promptTokens: inputTokens,\n completionTokens: outputTokens,\n totalTokens,\n };\n}\n\nfunction readNumber(\n source: Record<string, unknown>,\n keys: ReadonlyArray<string>,\n): number | null {\n for (const key of keys) {\n const value = source[key];\n if (typeof value === \"number\") return value;\n }\n return null;\n}\n"]}
1
+ {"version":3,"sources":["../../src/core/errors/ai-error-types.ts","../../src/core/errors/ai-error.ts","../../src/providers/base/provider.types.ts","../../src/content/domain/limits/ProviderTimingConfig.ts","../../src/providers/factory/provider.factory.ts","../../src/core/calculations/random-base36-suffix.ts","../../src/core/constants/identifier.constants.ts","../../src/chat/utils/chat-id-generator.ts","../../src/chat/utils/message-formatter.ts","../../src/chat/utils/prompt-strategy.ts","../../src/chat/services/chat.service.ts"],"names":["AIErrorType"],"mappings":"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","file":"index.js","sourcesContent":["\nexport enum AIErrorType {\n INVALID_API_KEY = \"INVALID_API_KEY\",\n MISSING_CONFIG = \"MISSING_CONFIG\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n ABORT_ERROR = \"ABORT_ERROR\",\n RATE_LIMIT_ERROR = \"RATE_LIMIT_ERROR\",\n SERVER_ERROR = \"SERVER_ERROR\",\n CLIENT_ERROR = \"CLIENT_ERROR\",\n UNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\nexport const USER_FRIENDLY_ERROR_MESSAGES: Readonly<Record<AIErrorType, string>> = {\n [AIErrorType.INVALID_API_KEY]: \"Please check your API key and try again.\",\n [AIErrorType.MISSING_CONFIG]: \"The provider is not configured. Please create a provider with createAI first.\",\n [AIErrorType.NETWORK_ERROR]: \"Network error. Please check your connection and try again.\",\n [AIErrorType.ABORT_ERROR]: \"Request was cancelled.\",\n [AIErrorType.RATE_LIMIT_ERROR]: \"You've reached the rate limit. Please wait a moment and try again.\",\n [AIErrorType.SERVER_ERROR]: \"The AI service is temporarily unavailable. Please try again later.\",\n [AIErrorType.CLIENT_ERROR]: \"The request was invalid. Please check your input and try again.\",\n [AIErrorType.UNKNOWN_ERROR]: \"An unexpected error occurred. Please try again.\",\n};\n","\nimport { AIErrorType } from \"./ai-error-types\";\n\nexport interface AIErrorMetadata {\n readonly status?: number;\n readonly url?: string;\n readonly [key: string]: unknown;\n}\n\nconst KNOWN_ERROR_TYPES = new Set<string>(Object.values(AIErrorType));\n\nfunction mapCodeToType(code: string): AIErrorType {\n switch (code) {\n case \"VALIDATION_ERROR\":\n case \"CLIENT_ERROR\":\n return AIErrorType.CLIENT_ERROR;\n case \"INVALID_API_KEY\":\n return AIErrorType.INVALID_API_KEY;\n case \"MISSING_CONFIG\":\n case \"PROVIDER_UNAVAILABLE\":\n return AIErrorType.MISSING_CONFIG;\n case \"PROVIDER_QUOTA_EXHAUSTED\":\n case \"RATE_LIMIT_ERROR\":\n return AIErrorType.RATE_LIMIT_ERROR;\n case \"NETWORK_ERROR\":\n case \"TIMEOUT\":\n return AIErrorType.NETWORK_ERROR;\n case \"ABORT_ERROR\":\n case \"ABORTED\":\n return AIErrorType.ABORT_ERROR;\n case \"SERVER_ERROR\":\n case \"PROVIDER_ERROR\":\n case \"NO_RESULT\":\n return AIErrorType.SERVER_ERROR;\n default:\n return AIErrorType.UNKNOWN_ERROR;\n }\n}\n\nfunction mapMessageToCode(message: string, fallback: string = \"UNKNOWN\"): string {\n const lower = message.toLowerCase();\n if (lower.includes(\"validation\")) return \"VALIDATION_ERROR\";\n if (lower.includes(\"quota\")) return \"PROVIDER_QUOTA_EXHAUSTED\";\n if (lower.includes(\"unavailable\")) return \"PROVIDER_UNAVAILABLE\";\n if (lower.includes(\"timeout\") || lower.includes(\"aborted\")) {\n return lower.includes(\"aborted\") ? \"ABORTED\" : \"TIMEOUT\";\n }\n if (lower.includes(\"parse\") || lower.includes(\"json\")) return \"PARSE_ERROR\";\n if (lower.includes(\"no result\")) return \"NO_RESULT\";\n if (lower.includes(\"network\") || lower.includes(\"fetch\")) return \"NETWORK_ERROR\";\n return fallback;\n}\n\nexport class AIError extends Error {\n public readonly type: AIErrorType;\n public readonly code: string;\n public readonly cause?: unknown;\n public readonly metadata: AIErrorMetadata;\n\n constructor(\n typeOrMessage: AIErrorType | string,\n messageOrCode?: string,\n cause?: unknown,\n metadata: AIErrorMetadata = {},\n ) {\n let effectiveType: AIErrorType;\n let effectiveMessage: string;\n let effectiveCode: string;\n\n if (KNOWN_ERROR_TYPES.has(typeOrMessage)) {\n effectiveType = typeOrMessage as AIErrorType;\n effectiveMessage = messageOrCode ?? \"\";\n effectiveCode = effectiveType;\n } else {\n effectiveMessage = typeOrMessage;\n effectiveCode = messageOrCode ?? \"UNKNOWN\";\n effectiveType = mapCodeToType(effectiveCode);\n }\n\n super(effectiveMessage);\n this.name = \"AIError\";\n this.type = effectiveType;\n this.code = effectiveCode;\n this.cause = cause;\n this.metadata = metadata;\n }\n\n static from(error: unknown, fallbackCode: string = \"UNKNOWN\"): AIError {\n if (error instanceof AIError) return error;\n if (error instanceof Error) {\n const code = mapMessageToCode(error.message, fallbackCode);\n return new AIError(error.message, code, error);\n }\n return new AIError(String(error), fallbackCode, error);\n }\n\n override toString(): string {\n const statusPart =\n typeof this.metadata.status === \"number\" ? ` (HTTP ${this.metadata.status})` : \"\";\n return `${this.name} [${this.type}]: ${this.message}${statusPart}`;\n }\n\n toJSON(): {\n name: string;\n type: AIErrorType;\n code: string;\n message: string;\n metadata: AIErrorMetadata;\n } {\n return {\n name: this.name,\n type: this.type,\n code: this.code,\n message: this.message,\n metadata: this.metadata,\n };\n }\n}\n","\nimport type {\n GenerationResult,\n ProviderHealth,\n StreamCallbacks,\n StructuredGeneration,\n StructuredTextRequest,\n TextRequest,\n TextTier,\n} from \"../../core/types\";\nimport type {\n GeneratedContent,\n ImageGenerationRequest,\n ImageToVideoRequest,\n TextGenerationRequest,\n VideoGenerationRequest,\n VideoToVideoRequest,\n} from \"../../content/domain/config/ProviderConfig\";\n\n/**\n * What a provider can serve. Replaces the old single `'multimodal'` type flag:\n * a provider declares exactly the capabilities it implements, and the factory\n * walks providers by capability when routing or failing over.\n */\nexport type ProviderCapability = \"text\" | \"image\" | \"video\";\n\n/** Cost estimation input — any generation request shape the fleet knows. */\nexport type CostEstimateRequest =\n | TextGenerationRequest\n | ImageGenerationRequest\n | VideoGenerationRequest;\n\nexport interface IProviderBase {\n readonly id: string;\n readonly name: string;\n readonly capabilities: ReadonlyArray<ProviderCapability>;\n healthCheck(): Promise<ProviderHealth>;\n estimateCost(request: CostEstimateRequest): Promise<number>;\n}\n\n/**\n * A provider that can turn conversations into text. This is the surface the\n * factory's `chat`/`chatStream` walk; model choice per quality tier is the\n * provider's own business (each maps neutral tiers onto its catalogue).\n */\nexport interface ITextProvider extends IProviderBase {\n generate(request: TextRequest): Promise<GenerationResult>;\n generateStructured<T>(request: StructuredTextRequest): Promise<StructuredGeneration<T>>;\n stream(request: TextRequest, callbacks: StreamCallbacks): Promise<GenerationResult>;\n resolveModel(tier: TextTier): string;\n}\n\n/**\n * A provider that generates media. Kept as B's media surface — image/video\n * request and result shapes are already provider-neutral.\n */\nexport interface IMediaProvider extends IProviderBase {\n generateImage(request: ImageGenerationRequest): Promise<GeneratedContent>;\n generateVideo(request: VideoGenerationRequest): Promise<GeneratedContent>;\n imageToVideo(request: ImageToVideoRequest): Promise<GeneratedContent>;\n videoToVideo(request: VideoToVideoRequest): Promise<GeneratedContent>;\n}\n\nexport type AnyProvider = ITextProvider | IMediaProvider;\n\nexport function isTextProvider(provider: AnyProvider): provider is ITextProvider {\n return provider.capabilities.includes(\"text\");\n}\n\nexport function isMediaProvider(provider: AnyProvider): provider is IMediaProvider {\n return provider.capabilities.includes(\"image\") || provider.capabilities.includes(\"video\");\n}\n","\nexport const ProviderTimingConfig = {\n DEFAULT_TIMEOUT_MS: 30_000,\n DEFAULT_RETRY_ATTEMPTS: 3,\n\n FAL_TIMEOUT_MS: 120_000,\n FAL_RETRY_ATTEMPTS: 2,\n\n GEMINI_TIMEOUT_MS: 60_000,\n GEMINI_RETRY_ATTEMPTS: 3,\n\n GROQ_TIMEOUT_MS: 30_000,\n GROQ_RETRY_ATTEMPTS: 3,\n\n HEALTH_CHECK_TTL_MS: 5 * 60 * 1000,\n\n RETRY_BACKOFF_BASE_MS: 1_000,\n} as const;\n","\nimport type {\n GenerationResult,\n ProviderHealth,\n StreamCallbacks,\n StructuredGeneration,\n StructuredTextRequest,\n TextRequest,\n TextTier,\n} from \"../../core/types\";\nimport { AIError, AIErrorType } from \"../../core/errors\";\nimport type {\n AnyProvider,\n IMediaProvider,\n ITextProvider,\n ProviderCapability,\n} from \"../base/provider.types\";\nimport { isTextProvider } from \"../base/provider.types\";\nimport type {\n GeneratedContent,\n ImageGenerationRequest,\n ImageToVideoRequest,\n VideoGenerationRequest,\n VideoToVideoRequest,\n} from \"../../content/domain/config/ProviderConfig\";\nimport type {\n ITextGenerator,\n TextGenerationOptions,\n} from \"../../content/domain/interfaces/ITextGenerator\";\nimport { ProviderTimingConfig } from \"../../content/domain/limits/ProviderTimingConfig\";\n\nexport interface ProviderFactoryConfig {\n /** Provider ids in preference order; unlisted providers follow in registration order. */\n priority?: ReadonlyArray<string>;\n fallbackEnabled?: boolean;\n /** Tier used when a request names neither a model nor a tier. */\n defaultTier?: TextTier;\n}\n\ninterface HealthCheckCache {\n health: ProviderHealth;\n timestamp: number;\n}\n\n/**\n * Composition-aware registry and router. Replaces both ancestors at once:\n * B's ProviderFactory (health TTL cache, priority fallback walk, media\n * dispatch) and A's singleton configureProvider (via createAI). Adds the\n * provider-neutral `chat`/`chatStream` text surface with full usage\n * propagation, and keeps B's ITextGenerator string facade so the ported\n * content services compile unchanged.\n */\nexport class ProviderFactory implements ITextGenerator {\n private readonly providers = new Map<string, AnyProvider>();\n private readonly healthCache = new Map<string, HealthCheckCache>();\n private readonly priority: ReadonlyArray<string>;\n private readonly fallbackEnabled: boolean;\n readonly defaultTier: TextTier;\n\n constructor(config: ProviderFactoryConfig = {}) {\n this.priority = config.priority ?? [];\n this.fallbackEnabled = config.fallbackEnabled ?? true;\n this.defaultTier = config.defaultTier ?? \"balanced\";\n }\n\n register(provider: AnyProvider): void {\n this.providers.set(provider.id, provider);\n }\n\n getProvider(id: string): AnyProvider | undefined {\n return this.providers.get(id);\n }\n\n getAllProviders(): AnyProvider[] {\n return Array.from(this.providers.values());\n }\n\n getByCapability(capability: ProviderCapability): AnyProvider[] {\n return this.getAllProviders().filter((provider) =>\n provider.capabilities.includes(capability),\n );\n }\n\n getTextProviders(): ITextProvider[] {\n return this.getAllProviders().filter(isTextProvider);\n }\n\n hasTextProvider(): boolean {\n return this.getByCapability(\"text\").length > 0;\n }\n\n /* ---------- neutral text surface ---------- */\n\n /**\n * Single-chat entry point: resolves a healthy text provider by priority,\n * injects the default tier when the request names neither model nor tier,\n * and walks the fallback chain on failure. Providers map tiers onto their\n * own models, so switching Groq→Anthropic is a config change.\n */\n async chat(request: TextRequest): Promise<GenerationResult> {\n const effective: TextRequest =\n request.model || request.tier ? request : { ...request, tier: this.defaultTier };\n return this.executeWithFallback(\"text\", (provider) =>\n (provider as ITextProvider).generate(effective),\n );\n }\n\n async chatStream(\n request: TextRequest,\n callbacks: StreamCallbacks,\n ): Promise<GenerationResult> {\n const effective: TextRequest =\n request.model || request.tier ? request : { ...request, tier: this.defaultTier };\n\n let lastError: unknown;\n // onError is withheld until every provider has failed — a successful\n // fallback would otherwise have already reported a spurious error.\n const attemptCallbacks: StreamCallbacks = {\n onChunk: callbacks.onChunk,\n onComplete: callbacks.onComplete,\n };\n\n const providers = this.getByCapability(\"text\");\n if (providers.length === 0) {\n throw this.noProviderError(\"text\");\n }\n\n const ordered = this.orderByPriority(providers);\n for (const provider of ordered) {\n if (!this.isProviderHealthy(provider.id)) continue;\n try {\n return await (provider as ITextProvider).stream(effective, attemptCallbacks);\n } catch (error) {\n lastError = error;\n this.markDegraded(provider.id);\n if (!this.fallbackEnabled) {\n callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n }\n\n const failure = new AIError(\n AIErrorType.SERVER_ERROR,\n `All providers failed for capability 'text'`,\n lastError instanceof Error ? lastError : undefined,\n );\n callbacks.onError?.(lastError instanceof Error ? lastError : failure);\n throw failure;\n }\n\n /** AsyncGenerator adapter over chatStream — A's familiar consumption shape. */\n async *streamText(request: TextRequest): AsyncGenerator<string> {\n const queue: string[] = [];\n let wake: (() => void) | null = null;\n let finished = false;\n let failure: unknown;\n\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n request.signal?.addEventListener(\"abort\", onAbort);\n const effectiveRequest = { ...request, signal: controller.signal };\n\n const notify = (): void => {\n const resolve = wake;\n wake = null;\n resolve?.();\n };\n\n const completion = this.chatStream(effectiveRequest, {\n onChunk: (chunk) => {\n queue.push(chunk);\n notify();\n },\n }).then(\n () => {\n finished = true;\n notify();\n },\n (error) => {\n failure = error;\n finished = true;\n notify();\n },\n );\n\n try {\n while (!finished || queue.length > 0) {\n if (queue.length === 0 && !finished) {\n await new Promise<void>((resolve) => {\n wake = resolve;\n });\n }\n while (queue.length > 0) {\n yield queue.shift() as string;\n }\n if (failure) throw failure;\n }\n await completion;\n } finally {\n controller.abort();\n request.signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n async generateJson<T>(\n request: StructuredTextRequest,\n ): Promise<StructuredGeneration<T>> {\n const effective: StructuredTextRequest =\n request.model || request.tier ? request : { ...request, tier: this.defaultTier };\n return this.executeWithFallback(\"text\", (provider) =>\n (provider as ITextProvider).generateStructured<T>(effective),\n );\n }\n\n /* ---------- content-layer string facade (ITextGenerator) ---------- */\n\n async generateText(prompt: string, options: TextGenerationOptions = {}): Promise<string> {\n const result = await this.chat({\n messages: [{ role: \"user\", content: prompt }],\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n });\n return result.text;\n }\n\n generateTextStream(prompt: string, options: TextGenerationOptions = {}): AsyncGenerator<string> {\n return this.streamText({\n messages: [{ role: \"user\", content: prompt }],\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n });\n }\n\n /* ---------- media surface ---------- */\n\n async generateImage(request: ImageGenerationRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"image\", (provider) =>\n (provider as IMediaProvider).generateImage(request),\n );\n }\n\n async generateVideo(request: VideoGenerationRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"video\", (provider) =>\n (provider as IMediaProvider).generateVideo(request),\n );\n }\n\n async imageToVideo(request: ImageToVideoRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"video\", (provider) =>\n (provider as IMediaProvider).imageToVideo(request),\n );\n }\n\n async videoToVideo(request: VideoToVideoRequest): Promise<GeneratedContent> {\n return this.executeWithFallback(\"video\", (provider) =>\n (provider as IMediaProvider).videoToVideo(request),\n );\n }\n\n /* ---------- health ---------- */\n\n async checkProviderHealth(providerId: string, forceRefresh = false): Promise<ProviderHealth> {\n const provider = this.providers.get(providerId);\n if (!provider) {\n return \"unavailable\";\n }\n\n const cached = this.healthCache.get(providerId);\n const now = Date.now();\n const ttl = ProviderTimingConfig.HEALTH_CHECK_TTL_MS;\n\n if (!forceRefresh && cached && now - cached.timestamp < ttl) {\n return cached.health;\n }\n\n try {\n const health = await provider.healthCheck();\n this.healthCache.set(providerId, { health, timestamp: now });\n return health;\n } catch {\n this.healthCache.set(providerId, { health: \"unavailable\", timestamp: now });\n return \"unavailable\";\n }\n }\n\n isProviderHealthy(providerId: string): boolean {\n const cached = this.healthCache.get(providerId);\n if (!cached) {\n return true;\n }\n return cached.health === \"healthy\" || cached.health === \"degraded\";\n }\n\n async refreshAllHealth(): Promise<void> {\n await Promise.all(\n Array.from(this.providers.keys()).map((id) => this.checkProviderHealth(id)),\n );\n }\n\n /* ---------- internals ---------- */\n\n private async executeWithFallback<T>(\n capability: ProviderCapability,\n fn: (provider: AnyProvider) => Promise<T>,\n ): Promise<T> {\n const providers = this.getByCapability(capability);\n if (providers.length === 0) {\n throw this.noProviderError(capability);\n }\n\n let lastError: unknown;\n for (const provider of this.orderByPriority(providers)) {\n if (!this.isProviderHealthy(provider.id)) {\n continue;\n }\n\n try {\n return await fn(provider);\n } catch (error) {\n lastError = error;\n this.markDegraded(provider.id);\n if (!this.fallbackEnabled) {\n throw error;\n }\n }\n }\n\n throw new AIError(\n AIErrorType.SERVER_ERROR,\n `All providers failed for capability '${capability}'`,\n lastError instanceof Error ? lastError : undefined,\n );\n }\n\n private orderByPriority(providers: AnyProvider[]): AnyProvider[] {\n if (this.priority.length === 0) {\n return providers;\n }\n const ordered: AnyProvider[] = [];\n for (const providerId of this.priority) {\n const provider = providers.find((p) => p.id === providerId);\n if (provider) ordered.push(provider);\n }\n for (const provider of providers) {\n if (!this.priority.includes(provider.id)) {\n ordered.push(provider);\n }\n }\n return ordered;\n }\n\n private markDegraded(providerId: string): void {\n const cached = this.healthCache.get(providerId);\n if (cached) {\n this.healthCache.set(providerId, { health: \"degraded\", timestamp: cached.timestamp });\n }\n }\n\n private noProviderError(capability: ProviderCapability): AIError {\n return new AIError(\n AIErrorType.MISSING_CONFIG,\n `No provider registered for capability '${capability}' — create one with createAI() and include its config block`,\n );\n }\n}\n","\nconst BASE_36_RADIX = 36;\nconst DECIMAL_OFFSET = 2;\n\nexport function generateRandomBase36Suffix(\n length: number,\n random: () => number = Math.random,\n): string {\n if (length <= 0) return \"\";\n const raw = random().toString(BASE_36_RADIX).slice(DECIMAL_OFFSET);\n if (raw.length >= length) return raw.slice(0, length);\n\n let result = raw;\n while (result.length < length) {\n result += random().toString(BASE_36_RADIX).slice(DECIMAL_OFFSET);\n }\n return result.slice(0, length);\n}\n","\nexport const MESSAGE_ID_PREFIX = \"msg-\" as const;\nexport const CHAT_MESSAGE_ID_SUFFIX_LENGTH = 9;\nexport const CACHE_KEY_TYPE_COMPLETION = \"completion\" as const;\nexport const CACHE_KEY_TYPE_CHAT = \"chat\" as const;\nexport const CACHE_KEY_TYPE_RESPONSE = \"response\" as const;\nexport const SYSTEM_PROMPT_CACHE_PREFIX = \"system-prompt\" as const;\n\nexport const USER_ROLE = \"user\" as const;\nexport const ASSISTANT_ROLE = \"assistant\" as const;\nexport const SYSTEM_ROLE = \"system\" as const;\n\nexport const QUEUE_PRIORITY_USER_REQUEST = 10;\nexport const DEFAULT_RETRY_MAX_ATTEMPTS = 3;\nexport const DEFAULT_RETRY_INITIAL_DELAY_MS = 1000;\nexport const DEFAULT_RETRY_MAX_DELAY_MS = 10000;\nexport const DEFAULT_RETRY_BACKOFF_MULTIPLIER = 2;\nexport const DEFAULT_RETRY_JITTER_FACTOR = 0.1;\n","\nimport { generateRandomBase36Suffix } from \"../../core/calculations/random-base36-suffix\";\nimport {\n MESSAGE_ID_PREFIX,\n CHAT_MESSAGE_ID_SUFFIX_LENGTH,\n} from \"../../core/constants/identifier.constants\";\n\nconst ID_PART_DELIMITER = \"-\";\n\nexport class ChatIdGenerator {\n private counter = 0;\n private readonly randomLength: number;\n\n constructor(randomLength: number = CHAT_MESSAGE_ID_SUFFIX_LENGTH) {\n this.randomLength = randomLength;\n }\n\n next(sender: string): string {\n this.counter += 1;\n const random = generateRandomBase36Suffix(this.randomLength);\n return [\n MESSAGE_ID_PREFIX,\n Date.now(),\n sender,\n this.counter,\n random,\n ].join(ID_PART_DELIMITER);\n }\n}\n\nexport const chatIdGenerator = new ChatIdGenerator();\n","\nimport type { IMessageFormatter } from \"../interfaces\";\nimport type { ChatMessage } from \"../entities\";\nimport type { ChatMessage as CoreChatMessage } from \"../../core/types\";\nimport type { ChatIdGenerator } from \"./chat-id-generator\";\nimport { chatIdGenerator as defaultIdGenerator } from \"./chat-id-generator\";\nimport { ASSISTANT_ROLE, USER_ROLE } from \"../../core/constants/identifier.constants\";\n\nexport class MessageFormatter implements IMessageFormatter {\n constructor(private readonly idGenerator: ChatIdGenerator = defaultIdGenerator) {}\n\n /** Maps chat-domain history to neutral core messages; system senders are\n * dropped — the system prompt travels on the request's own slot. */\n toCoreMessages(messages: ReadonlyArray<ChatMessage>): CoreChatMessage[] {\n const coreMessages: CoreChatMessage[] = [];\n for (const message of messages) {\n if (message.sender === \"system\") continue;\n coreMessages.push({\n role: message.sender === \"user\" ? USER_ROLE : ASSISTANT_ROLE,\n content: message.content,\n });\n }\n return coreMessages;\n }\n\n toChatMessage(content: string, sender: ChatMessage[\"sender\"]): ChatMessage {\n return {\n id: this.idGenerator.next(sender),\n sender,\n content: content.trim(),\n timestamp: new Date().toISOString(),\n type: \"text\",\n };\n }\n}\n\nexport const messageFormatter = new MessageFormatter();\n","\nimport type { ChatConfig } from \"../entities\";\n\nexport interface SystemPromptStrategy {\n resolve(config: ChatConfig): string | undefined;\n}\n\nexport const DEFAULT_PROMPT_STRATEGY: SystemPromptStrategy = {\n resolve: (config) => {\n if (config.systemPrompt && config.systemPrompt.length > 0) {\n return config.systemPrompt;\n }\n return undefined;\n },\n};\n","\nimport type {\n IChatService,\n SystemPromptStrategy,\n} from \"../interfaces\";\nimport type {\n ChatMessage,\n ChatConfig,\n ChatConversation,\n SendMessageInput,\n SendMessageResult,\n IChatStorage,\n ChatTokenUsage,\n} from \"../entities\";\nimport type { GenerationResult, StreamCallbacks, TextRequest } from \"../../core/types\";\nimport { AIError, AIErrorType } from \"../../core/errors\";\nimport type { ITextProvider } from \"../../providers/base/provider.types\";\nimport { ProviderFactory } from \"../../providers/factory/provider.factory\";\nimport { messageFormatter } from \"../utils/message-formatter\";\nimport { DEFAULT_PROMPT_STRATEGY } from \"../utils/prompt-strategy\";\n\nconst DEFAULT_CONFIG: ChatConfig = {\n temperature: 0.8,\n maxTokens: 500,\n};\n\n/**\n * Conversation engine over the neutral text surface. Accepts either a\n * single ITextProvider or a ProviderFactory (which brings tier defaults,\n * health checks, and fallback across providers). Model choice is tier-based:\n * `config.tier ?? provider default` — no hardcoded model names anywhere.\n */\nexport class ChatService implements IChatService {\n private config: ChatConfig = DEFAULT_CONFIG;\n private promptStrategy: SystemPromptStrategy = DEFAULT_PROMPT_STRATEGY;\n private storage: IChatStorage | null = null;\n\n constructor(\n private readonly engine: ITextProvider | ProviderFactory,\n ) {}\n\n initialize(config: ChatConfig): void {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n updateConfig(config: Partial<ChatConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n setPromptStrategy(strategy: SystemPromptStrategy): void {\n this.promptStrategy = strategy;\n }\n\n setStorage(storage: IChatStorage): void {\n this.storage = storage;\n }\n\n async getConversation(conversationId: string): Promise<ChatConversation | null> {\n const storage = this.requireStorage();\n const messages = await storage.getMessages(conversationId);\n if (messages.length === 0) return null;\n const last = messages[messages.length - 1];\n const first = messages[0];\n const companionId = String(first.metadata?.[\"companionId\"] ?? \"unknown\");\n const companionName = String(first.metadata?.[\"companionName\"] ?? \"Unknown\");\n return {\n id: conversationId,\n companionId,\n companionName,\n lastMessage: last,\n messageCount: messages.length,\n updatedAt: last.timestamp,\n };\n }\n\n async getConversations(): Promise<ChatConversation[]> {\n if (\n this.storage &&\n \"getConversations\" in this.storage &&\n typeof (this.storage as unknown as { getConversations: () => Promise<ChatConversation[]> }).getConversations === \"function\"\n ) {\n return (this.storage as unknown as { getConversations: () => Promise<ChatConversation[]> }).getConversations();\n }\n return [];\n }\n\n async sendMessage(input: SendMessageInput, signal?: AbortSignal): Promise<SendMessageResult> {\n const userMessage: ChatMessage = {\n ...messageFormatter.toChatMessage(input.text, \"user\"),\n type: input.type ?? \"text\",\n ...(input.imageUrl !== undefined ? { imageUrl: input.imageUrl } : {}),\n };\n\n const aiResponse = await this.generateAIResponse(\n input.companionId,\n input.text,\n [],\n signal,\n );\n\n return { userMessage, aiResponse };\n }\n\n async generateAIResponse(\n companionId: string,\n userMessage: string,\n context: ReadonlyArray<ChatMessage> = [],\n signal?: AbortSignal,\n ): Promise<ChatMessage> {\n const result = await this.run({\n ...this.buildRequest(userMessage, context, signal),\n });\n\n return {\n ...messageFormatter.toChatMessage(result.text, \"assistant\"),\n metadata: {\n companionId,\n model: result.model,\n usage: {\n input_tokens: result.usage?.inputTokens,\n output_tokens: result.usage?.outputTokens,\n total_tokens: result.usage?.totalTokens,\n },\n finishReason: result.finishReason,\n },\n };\n }\n\n async generateStreamingResponse(\n userMessage: string,\n context: ReadonlyArray<ChatMessage>,\n onChunk: (chunk: string) => void,\n signal?: AbortSignal,\n ): Promise<string> {\n const request = this.buildRequest(userMessage, context, signal);\n const result = await this.runStream(request, { onChunk });\n return result.text;\n }\n\n private buildRequest(\n userMessage: string,\n context: ReadonlyArray<ChatMessage>,\n signal?: AbortSignal,\n ): TextRequest {\n const messages = messageFormatter.toCoreMessages(context);\n messages.push({ role: \"user\", content: userMessage });\n return {\n messages,\n systemPrompt: this.resolveSystemPrompt(),\n model: this.config.model,\n tier: this.config.tier,\n temperature: this.config.temperature,\n maxTokens: this.config.maxTokens,\n ...(signal !== undefined ? { signal } : {}),\n };\n }\n\n private resolveSystemPrompt(): string | undefined {\n const prompt = this.promptStrategy.resolve(this.config);\n return prompt && prompt.length > 0 ? prompt : undefined;\n }\n\n private async run(request: TextRequest): Promise<GenerationResult> {\n if (this.engine instanceof ProviderFactory) {\n return this.engine.chat(request);\n }\n return this.engine.generate(request);\n }\n\n private async runStream(\n request: TextRequest,\n callbacks: Pick<StreamCallbacks, \"onChunk\">,\n ): Promise<GenerationResult> {\n if (this.engine instanceof ProviderFactory) {\n return this.engine.chatStream(request, callbacks);\n }\n return this.engine.stream(request, callbacks);\n }\n\n private requireStorage(): IChatStorage {\n if (!this.storage) {\n throw new AIError(\n AIErrorType.MISSING_CONFIG,\n \"ChatService.getConversation requires setStorage() to be called first.\",\n );\n }\n return this.storage;\n }\n}\n\nexport function extractTokenUsage(message: ChatMessage): ChatTokenUsage | null {\n const meta = message.metadata;\n if (!meta) return null;\n const usage = meta[\"usage\"];\n if (!usage || typeof usage !== \"object\") return null;\n const u = usage as Record<string, unknown>;\n const inputTokens = readNumber(u, [\"input_tokens\", \"prompt_tokens\"]);\n const outputTokens = readNumber(u, [\"output_tokens\", \"completion_tokens\"]);\n const totalTokens = readNumber(u, [\"total_tokens\"]);\n if (inputTokens === null || outputTokens === null || totalTokens === null) {\n return null;\n }\n return {\n promptTokens: inputTokens,\n completionTokens: outputTokens,\n totalTokens,\n };\n}\n\nfunction readNumber(\n source: Record<string, unknown>,\n keys: ReadonlyArray<string>,\n): number | null {\n for (const key of keys) {\n const value = source[key];\n if (typeof value === \"number\") return value;\n }\n return null;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { c as TextTier, C as ChatMessage$1 } from './index-fXjxTR5W.cjs';
2
- import { b as ITextProvider, c as ProviderFactory } from './provider.factory-COsnprLH.cjs';
2
+ import { b as ITextProvider, c as ProviderFactory } from './provider.factory-BxsfK4WW.cjs';
3
3
 
4
4
  type ChatMessageSender = "user" | "assistant" | "system";
5
5
  type ChatMessageType = "text" | "image" | "audio" | "sticker";
@@ -58,11 +58,11 @@ interface SystemPromptStrategy {
58
58
  declare const DEFAULT_PROMPT_STRATEGY: SystemPromptStrategy;
59
59
 
60
60
  interface IChatService {
61
- sendMessage(input: SendMessageInput): Promise<SendMessageResult>;
61
+ sendMessage(input: SendMessageInput, signal?: AbortSignal): Promise<SendMessageResult>;
62
62
  getConversation(conversationId: string): Promise<ChatConversation | null>;
63
63
  getConversations(): Promise<ChatConversation[]>;
64
- generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>): Promise<ChatMessage>;
65
- generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void): Promise<string>;
64
+ generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>, signal?: AbortSignal): Promise<ChatMessage>;
65
+ generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void, signal?: AbortSignal): Promise<string>;
66
66
  }
67
67
  interface UseChatOptions {
68
68
  readonly conversationId: string;
@@ -110,9 +110,9 @@ declare class ChatService implements IChatService {
110
110
  setStorage(storage: IChatStorage): void;
111
111
  getConversation(conversationId: string): Promise<ChatConversation | null>;
112
112
  getConversations(): Promise<ChatConversation[]>;
113
- sendMessage(input: SendMessageInput): Promise<SendMessageResult>;
114
- generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>): Promise<ChatMessage>;
115
- generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void): Promise<string>;
113
+ sendMessage(input: SendMessageInput, signal?: AbortSignal): Promise<SendMessageResult>;
114
+ generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>, signal?: AbortSignal): Promise<ChatMessage>;
115
+ generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void, signal?: AbortSignal): Promise<string>;
116
116
  private buildRequest;
117
117
  private resolveSystemPrompt;
118
118
  private run;
@@ -1,5 +1,5 @@
1
1
  import { c as TextTier, C as ChatMessage$1 } from './index-fXjxTR5W.js';
2
- import { b as ITextProvider, c as ProviderFactory } from './provider.factory-CpWFyjbw.js';
2
+ import { b as ITextProvider, c as ProviderFactory } from './provider.factory-DfDfk0dK.js';
3
3
 
4
4
  type ChatMessageSender = "user" | "assistant" | "system";
5
5
  type ChatMessageType = "text" | "image" | "audio" | "sticker";
@@ -58,11 +58,11 @@ interface SystemPromptStrategy {
58
58
  declare const DEFAULT_PROMPT_STRATEGY: SystemPromptStrategy;
59
59
 
60
60
  interface IChatService {
61
- sendMessage(input: SendMessageInput): Promise<SendMessageResult>;
61
+ sendMessage(input: SendMessageInput, signal?: AbortSignal): Promise<SendMessageResult>;
62
62
  getConversation(conversationId: string): Promise<ChatConversation | null>;
63
63
  getConversations(): Promise<ChatConversation[]>;
64
- generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>): Promise<ChatMessage>;
65
- generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void): Promise<string>;
64
+ generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>, signal?: AbortSignal): Promise<ChatMessage>;
65
+ generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void, signal?: AbortSignal): Promise<string>;
66
66
  }
67
67
  interface UseChatOptions {
68
68
  readonly conversationId: string;
@@ -110,9 +110,9 @@ declare class ChatService implements IChatService {
110
110
  setStorage(storage: IChatStorage): void;
111
111
  getConversation(conversationId: string): Promise<ChatConversation | null>;
112
112
  getConversations(): Promise<ChatConversation[]>;
113
- sendMessage(input: SendMessageInput): Promise<SendMessageResult>;
114
- generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>): Promise<ChatMessage>;
115
- generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void): Promise<string>;
113
+ sendMessage(input: SendMessageInput, signal?: AbortSignal): Promise<SendMessageResult>;
114
+ generateAIResponse(companionId: string, userMessage: string, context?: ReadonlyArray<ChatMessage>, signal?: AbortSignal): Promise<ChatMessage>;
115
+ generateStreamingResponse(userMessage: string, context: ReadonlyArray<ChatMessage>, onChunk: (chunk: string) => void, signal?: AbortSignal): Promise<string>;
116
116
  private buildRequest;
117
117
  private resolveSystemPrompt;
118
118
  private run;