dominds 1.23.3 → 1.23.4

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.
@@ -581,6 +581,7 @@ providers:
581
581
  context_window: '204K'
582
582
  glm-5.1:
583
583
  name: GLM-5.1
584
+ optimal_max_tokens: 180000
584
585
  supports_thinking: true
585
586
  default_thinking: true
586
587
  supports_image_input: false
@@ -590,6 +591,7 @@ providers:
590
591
  context_window: '256K'
591
592
  glm-4.7:
592
593
  name: GLM-4.7
594
+ optimal_max_tokens: 180000
593
595
  supports_thinking: true
594
596
  default_thinking: false
595
597
  supports_image_input: false
@@ -1955,9 +1955,13 @@ class AnthropicGen {
1955
1955
  completionTokens,
1956
1956
  totalTokens: promptTokens + completionTokens,
1957
1957
  };
1958
+ const messages = anthropicToChatMessages(response, genseq, forceJsonResponse ? ANTHROPIC_JSON_RESPONSE_TOOL_NAME : undefined);
1959
+ const orderedOutputs = outputs.length > 0
1960
+ ? [...outputs, ...messages.map((message) => ({ kind: 'message', message }))]
1961
+ : [];
1958
1962
  return {
1959
- messages: anthropicToChatMessages(response, genseq, forceJsonResponse ? ANTHROPIC_JSON_RESPONSE_TOOL_NAME : undefined),
1960
- ...(outputs.length > 0 ? { outputs } : {}),
1963
+ messages,
1964
+ ...(orderedOutputs.length > 0 ? { outputs: orderedOutputs } : {}),
1961
1965
  usage,
1962
1966
  llmGenModel: returnedModel,
1963
1967
  };
@@ -474,6 +474,10 @@ responses:
474
474
  : `mock_func_${String(i + 1)}_${call.name}`;
475
475
  await receiver.funcCall(callId, call.name, this.normalizeFuncCallArgs(call.arguments));
476
476
  }
477
+ const invalidFuncCalls = matched?.invalidFuncCalls ?? [];
478
+ for (const call of invalidFuncCalls) {
479
+ await receiver.invalidFuncCall?.(call);
480
+ }
477
481
  return { usage, llmGenModel: modelName };
478
482
  }
479
483
  async genMoreMessages(providerConfig, agent, systemPrompt, _funcTools, _requestContext, context, genseq, abortSignal) {
@@ -575,14 +579,28 @@ responses:
575
579
  arguments: this.normalizeFuncCallArgs(call.arguments),
576
580
  };
577
581
  }) ?? [];
582
+ const invalidFuncCalls = matched?.invalidFuncCalls ?? [];
583
+ const invalidFuncCallOutputs = invalidFuncCalls.map((call) => ({
584
+ kind: 'invalid_func_call',
585
+ call,
586
+ }));
587
+ const messages = thinking !== undefined
588
+ ? saying
589
+ ? [thinking, saying, ...funcMsgs]
590
+ : [thinking, ...funcMsgs]
591
+ : saying
592
+ ? [saying, ...funcMsgs]
593
+ : [...funcMsgs];
578
594
  return {
579
- messages: thinking !== undefined
580
- ? saying
581
- ? [thinking, saying, ...funcMsgs]
582
- : [thinking, ...funcMsgs]
583
- : saying
584
- ? [saying, ...funcMsgs]
585
- : [...funcMsgs],
595
+ messages,
596
+ ...(invalidFuncCallOutputs.length > 0
597
+ ? {
598
+ outputs: [
599
+ ...messages.map((message) => ({ kind: 'message', message })),
600
+ ...invalidFuncCallOutputs,
601
+ ],
602
+ }
603
+ : {}),
586
604
  usage,
587
605
  llmGenModel: modelName,
588
606
  };
@@ -14,7 +14,7 @@ import type { ChatCompletion, ChatCompletionChunk, ChatCompletionMessageParam }
14
14
  import type { Team } from '../../team';
15
15
  import type { FuncTool } from '../../tool';
16
16
  import type { ChatMessage, ModelInfo, ProviderConfig } from '../client';
