minimal-agent 0.18.13 → 0.18.14
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/package.json +1 -3
- package/plugins/workflow-runner/src/runtime/context.js +1 -1
- package/plugins/workflow-runner/src/runtime/context.ts +1 -1
- package/plugins/workflow-runner/test/embeddedExecution.test.ts +2 -5
- package/plugins/workflow-runner/test/execLifetime.test.ts +15 -2
- package/skills/ssh-remote-dev/SKILL.md +61 -0
- package/skills/ssh-remote-dev/agents/openai.yaml +4 -0
- package/src/advisor/README.md +62 -24
- package/src/advisor/advisorNudge.js +199 -0
- package/src/advisor/advisorNudge.ts +232 -0
- package/src/advisor/deliveryReview.js +35 -12
- package/src/advisor/deliveryReview.ts +35 -11
- package/src/advisor/presentation.js +7 -10
- package/src/advisor/presentation.ts +10 -13
- package/src/advisor/reviewContext.js +22 -58
- package/src/advisor/reviewContext.ts +24 -67
- package/src/cli/configMenu.js +17 -128
- package/src/cli/configMenu.tsx +17 -193
- package/src/cli/print.js +2 -0
- package/src/cli/print.ts +2 -0
- package/src/cli/streamJson.js +2 -0
- package/src/cli/streamJson.ts +2 -0
- package/src/cli/wizards/advisorWizard.js +9 -7
- package/src/cli/wizards/advisorWizard.tsx +9 -7
- package/src/cli/wizards/contextAdvisorWizard.js +9 -7
- package/src/cli/wizards/contextAdvisorWizard.tsx +9 -7
- package/src/cli/wizards/providerPresets.js +27 -1
- package/src/cli/wizards/providerPresets.ts +44 -2
- package/src/cli/wizards/providerWizard.js +51 -10
- package/src/cli/wizards/providerWizard.tsx +59 -9
- package/src/config/configDefaults.js +1 -1
- package/src/config/configDefaults.ts +1 -1
- package/src/config/configDiagnostics.js +1 -21
- package/src/config/configDiagnostics.ts +3 -23
- package/src/config/configFile.js +11 -4
- package/src/config/configFile.ts +27 -7
- package/src/config/configManagement.js +1 -0
- package/src/config/configManagement.ts +2 -0
- package/src/config/configService.js +12 -8
- package/src/config/configService.ts +16 -11
- package/src/config/numericLimits.js +0 -4
- package/src/config/numericLimits.ts +0 -4
- package/src/config/reasoningEffort.js +16 -0
- package/src/config/reasoningEffort.ts +18 -0
- package/src/context/budgetPlan.js +1 -1
- package/src/context/budgetPlan.ts +1 -1
- package/src/context/optimizeConversation.js +1 -1
- package/src/context/optimizeConversation.ts +1 -1
- package/src/harness/stallGuard.js +8 -13
- package/src/harness/stallGuard.ts +8 -12
- package/src/llm/client.js +64 -17
- package/src/llm/client.ts +62 -7
- package/src/llm/providers/openaiFormat.js +14 -3
- package/src/llm/providers/openaiFormat.ts +17 -3
- package/src/llm/providers/responsesFormat.js +275 -0
- package/src/llm/providers/responsesFormat.ts +306 -0
- package/src/loop/README.md +18 -3
- package/src/loop/liveDiagramGate.js +63 -0
- package/src/loop/liveDiagramGate.ts +61 -0
- package/src/loop/messages.js +12 -0
- package/src/loop/messages.ts +13 -0
- package/src/loop/options.ts +7 -2
- package/src/loop/toolBatch.js +0 -1
- package/src/loop/toolBatch.ts +0 -1
- package/src/loop/toolExecutor.js +11 -46
- package/src/loop/toolExecutor.ts +12 -55
- package/src/loop/toolPresentation.js +2 -13
- package/src/loop/toolPresentation.ts +2 -13
- package/src/loop/toolSemantics.js +3 -4
- package/src/loop/toolSemantics.ts +4 -6
- package/src/loop.js +222 -214
- package/src/loop.ts +226 -232
- package/src/memory/dependencies.js +11 -3
- package/src/memory/dependencies.ts +11 -3
- package/src/memory/episodicMemory.js +59 -18
- package/src/memory/episodicMemory.ts +58 -18
- package/src/memory/experienceStore.js +4 -3
- package/src/memory/experienceStore.ts +4 -3
- package/src/memory/factCandidates.js +53 -1
- package/src/memory/factCandidates.ts +54 -1
- package/src/memory/factLearning.js +2 -2
- package/src/memory/factLearning.ts +2 -2
- package/src/memory/jobPolicy.js +24 -5
- package/src/memory/jobPolicy.ts +25 -5
- package/src/memory/learning.js +2 -2
- package/src/memory/learning.ts +2 -2
- package/src/memory/learningModel.js +7 -0
- package/src/memory/learningModel.ts +7 -0
- package/src/memory/managementService.js +8 -7
- package/src/memory/managementService.ts +16 -8
- package/src/memory/memoryService.js +104 -33
- package/src/memory/memoryService.ts +132 -28
- package/src/memory/projectKnowledge.js +39 -3
- package/src/memory/projectKnowledge.ts +45 -3
- package/src/memory/recallQuery.js +56 -0
- package/src/memory/recallQuery.ts +58 -0
- package/src/memory/retrieval.js +39 -10
- package/src/memory/retrieval.ts +46 -11
- package/src/memory/turnJournal.js +75 -10
- package/src/memory/turnJournal.ts +66 -10
- package/src/memory/types.ts +7 -1
- package/src/prompts/delegation.js +2 -1
- package/src/prompts/delegation.ts +3 -1
- package/src/prompts/policyRegistry.js +9 -12
- package/src/prompts/policyRegistry.ts +9 -12
- package/src/prompts/promptAssembly.js +6 -5
- package/src/prompts/promptAssembly.ts +8 -6
- package/src/prompts/visualPresentation.js +39 -10
- package/src/prompts/visualPresentation.ts +38 -9
- package/src/runtime/answerPreparation.js +1 -1
- package/src/runtime/answerPreparation.ts +1 -1
- package/src/runtime/fileLock.js +19 -3
- package/src/runtime/fileLock.ts +19 -3
- package/src/runtime/invocationPolicy.js +1 -1
- package/src/runtime/invocationPolicy.ts +1 -1
- package/src/runtime/outputContract.js +0 -4
- package/src/runtime/outputContract.ts +0 -7
- package/src/session/runAgentTurn.js +3 -0
- package/src/session/runAgentTurn.ts +3 -0
- package/src/team/onlineToolContract.js +0 -1
- package/src/team/onlineToolContract.ts +0 -1
- package/src/tools/advisor/advisor.js +207 -365
- package/src/tools/advisor/advisor.ts +211 -383
- package/src/tools/agent/agentTypes.js +0 -1
- package/src/tools/agent/agentTypes.ts +0 -1
- package/src/tools/agent/coordinator.js +4 -1
- package/src/tools/agent/coordinator.ts +4 -1
- package/src/tools/bash/semantics.js +4 -5
- package/src/tools/bash/semantics.ts +4 -5
- package/src/tools/capabilities.js +2 -3
- package/src/tools/capabilities.ts +2 -4
- package/src/tools/index.js +0 -16
- package/src/tools/index.ts +0 -16
- package/src/tools/memory/maintenance.js +8 -9
- package/src/tools/memory/maintenance.ts +13 -11
- package/src/tools/memory/memory.js +5 -1
- package/src/tools/memory/memory.ts +5 -0
- package/src/tools/optimizeConversation/README.md +4 -6
- package/src/tools/toolPromptGuides.js +2 -9
- package/src/tools/toolPromptGuides.ts +2 -9
- package/src/types.ts +28 -105
- package/src/ui/App.js +2 -0
- package/src/ui/App.tsx +1 -0
- package/src/ui/MessageList.js +8 -44
- package/src/ui/MessageList.tsx +3 -81
- package/src/ui/hooks/useChat.js +2 -0
- package/src/ui/hooks/useChat.ts +2 -0
- package/src/ui/toolProgress.js +1 -1
- package/src/ui/toolProgress.ts +1 -1
- package/src/web/protocol.ts +10 -3
- package/src/advisor/advisorCoordinator.js +0 -734
- package/src/advisor/advisorCoordinator.ts +0 -825
- package/src/cli/wizards/sshHostWizard.js +0 -156
- package/src/cli/wizards/sshHostWizard.tsx +0 -214
- package/src/context/sshHosts.js +0 -290
- package/src/context/sshHosts.ts +0 -312
- package/src/loop/publication.js +0 -94
- package/src/loop/publication.ts +0 -124
- package/src/runtime/finalAnswer.js +0 -9
- package/src/runtime/finalAnswer.ts +0 -13
- package/src/tools/advisor/advisorDecision.js +0 -79
- package/src/tools/advisor/advisorDecision.ts +0 -92
- package/src/tools/ssh/ssh.js +0 -152
- package/src/tools/ssh/ssh.ts +0 -167
- package/src/tools/ssh/sshAvailability.js +0 -35
- package/src/tools/ssh/sshAvailability.ts +0 -39
- package/src/tools/ssh/sshClient.js +0 -177
- package/src/tools/ssh/sshClient.ts +0 -189
- package/src/tools/ssh/sshDownload.js +0 -77
- package/src/tools/ssh/sshDownload.ts +0 -92
- package/src/tools/ssh/sshHostsTool.js +0 -36
- package/src/tools/ssh/sshHostsTool.ts +0 -48
- package/src/tools/ssh/sshUpload.js +0 -72
- package/src/tools/ssh/sshUpload.ts +0 -85
package/src/config/configFile.js
CHANGED
|
@@ -6,7 +6,12 @@ import { normalizePromptCacheMode } from '../llm/promptCache.js';
|
|
|
6
6
|
import { execSiblingDir } from '../utils/greenRoot.js';
|
|
7
7
|
import { DEFAULT_ADVISOR_CONFIG, DEFAULT_BROWSER_CONFIG, DEFAULT_COMPUTER_USE_CONFIG, DEFAULT_NETWORK_PROXY_CONFIG, DEFAULT_SUBAGENTS_CONFIG, } from './configDefaults.js';
|
|
8
8
|
import { CONFIG_LIMITS, normalizeLimited } from './numericLimits.js';
|
|
9
|
+
import { normalizeReasoningEffort } from './reasoningEffort.js';
|
|
9
10
|
export { DEFAULT_ADVISOR_CONFIG, DEFAULT_BROWSER_CONFIG, DEFAULT_COMPUTER_USE_CONFIG, DEFAULT_NETWORK_PROXY_CONFIG, DEFAULT_SUBAGENTS_CONFIG, } from './configDefaults.js';
|
|
11
|
+
export { REASONING_EFFORTS, normalizeReasoningEffort } from './reasoningEffort.js';
|
|
12
|
+
export function normalizeApiFormat(value) {
|
|
13
|
+
return value === 'anthropic' || value === 'openai-responses' ? value : 'openai';
|
|
14
|
+
}
|
|
10
15
|
export const DEFAULT_CONTEXT_WINDOW = 128_000;
|
|
11
16
|
const LOCK_STALE_MS = 120_000;
|
|
12
17
|
const LOCK_WAIT_MS = 15_000;
|
|
@@ -64,7 +69,7 @@ function parseModel(value) {
|
|
|
64
69
|
const now = Date.now();
|
|
65
70
|
return {
|
|
66
71
|
id,
|
|
67
|
-
apiFormat: raw.apiFormat
|
|
72
|
+
apiFormat: normalizeApiFormat(raw.apiFormat),
|
|
68
73
|
...(displayName ? { displayName } : {}),
|
|
69
74
|
baseURL,
|
|
70
75
|
apiKey,
|
|
@@ -76,6 +81,9 @@ function parseModel(value) {
|
|
|
76
81
|
? { supportsJsonSchema: raw.supportsJsonSchema }
|
|
77
82
|
: {}),
|
|
78
83
|
...(typeof raw.reasoning === 'boolean' ? { reasoning: raw.reasoning } : {}),
|
|
84
|
+
...(normalizeReasoningEffort(raw.reasoningEffort)
|
|
85
|
+
? { reasoningEffort: normalizeReasoningEffort(raw.reasoningEffort) }
|
|
86
|
+
: {}),
|
|
79
87
|
promptCache: {
|
|
80
88
|
mode: normalizePromptCacheMode(raw.promptCache?.mode
|
|
81
89
|
?? defaultPromptCacheMode(baseURL)),
|
|
@@ -150,9 +158,9 @@ function parseAdvisor(value) {
|
|
|
150
158
|
// 默认关闭;旧配置显式 enabled:true 仍保持用户选择。
|
|
151
159
|
enabled: raw.enabled === true,
|
|
152
160
|
mode: raw.mode === 'manual' ? 'manual' : 'auto',
|
|
161
|
+
enforcement: raw.enforcement === 'followup' ? 'followup' : 'remind',
|
|
153
162
|
modelId: nonEmpty(raw.modelId) ?? null,
|
|
154
163
|
contextPolicy: 'full-relevant',
|
|
155
|
-
shareSensitive: raw.shareSensitive === true,
|
|
156
164
|
inputTokenBudget: normalizeLimited(raw.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget, DEFAULT_ADVISOR_CONFIG.inputTokenBudget),
|
|
157
165
|
timeoutMs: normalizeLimited(raw.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs, DEFAULT_ADVISOR_CONFIG.timeoutMs),
|
|
158
166
|
};
|
|
@@ -262,7 +270,6 @@ function parseLegacyAdvisorConfig(value) {
|
|
|
262
270
|
mode: raw.mode === 'manual' ? 'manual' : 'auto',
|
|
263
271
|
provider,
|
|
264
272
|
supportsVision: raw.supportsVision === true,
|
|
265
|
-
shareSensitive: raw.shareSensitive === true,
|
|
266
273
|
inputTokenBudget: normalizeLimited(raw.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget, DEFAULT_ADVISOR_CONFIG.inputTokenBudget),
|
|
267
274
|
timeoutMs: normalizeLimited(raw.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs, DEFAULT_ADVISOR_CONFIG.timeoutMs),
|
|
268
275
|
};
|
|
@@ -319,9 +326,9 @@ function buildV4FromLegacy(legacyProvider, legacyAdvisor, subagents, tools, save
|
|
|
319
326
|
advisor = {
|
|
320
327
|
enabled: legacyAdvisor.enabled,
|
|
321
328
|
mode: legacyAdvisor.mode,
|
|
329
|
+
enforcement: 'remind',
|
|
322
330
|
modelId: advisorModelId,
|
|
323
331
|
contextPolicy: 'full-relevant',
|
|
324
|
-
shareSensitive: legacyAdvisor.shareSensitive,
|
|
325
332
|
inputTokenBudget: legacyAdvisor.inputTokenBudget,
|
|
326
333
|
timeoutMs: legacyAdvisor.timeoutMs,
|
|
327
334
|
};
|
package/src/config/configFile.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
DEFAULT_SUBAGENTS_CONFIG,
|
|
15
15
|
} from './configDefaults.js';
|
|
16
16
|
import { CONFIG_LIMITS, normalizeLimited } from './numericLimits.js';
|
|
17
|
+
import { type ReasoningEffort, normalizeReasoningEffort } from './reasoningEffort.js';
|
|
17
18
|
|
|
18
19
|
export {
|
|
19
20
|
DEFAULT_ADVISOR_CONFIG,
|
|
@@ -24,7 +25,19 @@ export {
|
|
|
24
25
|
} from './configDefaults.js';
|
|
25
26
|
|
|
26
27
|
export type ImageProtocol = 'auto' | 'chat' | 'images';
|
|
27
|
-
|
|
28
|
+
/**
|
|
29
|
+
* openai Chat Completions(DeepSeek/月之暗面/智谱/火山/MiniMax/OpenRouter 都按它兼容)
|
|
30
|
+
* openai-responses OpenAI Responses API(/v1/responses,OpenAI 当前主推接口)
|
|
31
|
+
* anthropic Anthropic Messages API
|
|
32
|
+
*/
|
|
33
|
+
export type ApiFormat = 'openai' | 'openai-responses' | 'anthropic';
|
|
34
|
+
|
|
35
|
+
export { REASONING_EFFORTS, normalizeReasoningEffort, type ReasoningEffort } from './reasoningEffort.js';
|
|
36
|
+
|
|
37
|
+
export function normalizeApiFormat(value: unknown): ApiFormat {
|
|
38
|
+
return value === 'anthropic' || value === 'openai-responses' ? value : 'openai';
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
|
|
29
42
|
/** 一个模型条目——「模型列表」的元素,基座模型和顾问模型都从这里引用。 */
|
|
30
43
|
export interface ModelConfig {
|
|
@@ -42,6 +55,8 @@ export interface ModelConfig {
|
|
|
42
55
|
supportsJsonSchema?: boolean;
|
|
43
56
|
/** Request provider reasoning when supported (serialized as reasoning.enabled). */
|
|
44
57
|
reasoning?: boolean;
|
|
58
|
+
/** 推理强度;缺省 = 不发送,沿用服务端对该模型的默认强度。 */
|
|
59
|
+
reasoningEffort?: ReasoningEffort;
|
|
45
60
|
promptCache?: PromptCacheConfig;
|
|
46
61
|
enabled: boolean;
|
|
47
62
|
createdAt: number;
|
|
@@ -54,10 +69,14 @@ export type WorkflowModelRoles = Record<string, string>;
|
|
|
54
69
|
export interface AdvisorConfig {
|
|
55
70
|
enabled: boolean;
|
|
56
71
|
mode: 'auto' | 'manual';
|
|
72
|
+
/**
|
|
73
|
+
* remind = 只提醒(默认);followup = 实质回答发布后仍未复核时,再发一次请求让模型自己补问顾问。
|
|
74
|
+
* 给不会主动咨询的弱基座模型用;回答不撤回,Advisor 仍由模型自己调用。
|
|
75
|
+
*/
|
|
76
|
+
enforcement: 'remind' | 'followup';
|
|
57
77
|
/** 引用 models[].id;null = 未选。顾问不再自带一整套独立 provider 字段。 */
|
|
58
78
|
modelId: string | null;
|
|
59
79
|
contextPolicy: 'full-relevant';
|
|
60
|
-
shareSensitive: boolean;
|
|
61
80
|
/** 顾问单次输入预算。独立于模型声明的上下文窗口,避免百万窗口吞入整段历史。 */
|
|
62
81
|
inputTokenBudget: number;
|
|
63
82
|
timeoutMs: number;
|
|
@@ -206,7 +225,7 @@ function parseModel(value: unknown): ModelConfig | null {
|
|
|
206
225
|
const now = Date.now();
|
|
207
226
|
return {
|
|
208
227
|
id,
|
|
209
|
-
apiFormat: raw.apiFormat
|
|
228
|
+
apiFormat: normalizeApiFormat(raw.apiFormat),
|
|
210
229
|
...(displayName ? { displayName } : {}),
|
|
211
230
|
baseURL,
|
|
212
231
|
apiKey,
|
|
@@ -218,6 +237,9 @@ function parseModel(value: unknown): ModelConfig | null {
|
|
|
218
237
|
? { supportsJsonSchema: raw.supportsJsonSchema }
|
|
219
238
|
: {}),
|
|
220
239
|
...(typeof raw.reasoning === 'boolean' ? { reasoning: raw.reasoning } : {}),
|
|
240
|
+
...(normalizeReasoningEffort(raw.reasoningEffort)
|
|
241
|
+
? { reasoningEffort: normalizeReasoningEffort(raw.reasoningEffort) }
|
|
242
|
+
: {}),
|
|
221
243
|
promptCache: {
|
|
222
244
|
mode: normalizePromptCacheMode(
|
|
223
245
|
(raw.promptCache as Record<string, unknown> | undefined)?.mode
|
|
@@ -291,9 +313,9 @@ function parseAdvisor(value: unknown): AdvisorConfig | undefined {
|
|
|
291
313
|
// 默认关闭;旧配置显式 enabled:true 仍保持用户选择。
|
|
292
314
|
enabled: raw.enabled === true,
|
|
293
315
|
mode: raw.mode === 'manual' ? 'manual' : 'auto',
|
|
316
|
+
enforcement: raw.enforcement === 'followup' ? 'followup' : 'remind',
|
|
294
317
|
modelId: nonEmpty(raw.modelId) ?? null,
|
|
295
318
|
contextPolicy: 'full-relevant',
|
|
296
|
-
shareSensitive: raw.shareSensitive === true,
|
|
297
319
|
inputTokenBudget: normalizeLimited(raw.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget, DEFAULT_ADVISOR_CONFIG.inputTokenBudget),
|
|
298
320
|
timeoutMs: normalizeLimited(raw.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs, DEFAULT_ADVISOR_CONFIG.timeoutMs),
|
|
299
321
|
};
|
|
@@ -394,7 +416,6 @@ interface LegacyAdvisorConfig {
|
|
|
394
416
|
mode: 'auto' | 'manual';
|
|
395
417
|
provider: LegacyProviderConfig;
|
|
396
418
|
supportsVision: boolean;
|
|
397
|
-
shareSensitive: boolean;
|
|
398
419
|
inputTokenBudget: number;
|
|
399
420
|
timeoutMs: number;
|
|
400
421
|
}
|
|
@@ -428,7 +449,6 @@ function parseLegacyAdvisorConfig(value: unknown): LegacyAdvisorConfig | undefin
|
|
|
428
449
|
mode: raw.mode === 'manual' ? 'manual' : 'auto',
|
|
429
450
|
provider,
|
|
430
451
|
supportsVision: raw.supportsVision === true,
|
|
431
|
-
shareSensitive: raw.shareSensitive === true,
|
|
432
452
|
inputTokenBudget: normalizeLimited(raw.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget, DEFAULT_ADVISOR_CONFIG.inputTokenBudget),
|
|
433
453
|
timeoutMs: normalizeLimited(raw.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs, DEFAULT_ADVISOR_CONFIG.timeoutMs),
|
|
434
454
|
};
|
|
@@ -490,9 +510,9 @@ function buildV4FromLegacy(
|
|
|
490
510
|
advisor = {
|
|
491
511
|
enabled: legacyAdvisor.enabled,
|
|
492
512
|
mode: legacyAdvisor.mode,
|
|
513
|
+
enforcement: 'remind',
|
|
493
514
|
modelId: advisorModelId,
|
|
494
515
|
contextPolicy: 'full-relevant',
|
|
495
|
-
shareSensitive: legacyAdvisor.shareSensitive,
|
|
496
516
|
inputTokenBudget: legacyAdvisor.inputTokenBudget,
|
|
497
517
|
timeoutMs: legacyAdvisor.timeoutMs,
|
|
498
518
|
};
|
|
@@ -33,6 +33,7 @@ export function buildConfigManagementView(snapshot) {
|
|
|
33
33
|
contextWindow: model.contextWindow,
|
|
34
34
|
...(model.maxTokens ? { maxTokens: model.maxTokens } : {}),
|
|
35
35
|
...(model.supportsVision ? { supportsVision: true } : {}),
|
|
36
|
+
...(model.reasoningEffort ? { reasoningEffort: model.reasoningEffort } : {}),
|
|
36
37
|
promptCache: model.promptCache ?? { mode: 'auto' },
|
|
37
38
|
enabled: model.enabled,
|
|
38
39
|
updatedAt: model.updatedAt,
|
|
@@ -23,6 +23,7 @@ export interface ManagedModelView {
|
|
|
23
23
|
contextWindow: number;
|
|
24
24
|
maxTokens?: number;
|
|
25
25
|
supportsVision?: boolean;
|
|
26
|
+
reasoningEffort?: ModelConfig['reasoningEffort'];
|
|
26
27
|
promptCache: NonNullable<ModelConfig['promptCache']>;
|
|
27
28
|
enabled: boolean;
|
|
28
29
|
updatedAt: number;
|
|
@@ -63,6 +64,7 @@ export function buildConfigManagementView(snapshot: ConfigSnapshot) {
|
|
|
63
64
|
contextWindow: model.contextWindow,
|
|
64
65
|
...(model.maxTokens ? { maxTokens: model.maxTokens } : {}),
|
|
65
66
|
...(model.supportsVision ? { supportsVision: true } : {}),
|
|
67
|
+
...(model.reasoningEffort ? { reasoningEffort: model.reasoningEffort } : {}),
|
|
66
68
|
promptCache: model.promptCache ?? { mode: 'auto' },
|
|
67
69
|
enabled: model.enabled,
|
|
68
70
|
updatedAt: model.updatedAt,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { modelRefFromLegacy, } from '../modelRef.js';
|
|
3
3
|
import { fetchOnlineModels, loadTeamCredentials, resolveOnlineModel, } from '../team/auth.js';
|
|
4
|
-
import { DEFAULT_ADVISOR_CONFIG, DEFAULT_BROWSER_CONFIG, DEFAULT_COMPUTER_USE_CONFIG, DEFAULT_NETWORK_PROXY_CONFIG, DEFAULT_SUBAGENTS_CONFIG, defaultMaxTokens, readMinimalAgentConfig, updateMinimalAgentConfig, } from './configFile.js';
|
|
4
|
+
import { normalizeApiFormat, normalizeReasoningEffort, DEFAULT_ADVISOR_CONFIG, DEFAULT_BROWSER_CONFIG, DEFAULT_COMPUTER_USE_CONFIG, DEFAULT_NETWORK_PROXY_CONFIG, DEFAULT_SUBAGENTS_CONFIG, defaultMaxTokens, readMinimalAgentConfig, updateMinimalAgentConfig, } from './configFile.js';
|
|
5
5
|
import { CONFIG_LIMITS, normalizeLimited } from './numericLimits.js';
|
|
6
6
|
import { applyNetworkProxy } from '../network/proxy.js';
|
|
7
7
|
const DEFAULT_CONTEXT_WINDOW = 128_000;
|
|
@@ -169,6 +169,7 @@ function resolveProvider(entry, compactRatio) {
|
|
|
169
169
|
? { supportsJsonSchema: entry.supportsJsonSchema }
|
|
170
170
|
: {}),
|
|
171
171
|
...(entry.reasoning === true ? { reasoning: true } : {}),
|
|
172
|
+
...(entry.reasoningEffort ? { reasoningEffort: entry.reasoningEffort } : {}),
|
|
172
173
|
promptCache: entry.promptCache ?? { mode: 'auto' },
|
|
173
174
|
...(compactRatio !== undefined ? { compactRatio } : {}),
|
|
174
175
|
// cache_edits 式回收:仅 Anthropic 格式 + 显式 env 开启时生效(非公开协议,
|
|
@@ -208,7 +209,7 @@ function applyModelsPatch(models, ops) {
|
|
|
208
209
|
for (const item of ops) {
|
|
209
210
|
if (item.op === 'add') {
|
|
210
211
|
const m = item.model;
|
|
211
|
-
const apiFormat = m.apiFormat
|
|
212
|
+
const apiFormat = normalizeApiFormat(m.apiFormat);
|
|
212
213
|
const baseURL = m.baseURL?.trim();
|
|
213
214
|
const modelId = m.model?.trim();
|
|
214
215
|
const apiKey = m.apiKey?.trim();
|
|
@@ -230,6 +231,9 @@ function applyModelsPatch(models, ops) {
|
|
|
230
231
|
? { supportsJsonSchema: m.supportsJsonSchema }
|
|
231
232
|
: {}),
|
|
232
233
|
...(m.reasoning !== undefined ? { reasoning: m.reasoning === true } : {}),
|
|
234
|
+
...(normalizeReasoningEffort(m.reasoningEffort)
|
|
235
|
+
? { reasoningEffort: normalizeReasoningEffort(m.reasoningEffort) }
|
|
236
|
+
: {}),
|
|
233
237
|
promptCache: m.promptCache ?? { mode: 'auto' },
|
|
234
238
|
enabled: m.enabled ?? true,
|
|
235
239
|
createdAt: now,
|
|
@@ -244,11 +248,7 @@ function applyModelsPatch(models, ops) {
|
|
|
244
248
|
const patch = item.patch;
|
|
245
249
|
const next = {
|
|
246
250
|
...existing,
|
|
247
|
-
...(patch.apiFormat
|
|
248
|
-
? {
|
|
249
|
-
apiFormat: patch.apiFormat === 'anthropic' ? 'anthropic' : 'openai',
|
|
250
|
-
}
|
|
251
|
-
: {}),
|
|
251
|
+
...(patch.apiFormat ? { apiFormat: normalizeApiFormat(patch.apiFormat) } : {}),
|
|
252
252
|
...(patch.displayName !== undefined
|
|
253
253
|
? { displayName: patch.displayName.trim() || undefined }
|
|
254
254
|
: {}),
|
|
@@ -267,6 +267,10 @@ function applyModelsPatch(models, ops) {
|
|
|
267
267
|
...(patch.reasoning !== undefined
|
|
268
268
|
? { reasoning: patch.reasoning === true }
|
|
269
269
|
: {}),
|
|
270
|
+
// null = 清除(回到服务端默认强度);未提供 = 不动。
|
|
271
|
+
...(patch.reasoningEffort !== undefined
|
|
272
|
+
? { reasoningEffort: normalizeReasoningEffort(patch.reasoningEffort) }
|
|
273
|
+
: {}),
|
|
270
274
|
...(patch.promptCache ? { promptCache: patch.promptCache } : {}),
|
|
271
275
|
...(patch.enabled !== undefined ? { enabled: patch.enabled } : {}),
|
|
272
276
|
updatedAt: now,
|
|
@@ -332,11 +336,11 @@ function applyConfigPatch(base, patch) {
|
|
|
332
336
|
advisor = {
|
|
333
337
|
enabled: patch.advisor.enabled ?? advisor?.enabled ?? DEFAULT_ADVISOR_CONFIG.enabled,
|
|
334
338
|
mode: patch.advisor.mode ?? advisor?.mode ?? 'auto',
|
|
339
|
+
enforcement: patch.advisor.enforcement ?? advisor?.enforcement ?? 'remind',
|
|
335
340
|
modelId: patch.advisor.modelId !== undefined
|
|
336
341
|
? patch.advisor.modelId
|
|
337
342
|
: (advisor?.modelId ?? null),
|
|
338
343
|
contextPolicy: 'full-relevant',
|
|
339
|
-
shareSensitive: patch.advisor.shareSensitive ?? advisor?.shareSensitive ?? false,
|
|
340
344
|
inputTokenBudget: normalizeLimited(patch.advisor.inputTokenBudget ?? advisor?.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget, DEFAULT_ADVISOR_CONFIG.inputTokenBudget),
|
|
341
345
|
timeoutMs: normalizeLimited(patch.advisor.timeoutMs ?? advisor?.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs, DEFAULT_ADVISOR_CONFIG.timeoutMs),
|
|
342
346
|
};
|
|
@@ -16,6 +16,8 @@ import type { GatewayProvider, LocalProvider, Provider } from '../types.js';
|
|
|
16
16
|
import {
|
|
17
17
|
type AdvisorConfig,
|
|
18
18
|
type ApiFormat,
|
|
19
|
+
normalizeApiFormat,
|
|
20
|
+
normalizeReasoningEffort,
|
|
19
21
|
type BrowserConfig,
|
|
20
22
|
type ComputerUseConfig,
|
|
21
23
|
DEFAULT_ADVISOR_CONFIG,
|
|
@@ -66,8 +68,10 @@ export type ModelOp =
|
|
|
66
68
|
| {
|
|
67
69
|
op: 'update';
|
|
68
70
|
id: string;
|
|
69
|
-
patch: Partial<Omit<ModelConfig, 'id' | 'createdAt' | 'updatedAt'>> & {
|
|
71
|
+
patch: Partial<Omit<ModelConfig, 'id' | 'createdAt' | 'updatedAt' | 'reasoningEffort'>> & {
|
|
70
72
|
clearApiKey?: boolean;
|
|
73
|
+
/** null = 清除,回到服务端对该模型的默认强度。 */
|
|
74
|
+
reasoningEffort?: ModelConfig['reasoningEffort'] | null;
|
|
71
75
|
};
|
|
72
76
|
}
|
|
73
77
|
| { op: 'remove'; id: string };
|
|
@@ -311,6 +315,7 @@ function resolveProvider(
|
|
|
311
315
|
? { supportsJsonSchema: entry.supportsJsonSchema }
|
|
312
316
|
: {}),
|
|
313
317
|
...(entry.reasoning === true ? { reasoning: true } : {}),
|
|
318
|
+
...(entry.reasoningEffort ? { reasoningEffort: entry.reasoningEffort } : {}),
|
|
314
319
|
promptCache: entry.promptCache ?? { mode: 'auto' },
|
|
315
320
|
...(compactRatio !== undefined ? { compactRatio } : {}),
|
|
316
321
|
// cache_edits 式回收:仅 Anthropic 格式 + 显式 env 开启时生效(非公开协议,
|
|
@@ -364,8 +369,7 @@ function applyModelsPatch(
|
|
|
364
369
|
for (const item of ops) {
|
|
365
370
|
if (item.op === 'add') {
|
|
366
371
|
const m = item.model;
|
|
367
|
-
const apiFormat: ApiFormat =
|
|
368
|
-
m.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
|
|
372
|
+
const apiFormat: ApiFormat = normalizeApiFormat(m.apiFormat);
|
|
369
373
|
const baseURL = m.baseURL?.trim();
|
|
370
374
|
const modelId = m.model?.trim();
|
|
371
375
|
const apiKey = m.apiKey?.trim();
|
|
@@ -388,6 +392,9 @@ function applyModelsPatch(
|
|
|
388
392
|
? { supportsJsonSchema: m.supportsJsonSchema }
|
|
389
393
|
: {}),
|
|
390
394
|
...(m.reasoning !== undefined ? { reasoning: m.reasoning === true } : {}),
|
|
395
|
+
...(normalizeReasoningEffort(m.reasoningEffort)
|
|
396
|
+
? { reasoningEffort: normalizeReasoningEffort(m.reasoningEffort) }
|
|
397
|
+
: {}),
|
|
391
398
|
promptCache: m.promptCache ?? { mode: 'auto' },
|
|
392
399
|
enabled: m.enabled ?? true,
|
|
393
400
|
createdAt: now,
|
|
@@ -400,12 +407,7 @@ function applyModelsPatch(
|
|
|
400
407
|
const patch = item.patch;
|
|
401
408
|
const next: ModelConfig = {
|
|
402
409
|
...existing,
|
|
403
|
-
...(patch.apiFormat
|
|
404
|
-
? {
|
|
405
|
-
apiFormat:
|
|
406
|
-
patch.apiFormat === 'anthropic' ? 'anthropic' : 'openai',
|
|
407
|
-
}
|
|
408
|
-
: {}),
|
|
410
|
+
...(patch.apiFormat ? { apiFormat: normalizeApiFormat(patch.apiFormat) } : {}),
|
|
409
411
|
...(patch.displayName !== undefined
|
|
410
412
|
? { displayName: patch.displayName.trim() || undefined }
|
|
411
413
|
: {}),
|
|
@@ -424,6 +426,10 @@ function applyModelsPatch(
|
|
|
424
426
|
...(patch.reasoning !== undefined
|
|
425
427
|
? { reasoning: patch.reasoning === true }
|
|
426
428
|
: {}),
|
|
429
|
+
// null = 清除(回到服务端默认强度);未提供 = 不动。
|
|
430
|
+
...(patch.reasoningEffort !== undefined
|
|
431
|
+
? { reasoningEffort: normalizeReasoningEffort(patch.reasoningEffort) }
|
|
432
|
+
: {}),
|
|
427
433
|
...(patch.promptCache ? { promptCache: patch.promptCache } : {}),
|
|
428
434
|
...(patch.enabled !== undefined ? { enabled: patch.enabled } : {}),
|
|
429
435
|
updatedAt: now,
|
|
@@ -498,13 +504,12 @@ function applyConfigPatch(
|
|
|
498
504
|
advisor = {
|
|
499
505
|
enabled: patch.advisor.enabled ?? advisor?.enabled ?? DEFAULT_ADVISOR_CONFIG.enabled,
|
|
500
506
|
mode: patch.advisor.mode ?? advisor?.mode ?? 'auto',
|
|
507
|
+
enforcement: patch.advisor.enforcement ?? advisor?.enforcement ?? 'remind',
|
|
501
508
|
modelId:
|
|
502
509
|
patch.advisor.modelId !== undefined
|
|
503
510
|
? patch.advisor.modelId
|
|
504
511
|
: (advisor?.modelId ?? null),
|
|
505
512
|
contextPolicy: 'full-relevant',
|
|
506
|
-
shareSensitive:
|
|
507
|
-
patch.advisor.shareSensitive ?? advisor?.shareSensitive ?? false,
|
|
508
513
|
inputTokenBudget: normalizeLimited(
|
|
509
514
|
patch.advisor.inputTokenBudget ?? advisor?.inputTokenBudget,
|
|
510
515
|
CONFIG_LIMITS.advisorInputTokenBudget,
|
|
@@ -62,10 +62,6 @@ export const CONFIG_LIMITS = {
|
|
|
62
62
|
modelContextWindow: { min: 1_000, max: 20_000_000, step: 1_000, kind: 'integer' },
|
|
63
63
|
/** 模型条目的单次输出上限(可留空 = 用公式推荐值,故 UI 允许空串,这里只约束填了值的情况)。 */
|
|
64
64
|
modelMaxTokens: { min: 256, max: 1_000_000, step: 256, kind: 'integer' },
|
|
65
|
-
/** SSH 主机端口。TCP 端口的合法范围。 */
|
|
66
|
-
sshPort: { min: 1, max: 65_535, step: 1, kind: 'integer' },
|
|
67
|
-
/** SSH 单次操作(连接+执行/传输)超时(毫秒),上界给到 10 分钟容纳慢速链路上的大文件传输。 */
|
|
68
|
-
sshTimeoutMs: { min: 1_000, max: 600_000, step: 1_000, kind: 'integer' },
|
|
69
65
|
};
|
|
70
66
|
/** 比例类字段保留的小数位(4 位比例 = 2 位百分比)。 */
|
|
71
67
|
const RATIO_DECIMALS = 4;
|
|
@@ -79,10 +79,6 @@ export const CONFIG_LIMITS = {
|
|
|
79
79
|
/** 模型条目的单次输出上限(可留空 = 用公式推荐值,故 UI 允许空串,这里只约束填了值的情况)。 */
|
|
80
80
|
modelMaxTokens: { min: 256, max: 1_000_000, step: 256, kind: 'integer' },
|
|
81
81
|
|
|
82
|
-
/** SSH 主机端口。TCP 端口的合法范围。 */
|
|
83
|
-
sshPort: { min: 1, max: 65_535, step: 1, kind: 'integer' },
|
|
84
|
-
/** SSH 单次操作(连接+执行/传输)超时(毫秒),上界给到 10 分钟容纳慢速链路上的大文件传输。 */
|
|
85
|
-
sshTimeoutMs: { min: 1_000, max: 600_000, step: 1_000, kind: 'integer' },
|
|
86
82
|
} as const satisfies Record<string, NumericLimit>;
|
|
87
83
|
|
|
88
84
|
export type ConfigLimitKey = keyof typeof CONFIG_LIMITS;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 推理强度(纯逻辑、零依赖)。
|
|
3
|
+
*
|
|
4
|
+
* 独立成文件是因为 Desktop 的浏览器端经 `minimal-agent/provider-presets` 引用它:
|
|
5
|
+
* 放在 configFile.ts 里会把 node:fs 等整串依赖拖进前端包。
|
|
6
|
+
*
|
|
7
|
+
* 不同模型认的档位不同(有的没有 none/minimal,有的才有 xhigh),所以这里只收「OpenAI
|
|
8
|
+
* 系文档出现过的全部取值」,具体某个模型接不接受由服务端裁决:被拒绝时 client.ts 会去掉
|
|
9
|
+
* 该参数重发一次并告警,而不是让整个对话 400。
|
|
10
|
+
*/
|
|
11
|
+
export const REASONING_EFFORTS = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
12
|
+
export function normalizeReasoningEffort(value) {
|
|
13
|
+
return typeof value === 'string' && REASONING_EFFORTS.includes(value)
|
|
14
|
+
? value
|
|
15
|
+
: undefined;
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 推理强度(纯逻辑、零依赖)。
|
|
3
|
+
*
|
|
4
|
+
* 独立成文件是因为 Desktop 的浏览器端经 `minimal-agent/provider-presets` 引用它:
|
|
5
|
+
* 放在 configFile.ts 里会把 node:fs 等整串依赖拖进前端包。
|
|
6
|
+
*
|
|
7
|
+
* 不同模型认的档位不同(有的没有 none/minimal,有的才有 xhigh),所以这里只收「OpenAI
|
|
8
|
+
* 系文档出现过的全部取值」,具体某个模型接不接受由服务端裁决:被拒绝时 client.ts 会去掉
|
|
9
|
+
* 该参数重发一次并告警,而不是让整个对话 400。
|
|
10
|
+
*/
|
|
11
|
+
export const REASONING_EFFORTS = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'] as const;
|
|
12
|
+
export type ReasoningEffort = (typeof REASONING_EFFORTS)[number];
|
|
13
|
+
|
|
14
|
+
export function normalizeReasoningEffort(value: unknown): ReasoningEffort | undefined {
|
|
15
|
+
return typeof value === 'string' && (REASONING_EFFORTS as readonly string[]).includes(value)
|
|
16
|
+
? (value as ReasoningEffort)
|
|
17
|
+
: undefined;
|
|
18
|
+
}
|
|
@@ -20,7 +20,7 @@ export function buildContextBudgetPlan(input) {
|
|
|
20
20
|
overBudget: totalInputTokens > inputLimit,
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
-
const AUXILIARY_REMOVAL_ORDER = ['
|
|
23
|
+
const AUXILIARY_REMOVAL_ORDER = ['Advisor', 'Agent'];
|
|
24
24
|
/**
|
|
25
25
|
* Last-resort schema reduction. Normal requests keep the full catalog; this is
|
|
26
26
|
* used only after history compaction still cannot fit the provider window.
|
|
@@ -47,7 +47,7 @@ export interface EmergencyToolFit {
|
|
|
47
47
|
plan: ContextBudgetPlan;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const AUXILIARY_REMOVAL_ORDER = ['
|
|
50
|
+
const AUXILIARY_REMOVAL_ORDER = ['Advisor', 'Agent'];
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Last-resort schema reduction. Normal requests keep the full catalog; this is
|
|
@@ -41,7 +41,7 @@ export function createConversationOptimizer(options) {
|
|
|
41
41
|
degraded: false, before: compact.before, after: compact.after,
|
|
42
42
|
messagesRemoved: compact.messagesRemoved, tokensFreed: compact.tokensFreed,
|
|
43
43
|
});
|
|
44
|
-
return { ok: true, content: `已优化对话:已完成历史的估算 token 从 ${compact.before} 降至 ${compact.after},释放 ${compact.tokensFreed}
|
|
44
|
+
return { ok: true, content: `已优化对话:已完成历史的估算 token 从 ${compact.before} 降至 ${compact.after},释放 ${compact.tokensFreed}。近期消息和当前工具调用保留;历史证据保留在本机会话中;顾问评审时会一并展开这些原始记录。本结果不是一手证据。继续未完成任务,无需复述摘要。` };
|
|
45
45
|
}
|
|
46
46
|
catch {
|
|
47
47
|
return { ok: false, error: signal?.aborted ? 'aborted'
|
|
@@ -48,7 +48,7 @@ export function createConversationOptimizer(options: {
|
|
|
48
48
|
degraded: false, before: compact.before, after: compact.after,
|
|
49
49
|
messagesRemoved: compact.messagesRemoved, tokensFreed: compact.tokensFreed,
|
|
50
50
|
});
|
|
51
|
-
return { ok: true, content: `已优化对话:已完成历史的估算 token 从 ${compact.before} 降至 ${compact.after},释放 ${compact.tokensFreed}
|
|
51
|
+
return { ok: true, content: `已优化对话:已完成历史的估算 token 从 ${compact.before} 降至 ${compact.after},释放 ${compact.tokensFreed}。近期消息和当前工具调用保留;历史证据保留在本机会话中;顾问评审时会一并展开这些原始记录。本结果不是一手证据。继续未完成任务,无需复述摘要。` };
|
|
52
52
|
} catch {
|
|
53
53
|
return { ok: false, error: signal?.aborted ? 'aborted'
|
|
54
54
|
: '优化未成功生成有效摘要,原历史保持不变。继续任务,不要重复调用。' };
|
|
@@ -12,18 +12,13 @@ export class StallGuard {
|
|
|
12
12
|
#sequence = 0;
|
|
13
13
|
#observed = new Set();
|
|
14
14
|
#problems = new Map();
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.#failureCount = 0;
|
|
23
|
-
this.#lastFailureCall = '';
|
|
24
|
-
this.#lastFailure = '';
|
|
25
|
-
}
|
|
26
|
-
}
|
|
15
|
+
/** After a successful consultation the failing path may be tried again: the
|
|
16
|
+
* repeated-call rejection and the open problems start from zero. */
|
|
17
|
+
noteConsultation() {
|
|
18
|
+
this.#problems.clear();
|
|
19
|
+
this.#failureCount = 0;
|
|
20
|
+
this.#lastFailureCall = '';
|
|
21
|
+
this.#lastFailure = '';
|
|
27
22
|
}
|
|
28
23
|
/** Called immediately after execution, so a serial batch cannot run attempt 3
|
|
29
24
|
* before its second failure has reached the advisor coordinator. */
|
|
@@ -31,7 +26,7 @@ export class StallGuard {
|
|
|
31
26
|
if (this.#observed.has(call.id))
|
|
32
27
|
return { stalled: false };
|
|
33
28
|
this.#observed.add(call.id);
|
|
34
|
-
if (call.function.name === 'Advisor'
|
|
29
|
+
if (call.function.name === 'Advisor'
|
|
35
30
|
|| (!result.ok && (result.disposition === 'deferred' || result.error === 'aborted')))
|
|
36
31
|
return { stalled: false };
|
|
37
32
|
const callSignature = hash(`${call.function.name}\0${call.function.arguments}`);
|
|
@@ -23,17 +23,13 @@ export class StallGuard {
|
|
|
23
23
|
readonly #observed = new Set<string>();
|
|
24
24
|
readonly #problems = new Map<string, { signature: string; calls: Set<string>; attempts: string[]; notified: boolean }>();
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.#lastFailureCall = '';
|
|
34
|
-
this.#lastFailure = '';
|
|
35
|
-
}
|
|
36
|
-
}
|
|
26
|
+
/** After a successful consultation the failing path may be tried again: the
|
|
27
|
+
* repeated-call rejection and the open problems start from zero. */
|
|
28
|
+
noteConsultation(): void {
|
|
29
|
+
this.#problems.clear();
|
|
30
|
+
this.#failureCount = 0;
|
|
31
|
+
this.#lastFailureCall = '';
|
|
32
|
+
this.#lastFailure = '';
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
/** Called immediately after execution, so a serial batch cannot run attempt 3
|
|
@@ -41,7 +37,7 @@ export class StallGuard {
|
|
|
41
37
|
observeAttempt(call: ToolCall, result: ToolResult): StallObservation {
|
|
42
38
|
if (this.#observed.has(call.id)) return { stalled: false };
|
|
43
39
|
this.#observed.add(call.id);
|
|
44
|
-
if (call.function.name === 'Advisor'
|
|
40
|
+
if (call.function.name === 'Advisor'
|
|
45
41
|
|| (!result.ok && (result.disposition === 'deferred' || result.error === 'aborted'))) return { stalled: false };
|
|
46
42
|
const callSignature = hash(`${call.function.name}\0${call.function.arguments}`);
|
|
47
43
|
const failed = result.problem?.outcome === 'failed' || !result.ok
|