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.
- package/dist/llm/defaults.yaml +2 -0
- package/dist/llm/gen/anthropic.js +6 -2
- package/dist/llm/gen/mock.js +25 -7
- package/dist/llm/gen/openai-compatible.d.ts +2 -1
- package/dist/llm/gen/openai-compatible.js +87 -18
- package/dist/llm/gen.d.ts +12 -0
- package/dist/llm/kernel-driver/drive.js +105 -1
- package/dist/log.js +35 -2
- package/dist/persistence.js +12 -1
- package/package.json +1 -1
package/dist/llm/defaults.yaml
CHANGED
|
@@ -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
|
|
1960
|
-
...(
|
|
1963
|
+
messages,
|
|
1964
|
+
...(orderedOutputs.length > 0 ? { outputs: orderedOutputs } : {}),
|
|
1961
1965
|
usage,
|
|
1962
1966
|
llmGenModel: returnedModel,
|
|
1963
1967
|
};
|
package/dist/llm/gen/mock.js
CHANGED
|
@@ -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
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
: [
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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
|
-
|
|
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.
|
|
1490
|
-
|
|
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
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
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
|
|
1698
|
-
const
|
|
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
|
|
1736
|
+
return outputs;
|
|
1703
1737
|
const reasoningContent = extractReasoningContentField(msg);
|
|
1704
1738
|
if (reasoningContent && reasoningContent.length > 0) {
|
|
1705
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
...(
|
|
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 ||
|
|
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:
|
|
322
|
+
sorted: false,
|
|
290
323
|
maxArrayLength: profile.maxArrayItems,
|
|
291
324
|
maxStringLength: profile.maxStringLength,
|
|
292
325
|
});
|
package/dist/persistence.js
CHANGED
|
@@ -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',
|