17
- import { type LlmBatchResult, type LlmFailureDisposition, type LlmGenerator, type LlmRequestContext, type LlmStreamReceiver, type LlmStreamResult } from '../gen';
17
+ import { type LlmBatchOutput, type LlmBatchResult, type LlmFailureDisposition, type LlmGenerator, type LlmRequestContext, type LlmStreamReceiver, type LlmStreamResult } from '../gen';
18
18
  type OpenAiCompatibleChatExtraParams = {
19
19
  thinking?: boolean | Record<string, unknown>;
20
20
  reasoning_effort?: NonNullable<Team.ModelParams['openai-compatible']>['reasoning_effort'];
@@ -48,6 +48,7 @@ export declare function consumeOpenAiCompatibleChatCompletionStreamForTest(args:
48
48
  abortSignal?: AbortSignal;
49
49
  }): Promise<LlmStreamResult>;
50
50
  export declare function chatCompletionToChatMessagesForTest(response: ChatCompletion, genseq: number): ChatMessage[];
51
+ export declare function chatCompletionToBatchOutputsForTest(response: ChatCompletion, genseq: number): LlmBatchOutput[];
51
52
  export declare class OpenAiCompatibleGen implements LlmGenerator {
52
53
  get apiType(): string;
53
54
  classifyFailure(error: unknown): LlmFailureDisposition | undefined;
@@ -22,6 +22,7 @@ exports.wrapOpenAiCompatibleRejectedRequestErrorForTest = wrapOpenAiCompatibleRe
22
22
  exports.buildOpenAiCompatibleRequestMessagesWrapper = buildOpenAiCompatibleRequestMessagesWrapper;
23
23
  exports.consumeOpenAiCompatibleChatCompletionStreamForTest = consumeOpenAiCompatibleChatCompletionStreamForTest;
24
24
  exports.chatCompletionToChatMessagesForTest = chatCompletionToChatMessagesForTest;
25
+ exports.chatCompletionToBatchOutputsForTest = chatCompletionToBatchOutputsForTest;
25
26
  const events_1 = require("events");
26
27
  const fs_1 = require("fs");
27
28
  const promises_1 = __importDefault(require("fs/promises"));
@@ -1475,6 +1476,24 @@ function throwOpenAiCompatibleMalformedBatchToolCall(detail) {
1475
1476
  log.error(message, error);
1476
1477
  throw error;
1477
1478
  }
1479
+ function buildInvalidStreamedToolFunctionNameCall(state) {
1480
+ return {
1481
+ provider: 'openai-compatible',
1482
+ callId: state.callId,
1483
+ detail: `OPENAI-COMPATIBLE missing streamed tool function name for callId=${state.callId}`,
1484
+ toolCallIndex: state.index,
1485
+ rawArgumentsText: state.argsJson,
1486
+ };
1487
+ }
1488
+ function buildInvalidToolFunctionNameCall(args) {
1489
+ return {
1490
+ provider: 'openai-compatible',
1491
+ callId: args.callId,
1492
+ detail: `OPENAI-COMPATIBLE missing tool function name for callId=${args.callId}`,
1493
+ toolCallIndex: args.toolCallIndex,
1494
+ rawArgumentsText: args.rawArgumentsText,
1495
+ };
1496
+ }
1478
1497
  async function maybeEmitFuncCall(state, receiver, genseq) {
1479
1498
  if (state.emitted)
1480
1499
  return;
@@ -1482,17 +1501,32 @@ async function maybeEmitFuncCall(state, receiver, genseq) {
1482
1501
  state.callId = synthesizeCallId(genseq, state.index);
1483
1502
  }
1484
1503
  if (state.name.trim().length === 0) {
1485
- const detail = `OPENAI-COMPATIBLE missing streamed tool function name for callId=${state.callId}`;
1504
+ if (state.argsJson.trim().length === 0) {
1505
+ log.warn('OPENAI-COMPATIBLE ignored empty streamed tool call placeholder', undefined, {
1506
+ callId: state.callId,
1507
+ index: state.index,
1508
+ });
1509
+ state.emitted = true;
1510
+ return;
1511
+ }
1512
+ const invalidCall = buildInvalidStreamedToolFunctionNameCall(state);
1513
+ const detail = invalidCall.detail;
1486
1514
  log.error(detail, new Error('openai_compatible_missing_tool_call_name'), {
1487
1515
  callId: state.callId,
1516
+ index: state.index,
1488
1517
  });
1489
- if (receiver.streamError) {
1490
- await receiver.streamError(detail);
1518
+ if (!receiver.invalidFuncCall) {
1519
+ if (receiver.streamError) {
1520
+ await receiver.streamError(detail);
1521
+ }
1522
+ throw buildOpenAiCompatibleStreamError({
1523
+ detail,
1524
+ kind: 'invalid_tool_call',
1525
+ });
1491
1526
  }
1492
- throw buildOpenAiCompatibleStreamError({
1493
- detail,
1494
- kind: 'invalid_tool_call',
1495
- });
1527
+ state.emitted = true;
1528
+ await receiver.invalidFuncCall(invalidCall);
1529
+ return;
1496
1530
  }
1497
1531
  state.emitted = true;
1498
1532
  const args = state.argsJson.trim().length > 0 ? state.argsJson : '{}';
@@ -1694,25 +1728,27 @@ async function consumeOpenAiCompatibleChatCompletionStreamForTest(args) {
1694
1728
  abortSignal: args.abortSignal,
1695
1729
  });
1696
1730
  }
1697
- function chatCompletionToChatMessages(response, genseq) {
1698
- const out = [];
1731
+ function chatCompletionToBatchOutputs(response, genseq) {
1732
+ const outputs = [];
1699
1733
  const choice = response.choices && response.choices.length > 0 ? response.choices[0] : undefined;
1700
1734
  const msg = choice ? choice.message : undefined;
1701
1735
  if (!msg)
1702
- return out;
1736
+ return outputs;
1703
1737
  const reasoningContent = extractReasoningContentField(msg);
1704
1738
  if (reasoningContent && reasoningContent.length > 0) {
1705
- out.push({
1739
+ const message = {
1706
1740
  type: 'thinking_msg',
1707
1741
  role: 'assistant',
1708
1742
  genseq,
1709
1743
  content: reasoningContent,
1710
1744
  reasoning: buildReasoningPayloadFromText(reasoningContent),
1711
- });
1745
+ };
1746
+ outputs.push({ kind: 'message', message });
1712
1747
  }
1713
1748
  const content = typeof msg.content === 'string' ? msg.content : null;
1714
1749
  if (content && content.length > 0) {
1715
- out.push({ type: 'saying_msg', role: 'assistant', genseq, content });
1750
+ const message = { type: 'saying_msg', role: 'assistant', genseq, content };
1751
+ outputs.push({ kind: 'message', message });
1716
1752
  }
1717
1753
  const toolCalls = msg.tool_calls;
1718
1754
  if (Array.isArray(toolCalls)) {
@@ -1730,23 +1766,48 @@ function chatCompletionToChatMessages(response, genseq) {
1730
1766
  const name = typeof call.function?.name === 'string' ? call.function.name : '';
1731
1767
  const args = typeof call.function?.arguments === 'string' ? call.function.arguments : '';
1732
1768
  if (name.trim().length === 0) {
1733
- throwOpenAiCompatibleMalformedBatchToolCall(`missing tool function name for callId=${callId}`);
1769
+ const invalidCall = buildInvalidToolFunctionNameCall({
1770
+ callId,
1771
+ toolCallIndex: index,
1772
+ rawArgumentsText: args,
1773
+ });
1774
+ log.error(invalidCall.detail, new Error('openai_compatible_missing_tool_call_name'), {
1775
+ callId,
1776
+ index,
1777
+ });
1778
+ outputs.push({ kind: 'invalid_func_call', call: invalidCall });
1779
+ continue;
1734
1780
  }
1735
- out.push({
1781
+ const message = {
1736
1782
  type: 'func_call_msg',
1737
1783
  role: 'assistant',
1738
1784
  genseq,
1739
1785
  id: callId,
1740
1786
  name,
1741
1787
  arguments: args,
1742
- });
1788
+ };
1789
+ outputs.push({ kind: 'message', message });
1743
1790
  }
1744
1791
  }
1792
+ return outputs;
1793
+ }
1794
+ function batchOutputsToChatMessages(outputs) {
1795
+ return outputs
1796
+ .filter((output) => {
1797
+ return output.kind === 'message';
1798
+ })
1799
+ .map((output) => output.message);
1800
+ }
1801
+ function chatCompletionToChatMessages(response, genseq) {
1802
+ const out = batchOutputsToChatMessages(chatCompletionToBatchOutputs(response, genseq));
1745
1803
  return out;
1746
1804
  }
1747
1805
  function chatCompletionToChatMessagesForTest(response, genseq) {
1748
1806
  return chatCompletionToChatMessages(response, genseq);
1749
1807
  }
1808
+ function chatCompletionToBatchOutputsForTest(response, genseq) {
1809
+ return chatCompletionToBatchOutputs(response, genseq);
1810
+ }
1750
1811
  class OpenAiCompatibleGen {
1751
1812
  get apiType() {
1752
1813
  return 'openai-compatible';
@@ -1898,7 +1959,15 @@ class OpenAiCompatibleGen {
1898
1959
  const response = await client.chat.completions.create(payload, {
1899
1960
  ...(abortSignal ? { signal: abortSignal } : {}),
1900
1961
  });
1901
- const messagesOut = chatCompletionToChatMessages(response, genseq);
1962
+ const batchOutputs = chatCompletionToBatchOutputs(response, genseq);
1963
+ const messagesOut = batchOutputsToChatMessages(batchOutputs);
1964
+ const orderedOutputs = outputs.length > 0
1965
+ ? [
1966
+ ...outputs,
1967
+ ...messagesOut.map((message) => ({ kind: 'message', message })),
1968
+ ...batchOutputs.filter((output) => output.kind !== 'message'),
1969
+ ]
1970
+ : batchOutputs;
1902
1971
  const usage = response.usage
1903
1972
  ? tryExtractChatUsage(response.usage)
1904
1973
  : { kind: 'unavailable' };
@@ -1907,7 +1976,7 @@ class OpenAiCompatibleGen {
1907
1976
  : undefined;
1908
1977
  return {
1909
1978
  messages: messagesOut,
1910
- ...(outputs.length > 0 ? { outputs } : {}),
1979
+ ...(orderedOutputs.length > 0 ? { outputs: orderedOutputs } : {}),
1911
1980
  usage,
1912
1981
  ...(model ? { llmGenModel: model } : {}),
1913
1982
  };
package/dist/llm/gen.d.ts CHANGED
@@ -20,6 +20,9 @@ export declare class LlmStreamErrorEmittedError extends Error {
20
20
  export type LlmBatchOutput = {
21
21
  kind: 'message';
22
22
  message: ChatMessage;
23
+ } | {
24
+ kind: 'invalid_func_call';
25
+ call: LlmInvalidFuncCall;
23
26
  } | {
24
27
  kind: 'web_search_call';
25
28
  call: LlmWebSearchCall;
@@ -138,6 +141,14 @@ export type OpenAiResponsesCustomToolCall = {
138
141
  detail?: string;
139
142
  };
140
143
  export type OpenAiResponsesNativeToolCall = OpenAiResponsesNonCustomNativeToolCall | OpenAiResponsesCustomToolCall;
144
+ export type LlmInvalidFuncCall = Readonly<{
145
+ provider: string;
146
+ callId: string;
147
+ detail: string;
148
+ toolCallIndex?: number;
149
+ rawFunctionName?: string;
150
+ rawArgumentsText?: string;
151
+ }>;
141
152
  export interface LlmStreamReceiver {
142
153
  thinkingStart: () => Promise<void>;
143
154
  thinkingChunk: (chunk: string) => Promise<void>;
@@ -149,6 +160,7 @@ export interface LlmStreamReceiver {
149
160
  rawCallId?: string;
150
161
  effectiveCallId?: string;
151
162
  }) => Promise<void>;
163
+ invalidFuncCall?: (call: LlmInvalidFuncCall) => Promise<void>;
152
164
  webSearchCall?: (call: LlmWebSearchCall) => Promise<void>;
153
165
  nativeToolCall?: (call: OpenAiResponsesNativeToolCall) => Promise<void>;
154
166
  toolResultImageIngest?: (ingest: ToolResultImageIngest) => Promise<void>;
@@ -205,6 +205,9 @@ async function persistAndEmitRuntimeGuide(dlg, content) {
205
205
  role: 'assistant',
206
206
  content,
207
207
  });
208
+ await persistAndPostRuntimeGuide(dlg, content);
209
+ }
210
+ async function persistAndPostRuntimeGuide(dlg, content) {
208
211
  await persistence_1.DialogPersistence.persistRuntimeGuide(dlg, content, dlg.activeGenSeq);
209
212
  (0, evt_registry_1.postDialogEvent)(dlg, {
210
213
  type: 'runtime_guide_evt',
@@ -301,6 +304,9 @@ function hasMeaningfulBatchOutput(batch) {
301
304
  if (output.kind === 'user_image_ingest') {
302
305
  continue;
303
306
  }
307
+ if (output.kind === 'invalid_func_call') {
308
+ return true;
309
+ }
304
310
  if (output.kind !== 'message') {
305
311
  return true;
306
312
  }
@@ -910,6 +916,75 @@ async function emitAssistantSaying(dlg, content) {
910
916
  await dlg.sayingChunk(content);
911
917
  await dlg.sayingFinish();
912
918
  }
919
+ function formatInvalidFuncCallRuntimeGuide(language, call) {
920
+ const rawName = call.rawFunctionName !== undefined && call.rawFunctionName.trim() !== ''
921
+ ? call.rawFunctionName.trim()
922
+ : '<missing>';
923
+ const rawArguments = call.rawArgumentsText !== undefined && call.rawArgumentsText.trim() !== ''
924
+ ? call.rawArgumentsText
925
+ : '<empty>';
926
+ const indexLine = call.toolCallIndex === undefined ? undefined : `- toolCallIndex: ${String(call.toolCallIndex)}`;
927
+ if (language === 'en') {
928
+ return [
929
+ '[Runtime notice] The previous model output contained an invalid tool-call payload that could not be represented as a normal provider tool call in the next generation context.',
930
+ '',
931
+ `- provider: ${call.provider}`,
932
+ `- callId: ${call.callId}`,
933
+ `- problem: ${call.detail}`,
934
+ `- rawFunctionName: ${rawName}`,
935
+ `- rawArgumentsText:`,
936
+ '```json',
937
+ rawArguments,
938
+ '```',
939
+ ...(indexLine === undefined ? [] : [indexLine]),
940
+ '',
941
+ 'Treat that payload as failed. Do not assume the tool ran. Continue from the current task, and if a tool call is still needed, emit a new valid tool call with a non-empty function name and valid arguments.',
942
+ ]
943
+ .filter((line) => line.length > 0)
944
+ .join('\n');
945
+ }
946
+ return [
947
+ '[运行时提示] 上一轮模型输出包含一个无效工具调用载荷,无法按正常 provider tool call 形态进入下一轮生成上下文。',
948
+ '',
949
+ `- provider: ${call.provider}`,
950
+ `- callId: ${call.callId}`,
951
+ `- 问题: ${call.detail}`,
952
+ `- rawFunctionName: ${rawName}`,
953
+ `- rawArgumentsText:`,
954
+ '```json',
955
+ rawArguments,
956
+ '```',
957
+ ...(indexLine === undefined ? [] : [indexLine]),
958
+ '',
959
+ '请把该载荷视为调用失败,不要假设工具已经执行。继续当前任务;如果仍需要调用工具,请重新发起一个函数名非空、参数有效的新工具调用。',
960
+ ]
961
+ .filter((line) => line.length > 0)
962
+ .join('\n');
963
+ }
964
+ async function persistInvalidFuncCallRuntimeGuide(args) {
965
+ const { dlg, call } = args;
966
+ const sourceText = args.source === 'streamed' ? 'streamed' : 'batch';
967
+ log_1.log.error(`kernel-driver received invalid ${sourceText} function call payload`, new Error(`kernel_driver_invalid_${sourceText}_function_call_payload`), {
968
+ rootId: dlg.id.rootId,
969
+ selfId: dlg.id.selfId,
970
+ course: dlg.activeGenCourseOrUndefined ?? dlg.currentCourse,
971
+ genseq: dlg.activeGenSeq,
972
+ callId: call.callId,
973
+ provider: call.provider,
974
+ detail: call.detail,
975
+ toolCallIndex: call.toolCallIndex,
976
+ });
977
+ if (args.emitStreamError) {
978
+ await dlg.streamError(call.detail);
979
+ }
980
+ const content = formatInvalidFuncCallRuntimeGuide((0, work_language_1.getWorkLanguage)(), call);
981
+ args.newMsgs.push({
982
+ type: 'transient_guide_msg',
983
+ role: 'assistant',
984
+ content,
985
+ });
986
+ await persistAndPostRuntimeGuide(dlg, content);
987
+ }
913
988
  function resolveFuncToolFollowupMode(tool) {
914
989
  return tool?.followupMode ?? 'immediate';
915
990
  }
@@ -1895,6 +1970,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1895
1970
  const streamedFuncCalls = [];
1896
1971
  let sawWebSearchSideChannelOutput = false;
1897
1972
  let sawNativeToolSideChannelOutput = false;
1973
+ let invalidFuncCallCount = 0;
1898
1974
  const streamOrBatch = async () => {
1899
1975
  let batchAttemptCourse;
1900
1976
  let batchAttemptCheckpointOffset;
@@ -1911,6 +1987,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1911
1987
  });
1912
1988
  sawWebSearchSideChannelOutput = false;
1913
1989
  sawNativeToolSideChannelOutput = false;
1990
+ invalidFuncCallCount = 0;
1914
1991
  streamedFuncCalls.length = 0;
1915
1992
  newMsgs.length = 0;
1916
1993
  };
@@ -2004,6 +2081,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2004
2081
  sawWebSearchSideChannelOutput = false;
2005
2082
  sawNativeToolSideChannelOutput = false;
2006
2083
  streamedFuncCalls.length = 0;
2084
+ invalidFuncCallCount = 0;
2007
2085
  newMsgs.length = 0;
2008
2086
  };
2009
2087
  const receiver = {
@@ -2127,6 +2205,17 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2127
2205
  arguments: argsStr,
2128
2206
  });
2129
2207
  },
2208
+ invalidFuncCall: async (call) => {
2209
+ throwIfAborted(abortSignal, dlg);
2210
+ invalidFuncCallCount += 1;
2211
+ await persistInvalidFuncCallRuntimeGuide({
2212
+ dlg,
2213
+ call,
2214
+ source: 'streamed',
2215
+ newMsgs,
2216
+ emitStreamError: true,
2217
+ });
2218
+ },
2130
2219
  webSearchCall: async (call) => {
2131
2220
  throwIfAborted(abortSignal, dlg);
2132
2221
  sawWebSearchSideChannelOutput = true;
@@ -2177,6 +2266,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2177
2266
  sawWebSearchSideChannelOutput = false;
2178
2267
  sawNativeToolSideChannelOutput = false;
2179
2268
  streamedFuncCalls.length = 0;
2269
+ invalidFuncCallCount = 0;
2180
2270
  newMsgs.length = 0;
2181
2271
  const promptCacheKey = prepareLlmRequestContextKey();
2182
2272
  const streamResult = await llmGen.genToReceiver(providerCfg, agent, systemPrompt, funcTools, {
@@ -2192,6 +2282,7 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2192
2282
  const hasFunctionCall = streamedFuncCalls.length > 0;
2193
2283
  if (!hasFinishedMessageContent &&
2194
2284
  !hasFunctionCall &&
2285
+ invalidFuncCallCount === 0 &&
2195
2286
  !sawWebSearchSideChannelOutput &&
2196
2287
  !sawNativeToolSideChannelOutput) {
2197
2288
  throw {
@@ -2259,6 +2350,17 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2259
2350
  }
2260
2351
  break;
2261
2352
  }
2353
+ case 'invalid_func_call': {
2354
+ invalidFuncCallCount += 1;
2355
+ await persistInvalidFuncCallRuntimeGuide({
2356
+ dlg,
2357
+ call: output.call,
2358
+ source: 'batch',
2359
+ newMsgs,
2360
+ emitStreamError: true,
2361
+ });
2362
+ break;
2363
+ }
2262
2364
  case 'web_search_call': {
2263
2365
  sawWebSearchSideChannelOutput = true;
2264
2366
  await dlg.webSearchCall(projectLlmWebSearchCall(output.call));
@@ -2468,7 +2570,9 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
2468
2570
  // warrant same-drive LLM reaction right away. Provider-native side-channel UI events are
2469
2571
  // meaningful output, but they are not transcript/context inputs and therefore must not
2470
2572
  // trigger another immediate generation round by themselves.
2471
- const shouldStartImmediatePostToolGeneration = routed.hasImmediateFollowupToolCalls || routed.tellaskToolOutputs.length > 0;
2573
+ const shouldStartImmediatePostToolGeneration = routed.hasImmediateFollowupToolCalls ||
2574
+ routed.tellaskToolOutputs.length > 0 ||
2575
+ invalidFuncCallCount > 0;
2472
2576
  if (!shouldStartImmediatePostToolGeneration) {
2473
2577
  const healthFirst = await maybeContinueWithHealthPromptBeforeDiligence({
2474
2578
  dlg,
package/dist/log.js CHANGED
@@ -78,6 +78,39 @@ const DETAIL_INSPECT_PROFILES = [
78
78
  maxStringLength: 192,
79
79
  },
80
80
  ];
81
+ const LOG_KEY_PRIORITY = new Map([
82
+ 'rootId',
83
+ 'selfId',
84
+ 'dialogId',
85
+ 'course',
86
+ 'genseq',
87
+ 'callId',
88
+ 'questionId',
89
+ 'agentId',
90
+ 'toolName',
91
+ 'provider',
92
+ 'model',
93
+ 'dialogClass',
94
+ 'status',
95
+ 'error',
96
+ 'detail',
97
+ 'message',
98
+ 'code',
99
+ 'name',
100
+ 'type',
101
+ ].map((key, index) => [key, index]));
102
+ function compareLogObjectKeys(left, right) {
103
+ const leftPriority = LOG_KEY_PRIORITY.get(left);
104
+ const rightPriority = LOG_KEY_PRIORITY.get(right);
105
+ if (leftPriority !== undefined || rightPriority !== undefined) {
106
+ return (leftPriority ?? Number.MAX_SAFE_INTEGER) - (rightPriority ?? Number.MAX_SAFE_INTEGER);
107
+ }
108
+ const leftInternal = left.startsWith('_') || left.startsWith('__');
109
+ const rightInternal = right.startsWith('_') || right.startsWith('__');
110
+ if (leftInternal !== rightInternal)
111
+ return leftInternal ? 1 : -1;
112
+ return left.localeCompare(right);
113
+ }
81
114
  function truncateText(value, maxChars, suffix) {
82
115
  if (maxChars <= 0) {
83
116
  return { text: '', truncated: value.length > 0 };
@@ -248,7 +281,7 @@ function pruneForLog(value, profile, depth, seen) {
248
281
  return { value: `[${ctorName} byteLength=${byteLen}]`, pruned: true };
249
282
  }
250
283
  const source = value;
251
- const allKeys = Object.keys(source).sort();
284
+ const allKeys = Object.keys(source).sort(compareLogObjectKeys);
252
285
  const visibleKeys = allKeys.slice(0, profile.maxObjectKeys);
253
286
  const ctorName = getConstructorName(value);
254
287
  const reduced = {};
@@ -286,7 +319,7 @@ function inspectAdaptive(value, maxChars) {
286
319
  depth: null,
287
320
  breakLength: 120,
288
321
  compact: false,
289
- sorted: true,
322
+ sorted: false,
290
323
  maxArrayLength: profile.maxArrayItems,
291
324
  maxStringLength: profile.maxStringLength,
292
325
  });
@@ -2573,9 +2573,20 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
2573
2573
  * Emit stream error for current generation lifecycle (uses active genseq when present)
2574
2574
  */
2575
2575
  async streamError(dialog, error) {
2576
- log_1.log.error(`Dialog stream error '${error}'`, new Error(), { dialog });
2577
2576
  const course = dialog.activeGenCourseOrUndefined ?? dialog.currentCourse;
2578
2577
  const genseq = dialog.activeGenSeqOrUndefined;
2578
+ log_1.log.error(`Dialog stream error '${error}'`, new Error(), {
2579
+ dialogId: dialog.id.valueOf(),
2580
+ rootId: dialog.id.rootId,
2581
+ selfId: dialog.id.selfId,
2582
+ course,
2583
+ genseq,
2584
+ agentId: dialog.agentId,
2585
+ dialogClass: dialog.constructor.name,
2586
+ status: dialog.status,
2587
+ activeGeneration: dialog.hasActiveGeneration,
2588
+ dialogSnapshot: dialog,
2589
+ });
2579
2590
  // Enhanced stream error event with better error classification
2580
2591
  const streamErrorEvent = {
2581
2592
  type: 'stream_error_evt',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dominds",
3
- "version": "1.23.3",
3
+ "version": "1.23.4",
4
4
  "description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
5
5
  "type": "commonjs",
6
6
  "publishConfig": {