@lenne.tech/nest-server 11.39.0 → 11.41.0

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 (32) hide show
  1. package/.claude/rules/configurable-features.md +3 -0
  2. package/.claude/rules/module-inheritance.md +2 -0
  3. package/.claude/rules/package-management.md +51 -2
  4. package/.claude/rules/testing.md +182 -3
  5. package/CLAUDE.md +13 -1
  6. package/FRAMEWORK-API.md +3 -2
  7. package/dist/core/common/interfaces/server-options.interface.d.ts +2 -1
  8. package/dist/core/modules/ai/core-ai.controller.js +6 -0
  9. package/dist/core/modules/ai/core-ai.controller.js.map +1 -1
  10. package/dist/core/modules/ai/interfaces/llm-provider.interface.d.ts +1 -0
  11. package/dist/core/modules/ai/models/core-ai-prompt.model.js +1 -1
  12. package/dist/core/modules/ai/models/core-ai-prompt.model.js.map +1 -1
  13. package/dist/core/modules/ai/models/core-ai-slot.model.js +1 -1
  14. package/dist/core/modules/ai/models/core-ai-slot.model.js.map +1 -1
  15. package/dist/core/modules/ai/providers/openai-compatible.provider.d.ts +6 -0
  16. package/dist/core/modules/ai/providers/openai-compatible.provider.js +106 -12
  17. package/dist/core/modules/ai/providers/openai-compatible.provider.js.map +1 -1
  18. package/dist/core/modules/ai/services/core-ai.service.d.ts +12 -1
  19. package/dist/core/modules/ai/services/core-ai.service.js +131 -13
  20. package/dist/core/modules/ai/services/core-ai.service.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/migration-guides/11.39.0-to-11.40.0.md +186 -0
  23. package/migration-guides/11.40.0-to-11.41.0.md +118 -0
  24. package/package.json +5 -4
  25. package/src/core/common/interfaces/server-options.interface.ts +34 -1
  26. package/src/core/modules/ai/README.md +59 -5
  27. package/src/core/modules/ai/core-ai.controller.ts +16 -0
  28. package/src/core/modules/ai/interfaces/llm-provider.interface.ts +15 -0
  29. package/src/core/modules/ai/models/core-ai-prompt.model.ts +10 -1
  30. package/src/core/modules/ai/models/core-ai-slot.model.ts +10 -1
  31. package/src/core/modules/ai/providers/openai-compatible.provider.ts +309 -15
  32. package/src/core/modules/ai/services/core-ai.service.ts +333 -23
@@ -42,7 +42,7 @@ class OpenAiCompatibleProvider {
42
42
  type: 'function',
43
43
  }));
44
44
  }
45
- if (this.capabilities.jsonResponse) {
45
+ if (this.capabilities.jsonResponse && options?.jsonResponse !== false && body.model === this.connection.model) {
46
46
  body.response_format = { type: 'json_object' };
47
47
  }
48
48
  const timeoutMs = options?.timeoutMs ?? this.defaultTimeoutMs;
@@ -84,8 +84,8 @@ class OpenAiCompatibleProvider {
84
84
  };
85
85
  }
86
86
  assertBaseUrlAllowed(url) {
87
- const allowedHosts = config_service_1.ConfigService.get('ai.allowedBaseUrlHosts');
88
- if (!Array.isArray(allowedHosts) || !allowedHosts.length) {
87
+ const allowedHosts = this.resolveAllowedBaseUrlHosts();
88
+ if (!allowedHosts.length) {
89
89
  return;
90
90
  }
91
91
  let parsed;
@@ -95,24 +95,104 @@ class OpenAiCompatibleProvider {
95
95
  catch {
96
96
  throw new common_1.ServiceUnavailableException(error_code_1.ErrorCode.AI_CONNECTION_INVALID_URL);
97
97
  }
98
- if (!allowedHosts.includes(parsed.host) && !allowedHosts.includes(parsed.hostname)) {
98
+ const defaultPort = parsed.protocol === 'https:' ? '443' : parsed.protocol === 'http:' ? '80' : '';
99
+ const candidates = [parsed.host, parsed.hostname];
100
+ if (defaultPort && parsed.host === parsed.hostname) {
101
+ candidates.push(`${parsed.hostname}:${defaultPort}`);
102
+ }
103
+ if (!candidates.map((candidate) => this.normaliseHostEntry(candidate)).some((c) => allowedHosts.includes(c))) {
99
104
  this.logger.warn(`AI connection "${this.connection.name}" host "${parsed.host}" is not in ai.allowedBaseUrlHosts`);
100
105
  throw new common_1.ServiceUnavailableException(error_code_1.ErrorCode.AI_CONNECTION_NOT_AVAILABLE);
101
106
  }
102
107
  }
108
+ static NATIVE_TOOL_PROBE_MAX_TOKENS = 256;
109
+ static NATIVE_TOOL_PROBE_MAX_TOKENS_RETRY = 1024;
110
+ resolveAllowedBaseUrlHosts() {
111
+ const configured = config_service_1.ConfigService.get('ai.allowedBaseUrlHosts');
112
+ if (configured === undefined || configured === null) {
113
+ return [];
114
+ }
115
+ const entries = typeof configured === 'string' ? configured.split(',') : configured;
116
+ if (!Array.isArray(entries)) {
117
+ this.logger.error(`ai.allowedBaseUrlHosts is a ${typeof configured} and carries no hostnames — the SSRF egress ` +
118
+ 'allowlist is NOT active. Use an array or a comma-separated string.');
119
+ return [];
120
+ }
121
+ return entries.map((host) => this.normaliseHostEntry(String(host))).filter(Boolean);
122
+ }
123
+ normaliseHostEntry(value) {
124
+ return value
125
+ .trim()
126
+ .toLowerCase()
127
+ .replace(/\.(?=$|:)/, '');
128
+ }
103
129
  async detectCapabilities() {
130
+ const needsJson = this.connection.supportsJsonResponse === undefined;
131
+ const needsTools = this.connection.supportsNativeTools === undefined;
132
+ const [jsonResponse, nativeTools] = await Promise.all([
133
+ needsJson ? this.probeJsonResponse() : Promise.resolve(undefined),
134
+ needsTools ? this.probeNativeTools() : Promise.resolve(undefined),
135
+ ]);
104
136
  const result = {};
105
- if (this.connection.supportsJsonResponse === undefined) {
137
+ if (needsJson) {
138
+ result.jsonResponse = jsonResponse;
139
+ }
140
+ if (needsTools) {
141
+ result.nativeTools = nativeTools;
142
+ }
143
+ return result;
144
+ }
145
+ async probeJsonResponse() {
146
+ const budgets = [
147
+ OpenAiCompatibleProvider.NATIVE_TOOL_PROBE_MAX_TOKENS,
148
+ OpenAiCompatibleProvider.NATIVE_TOOL_PROBE_MAX_TOKENS_RETRY,
149
+ ];
150
+ for (const [attempt, maxTokens] of budgets.entries()) {
106
151
  const res = await this.probe({
107
- max_tokens: 8,
152
+ max_tokens: maxTokens,
108
153
  messages: [{ content: 'Reply with the JSON object {"ok":true}.', role: 'user' }],
109
154
  response_format: { type: 'json_object' },
110
155
  });
111
- result.jsonResponse = res.ok;
156
+ if (!res.ok) {
157
+ return false;
158
+ }
159
+ const choice = res.json?.choices?.[0];
160
+ const content = choice?.message?.content;
161
+ const truncated = choice?.finish_reason === 'length';
162
+ if (typeof content === 'string' && content.trim()) {
163
+ try {
164
+ JSON.parse(content);
165
+ return true;
166
+ }
167
+ catch {
168
+ if (!truncated) {
169
+ this.logger.warn(`JSON-response probe for model "${this.connection.model}" returned non-JSON content — ` +
170
+ 'recording structured JSON as unsupported');
171
+ return false;
172
+ }
173
+ }
174
+ }
175
+ else if (!truncated) {
176
+ return false;
177
+ }
178
+ const isLastAttempt = attempt === budgets.length - 1;
179
+ this.logger.warn(`JSON-response probe for model "${this.connection.model}" was truncated (finish_reason=length) at ` +
180
+ `max_tokens=${maxTokens}` +
181
+ (isLastAttempt
182
+ ? ' on the final attempt — recording structured JSON as unsupported; a model that cannot emit a ' +
183
+ 'trivial JSON object within a usable output budget is better served by the prompt-driven fallback'
184
+ : ' — retrying once with a larger budget'));
112
185
  }
113
- if (this.connection.supportsNativeTools === undefined) {
186
+ return false;
187
+ }
188
+ async probeNativeTools() {
189
+ const budgets = [
190
+ OpenAiCompatibleProvider.NATIVE_TOOL_PROBE_MAX_TOKENS,
191
+ OpenAiCompatibleProvider.NATIVE_TOOL_PROBE_MAX_TOKENS_RETRY,
192
+ ];
193
+ for (const [attempt, maxTokens] of budgets.entries()) {
114
194
  const res = await this.probe({
115
- max_tokens: 8,
195
+ max_tokens: maxTokens,
116
196
  messages: [{ content: 'Call the ping tool.', role: 'user' }],
117
197
  tool_choice: 'required',
118
198
  tools: [
@@ -126,9 +206,22 @@ class OpenAiCompatibleProvider {
126
206
  },
127
207
  ],
128
208
  });
129
- result.nativeTools = res.ok && !!res.json?.choices?.[0]?.message?.tool_calls?.length;
209
+ const choice = res.json?.choices?.[0];
210
+ if (res.ok && choice?.message?.tool_calls?.length) {
211
+ return true;
212
+ }
213
+ if (!res.ok || choice?.finish_reason !== 'length') {
214
+ return false;
215
+ }
216
+ const isLastAttempt = attempt === budgets.length - 1;
217
+ this.logger.warn(`Native-tool probe for model "${this.connection.model}" was truncated (finish_reason=length) at ` +
218
+ `max_tokens=${maxTokens}` +
219
+ (isLastAttempt
220
+ ? ' on the final attempt — recording native tools as unsupported; the model does not reach a tool ' +
221
+ 'call within a usable output budget, so emulated tool calling is the correct fallback'
222
+ : ' — retrying once with a larger budget'));
130
223
  }
131
- return result;
224
+ return false;
132
225
  }
133
226
  async probe(extra) {
134
227
  const url = `${this.connection.baseUrl.replace(/\/$/, '')}/chat/completions`;
@@ -161,7 +254,7 @@ class OpenAiCompatibleProvider {
161
254
  128_000,
162
255
  ['gpt-4o', 'gpt-4.1', 'gpt-4-turbo', 'o1', 'o3', 'gpt-oss', 'mistral-large', 'mistral-small3', 'command-r'],
163
256
  ],
164
- [131_072, ['qwen2.5', 'qwen3', 'llama-3.1', 'llama3.1', 'llama-3.3', 'llama3.3']],
257
+ [131_072, ['qwen2.5', 'qwen3', 'llama-3.1', 'llama3.1', 'llama-3.3', 'llama3.3', 'ministral', 'mistral-medium']],
165
258
  [65_536, ['mixtral']],
166
259
  [32_768, ['qwen2', 'mistral', 'gemma2', 'gemma-2']],
167
260
  [16_385, ['gpt-3.5']],
@@ -179,6 +272,7 @@ class OpenAiCompatibleProvider {
179
272
  if (!base.startsWith('http')) {
180
273
  return undefined;
181
274
  }
275
+ this.assertBaseUrlAllowed(`${base}/api/show`);
182
276
  const response = await fetch(`${base}/api/show`, {
183
277
  body: JSON.stringify({ name: this.connection.model }),
184
278
  headers: { 'Content-Type': 'application/json' },
@@ -1 +1 @@
1
- {"version":3,"file":"openai-compatible.provider.js","sourceRoot":"","sources":["../../../../../src/core/modules/ai/providers/openai-compatible.provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"openai-compatible.provider.js","sourceRoot":"","sources":["../../../../../src/core/modules/ai/providers/openai-compatible.provider.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,7 @@ export interface AiRunContext {
46
46
  role: string;
47
47
  }[];
48
48
  language?: string;
49
+ onAction?: (action: CoreAiAction) => void;
49
50
  provider: import('../interfaces/llm-provider.interface').ILlmProvider;
50
51
  tenantId?: string;
51
52
  tools: IAiTool[];
@@ -69,9 +70,15 @@ export declare class CoreAiService {
69
70
  protected readonly logger: Logger;
70
71
  protected rateLimitStore?: RateLimitStore;
71
72
  constructor(connectionService: CoreAiConnectionService, providerFactory: LlmProviderFactory, toolRegistry: AiToolRegistry, promptBuilder: CoreAiPromptBuilderService, interactionService?: CoreAiInteractionService, conversationService?: CoreAiConversationService, budgetService?: CoreAiBudgetService, connectionResolver?: CoreAiConnectionResolverService, hintService?: CoreAiPromptHintService, toolGrantService?: CoreAiToolGrantService, hookRegistry?: AiHookRegistry, toolPolicyService?: CoreAiToolPolicyService, modeService?: CoreAiModeService, placeholderRegistry?: CoreAiPlaceholderRegistry, coreRedisService?: CoreRedisService);
72
- prompt(input: CoreAiPromptInput, serviceOptions: ServiceOptions): Promise<CoreAiResponse>;
73
+ prompt(input: CoreAiPromptInput, serviceOptions: ServiceOptions, hooks?: {
74
+ onAction?: (action: CoreAiAction) => void;
75
+ }): Promise<CoreAiResponse>;
73
76
  protected resolvePromptPlaceholders(input: CoreAiPromptInput, serviceOptions: ServiceOptions): Promise<CoreAiPromptInput>;
74
77
  protected unavailableResponse(input: CoreAiPromptInput, language?: string): CoreAiResponse;
78
+ protected readonly detectionBackoff: Map<string, number>;
79
+ protected readonly detectionBackoffMs: number;
80
+ protected detectionSuppressed(connectionId: string): boolean;
81
+ protected rememberFailedDetection(connectionId: string): void;
75
82
  protected prepareRun(input: CoreAiPromptInput, serviceOptions: ServiceOptions): Promise<AiRunContext | undefined>;
76
83
  protected attachBudgetSummary(response: CoreAiResponse, run: AiRunContext): Promise<void>;
77
84
  protected runAuto(input: CoreAiPromptInput, run: AiRunContext): Promise<CoreAiResponse>;
@@ -107,6 +114,10 @@ export declare class CoreAiService {
107
114
  onModuleDestroy(): void;
108
115
  protected executeToolCall(call: LlmToolCall, availableTools: IAiTool[], context: AiToolContext, input?: CoreAiPromptInput): Promise<CoreAiAction>;
109
116
  protected extractToolCalls(text: string): LlmToolCall[] | undefined;
117
+ protected hitOutputCeiling(completion: LlmResponse): boolean;
118
+ protected isBareJsonValue(text: string, truncated?: boolean): boolean;
119
+ protected isFencedJsonValue(text: string): boolean;
120
+ protected isProtocolResidue(text: string, parsed: any | null, truncated?: boolean): boolean;
110
121
  protected extractJsonObject(text: string): any | null;
111
122
  protected firstBalancedJson(text: string, from: number): null | string;
112
123
  protected estimateTokens(text: string): number;
@@ -73,13 +73,16 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
73
73
  this.placeholderRegistry = placeholderRegistry;
74
74
  this.coreRedisService = coreRedisService;
75
75
  }
76
- async prompt(input, serviceOptions) {
76
+ async prompt(input, serviceOptions, hooks) {
77
77
  const mode = input.mode || config_service_1.ConfigService.get('ai.defaultMode') || 'auto';
78
78
  const resolvedInput = await this.resolvePromptPlaceholders(input, serviceOptions);
79
79
  const run = await this.prepareRun(resolvedInput, serviceOptions);
80
80
  if (!run) {
81
81
  return this.unavailableResponse(resolvedInput, serviceOptions?.language);
82
82
  }
83
+ if (hooks?.onAction) {
84
+ run.onAction = hooks.onAction;
85
+ }
83
86
  const response = mode === 'plan' ? await this.runPlan(resolvedInput, run) : await this.runAuto(resolvedInput, run);
84
87
  await this.attachBudgetSummary(response, run);
85
88
  return response;
@@ -111,6 +114,28 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
111
114
  response.text = this.translate('ai_unavailable', language);
112
115
  return response;
113
116
  }
117
+ detectionBackoff = new Map();
118
+ detectionBackoffMs = 5 * 60 * 1000;
119
+ detectionSuppressed(connectionId) {
120
+ const until = this.detectionBackoff.get(connectionId);
121
+ if (until === undefined) {
122
+ return false;
123
+ }
124
+ if (until > Date.now()) {
125
+ return true;
126
+ }
127
+ this.detectionBackoff.delete(connectionId);
128
+ return false;
129
+ }
130
+ rememberFailedDetection(connectionId) {
131
+ const now = Date.now();
132
+ for (const [id, until] of this.detectionBackoff) {
133
+ if (until <= now) {
134
+ this.detectionBackoff.delete(id);
135
+ }
136
+ }
137
+ this.detectionBackoff.set(connectionId, now + this.detectionBackoffMs);
138
+ }
114
139
  async prepareRun(input, serviceOptions) {
115
140
  const currentUser = serviceOptions?.currentUser;
116
141
  const tenantId = request_context_service_1.RequestContext.getTenantId();
@@ -129,8 +154,15 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
129
154
  if ((connection.supportsJsonResponse === undefined ||
130
155
  connection.supportsNativeTools === undefined ||
131
156
  connection.contextWindow === undefined) &&
132
- typeof this.connectionService?.detectAndPersistCapabilities === 'function') {
133
- connection = await this.connectionService.detectAndPersistCapabilities(connection.id).catch(() => connection);
157
+ typeof this.connectionService?.detectAndPersistCapabilities === 'function' &&
158
+ !this.detectionSuppressed(connection.id)) {
159
+ const detected = await this.connectionService.detectAndPersistCapabilities(connection.id).catch(() => undefined);
160
+ if (detected) {
161
+ connection = detected;
162
+ }
163
+ else {
164
+ this.rememberFailedDetection(connection.id);
165
+ }
134
166
  }
135
167
  await this.checkRateLimit(currentUser?.id);
136
168
  if (this.budgetService) {
@@ -190,6 +222,7 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
190
222
  language,
191
223
  });
192
224
  const toolSchemas = this.promptBuilder.buildToolSchemas(tools);
225
+ const jsonMode = provider.capabilities.nativeTools ? { jsonResponse: false } : {};
193
226
  const messages = [{ content: systemPrompt, role: 'system' }];
194
227
  for (const turn of history) {
195
228
  messages.push({ content: turn.content, role: turn.role === 'assistant' ? 'assistant' : 'user' });
@@ -201,6 +234,7 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
201
234
  role: 'user',
202
235
  });
203
236
  const maxIterations = config_service_1.ConfigService.get('ai.maxIterations') ?? 5;
237
+ const maxRunMs = config_service_1.ConfigService.get('ai.maxRunMs') ?? 0;
204
238
  const confirm = !!input.confirm;
205
239
  const actions = [];
206
240
  const pendingActions = [];
@@ -211,11 +245,19 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
211
245
  let nudgedForFinal = false;
212
246
  let pendingQuestion;
213
247
  let requiresConfirmation = false;
248
+ const runStartedAt = Date.now();
249
+ const runDeadlineExceeded = () => maxRunMs > 0 && Date.now() - runStartedAt >= maxRunMs;
214
250
  while (iterations < maxIterations) {
251
+ if (iterations > 0 && runDeadlineExceeded()) {
252
+ this.logger.warn(`AI run stopped after ${Date.now() - runStartedAt}ms (ai.maxRunMs=${maxRunMs}) at iteration ` +
253
+ `${iterations}/${maxIterations} — answering with what the run has so far`);
254
+ break;
255
+ }
215
256
  iterations++;
216
257
  await this.compactMessages(messages, connection);
217
258
  this.fitMessagesToContext(messages, connection);
218
259
  const completion = await provider.chat(messages, toolSchemas, {
260
+ ...jsonMode,
219
261
  maxTokens: connection.defaultMaxTokens,
220
262
  temperature: connection.defaultTemperature,
221
263
  });
@@ -278,6 +320,7 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
278
320
  for (const call of toolCalls) {
279
321
  const action = await this.executeToolCall(call, tools, context, input);
280
322
  actions.push(action);
323
+ run.onAction?.(action);
281
324
  results.push({ name: action.name, result: action.result, success: action.success });
282
325
  const sentinel = this.extractAskUserQuestion(action);
283
326
  if (sentinel) {
@@ -297,21 +340,24 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
297
340
  continue;
298
341
  }
299
342
  const parsed = this.extractJsonObject(completion.text);
343
+ const residue = this.isProtocolResidue(completion.text, parsed, this.hitOutputCeiling(completion));
300
344
  if (parsed && typeof parsed.final === 'string') {
301
345
  finalText = parsed.final;
302
346
  finalData = parsed.data ?? undefined;
303
347
  }
304
- else if (parsed && 'tool_calls' in parsed && !nudgedForFinal && iterations < maxIterations) {
348
+ else if (residue && !nudgedForFinal && iterations < maxIterations) {
305
349
  nudgedForFinal = true;
306
- messages.push({ content: completion.text, role: 'assistant' });
350
+ messages.push({ content: '(previous reply was machine output, not an answer)', role: 'assistant' });
307
351
  messages.push({
308
- content: 'You did not request any tool. Now reply with your final answer ONLY as {"final":"<your answer>"}.',
352
+ content: provider.capabilities.nativeTools
353
+ ? 'That was not an answer for the user. Reply now in plain natural language — no JSON, no code fences.'
354
+ : 'You did not request any tool. Now reply with your final answer ONLY as {"final":"<your answer>"}.',
309
355
  role: 'user',
310
356
  });
311
357
  continue;
312
358
  }
313
359
  else {
314
- finalText = parsed && ('tool_calls' in parsed || 'final' in parsed) ? '' : completion.text;
360
+ finalText = residue || !completion.text?.trim() ? '' : completion.text;
315
361
  }
316
362
  break;
317
363
  }
@@ -425,12 +471,13 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
425
471
  }
426
472
  messages.push({ content: `TOOL_RESULTS:\n${this.capToolResults(JSON.stringify(results))}`, role: 'user' });
427
473
  this.fitMessagesToContext(messages, connection);
428
- const finalCompletion = await provider.chat(messages, [], chatOptions);
474
+ const finalCompletion = await provider.chat(messages, [], { ...chatOptions, jsonResponse: false });
429
475
  this.accumulateUsage(usage, finalCompletion);
430
476
  const finalParsed = this.extractJsonObject(finalCompletion.text);
477
+ const finalResidue = this.isProtocolResidue(finalCompletion.text, finalParsed, this.hitOutputCeiling(finalCompletion));
431
478
  const finalText = finalParsed && typeof finalParsed.final === 'string'
432
479
  ? finalParsed.final
433
- : finalCompletion.text || parsed?.summary || this.translate('done', language);
480
+ : (finalResidue ? '' : finalCompletion.text) || parsed?.summary || this.translate('done', language);
434
481
  const response = this.baseResponse(connection.id, input);
435
482
  response.actions = actions;
436
483
  response.data = finalParsed?.data;
@@ -443,10 +490,44 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
443
490
  return response;
444
491
  }
445
492
  async *promptStream(input, serviceOptions) {
446
- const response = await this.prompt(input, serviceOptions);
447
- for (const action of response.actions ?? []) {
448
- yield { action, type: 'action' };
493
+ const pending = [];
494
+ let notify;
495
+ const runPromise = this.prompt(input, serviceOptions, {
496
+ onAction: (action) => {
497
+ pending.push(action);
498
+ notify?.();
499
+ },
500
+ });
501
+ const run = { settled: false };
502
+ const settle = runPromise.then((response) => {
503
+ run.settled = true;
504
+ notify?.();
505
+ return { response };
506
+ }, (error) => {
507
+ run.settled = true;
508
+ notify?.();
509
+ return { error: error };
510
+ });
511
+ for (;;) {
512
+ while (pending.length) {
513
+ yield { action: pending.shift(), type: 'action' };
514
+ }
515
+ if (run.settled) {
516
+ break;
517
+ }
518
+ await new Promise((resolve) => {
519
+ notify = resolve;
520
+ if (run.settled || pending.length) {
521
+ resolve();
522
+ }
523
+ });
524
+ notify = undefined;
525
+ }
526
+ const outcome = await settle;
527
+ if (outcome.error) {
528
+ throw outcome.error;
449
529
  }
530
+ const response = outcome.response;
450
531
  for (const token of this.chunkText(response.text)) {
451
532
  yield { token, type: 'token' };
452
533
  }
@@ -709,6 +790,43 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
709
790
  }
710
791
  return undefined;
711
792
  }
793
+ hitOutputCeiling(completion) {
794
+ return completion?.raw?.choices?.[0]?.finish_reason === 'length';
795
+ }
796
+ isBareJsonValue(text, truncated = false) {
797
+ const trimmed = (text ?? '').trim();
798
+ if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
799
+ return false;
800
+ }
801
+ try {
802
+ JSON.parse(trimmed);
803
+ return true;
804
+ }
805
+ catch {
806
+ return truncated;
807
+ }
808
+ }
809
+ isFencedJsonValue(text) {
810
+ const fence = (text ?? '').trim().match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
811
+ const inner = fence?.[1]?.trim();
812
+ if (!inner || (!inner.startsWith('{') && !inner.startsWith('['))) {
813
+ return false;
814
+ }
815
+ try {
816
+ JSON.parse(inner);
817
+ return true;
818
+ }
819
+ catch {
820
+ return false;
821
+ }
822
+ }
823
+ isProtocolResidue(text, parsed, truncated = false) {
824
+ if (this.isBareJsonValue(text, truncated)) {
825
+ return true;
826
+ }
827
+ const protocolShaped = !!parsed && ('tool_calls' in parsed || ('final' in parsed && typeof parsed.final !== 'string'));
828
+ return protocolShaped && this.isFencedJsonValue(text);
829
+ }
712
830
  extractJsonObject(text) {
713
831
  if (!text) {
714
832
  return null;
@@ -810,7 +928,7 @@ let CoreAiService = CoreAiService_1 = class CoreAiService {
810
928
  role: 'system',
811
929
  },
812
930
  { content: transcript, role: 'user' },
813
- ], [], { temperature: 0 });
931
+ ], [], { jsonResponse: false, temperature: 0 });
814
932
  const text = (summary?.text || '').trim();
815
933
  if (!text) {
816
934
  return 0;