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.
Files changed (174) hide show
  1. package/package.json +1 -3
  2. package/plugins/workflow-runner/src/runtime/context.js +1 -1
  3. package/plugins/workflow-runner/src/runtime/context.ts +1 -1
  4. package/plugins/workflow-runner/test/embeddedExecution.test.ts +2 -5
  5. package/plugins/workflow-runner/test/execLifetime.test.ts +15 -2
  6. package/skills/ssh-remote-dev/SKILL.md +61 -0
  7. package/skills/ssh-remote-dev/agents/openai.yaml +4 -0
  8. package/src/advisor/README.md +62 -24
  9. package/src/advisor/advisorNudge.js +199 -0
  10. package/src/advisor/advisorNudge.ts +232 -0
  11. package/src/advisor/deliveryReview.js +35 -12
  12. package/src/advisor/deliveryReview.ts +35 -11
  13. package/src/advisor/presentation.js +7 -10
  14. package/src/advisor/presentation.ts +10 -13
  15. package/src/advisor/reviewContext.js +22 -58
  16. package/src/advisor/reviewContext.ts +24 -67
  17. package/src/cli/configMenu.js +17 -128
  18. package/src/cli/configMenu.tsx +17 -193
  19. package/src/cli/print.js +2 -0
  20. package/src/cli/print.ts +2 -0
  21. package/src/cli/streamJson.js +2 -0
  22. package/src/cli/streamJson.ts +2 -0
  23. package/src/cli/wizards/advisorWizard.js +9 -7
  24. package/src/cli/wizards/advisorWizard.tsx +9 -7
  25. package/src/cli/wizards/contextAdvisorWizard.js +9 -7
  26. package/src/cli/wizards/contextAdvisorWizard.tsx +9 -7
  27. package/src/cli/wizards/providerPresets.js +27 -1
  28. package/src/cli/wizards/providerPresets.ts +44 -2
  29. package/src/cli/wizards/providerWizard.js +51 -10
  30. package/src/cli/wizards/providerWizard.tsx +59 -9
  31. package/src/config/configDefaults.js +1 -1
  32. package/src/config/configDefaults.ts +1 -1
  33. package/src/config/configDiagnostics.js +1 -21
  34. package/src/config/configDiagnostics.ts +3 -23
  35. package/src/config/configFile.js +11 -4
  36. package/src/config/configFile.ts +27 -7
  37. package/src/config/configManagement.js +1 -0
  38. package/src/config/configManagement.ts +2 -0
  39. package/src/config/configService.js +12 -8
  40. package/src/config/configService.ts +16 -11
  41. package/src/config/numericLimits.js +0 -4
  42. package/src/config/numericLimits.ts +0 -4
  43. package/src/config/reasoningEffort.js +16 -0
  44. package/src/config/reasoningEffort.ts +18 -0
  45. package/src/context/budgetPlan.js +1 -1
  46. package/src/context/budgetPlan.ts +1 -1
  47. package/src/context/optimizeConversation.js +1 -1
  48. package/src/context/optimizeConversation.ts +1 -1
  49. package/src/harness/stallGuard.js +8 -13
  50. package/src/harness/stallGuard.ts +8 -12
  51. package/src/llm/client.js +64 -17
  52. package/src/llm/client.ts +62 -7
  53. package/src/llm/providers/openaiFormat.js +14 -3
  54. package/src/llm/providers/openaiFormat.ts +17 -3
  55. package/src/llm/providers/responsesFormat.js +275 -0
  56. package/src/llm/providers/responsesFormat.ts +306 -0
  57. package/src/loop/README.md +18 -3
  58. package/src/loop/liveDiagramGate.js +63 -0
  59. package/src/loop/liveDiagramGate.ts +61 -0
  60. package/src/loop/messages.js +12 -0
  61. package/src/loop/messages.ts +13 -0
  62. package/src/loop/options.ts +7 -2
  63. package/src/loop/toolBatch.js +0 -1
  64. package/src/loop/toolBatch.ts +0 -1
  65. package/src/loop/toolExecutor.js +11 -46
  66. package/src/loop/toolExecutor.ts +12 -55
  67. package/src/loop/toolPresentation.js +2 -13
  68. package/src/loop/toolPresentation.ts +2 -13
  69. package/src/loop/toolSemantics.js +3 -4
  70. package/src/loop/toolSemantics.ts +4 -6
  71. package/src/loop.js +222 -214
  72. package/src/loop.ts +226 -232
  73. package/src/memory/dependencies.js +11 -3
  74. package/src/memory/dependencies.ts +11 -3
  75. package/src/memory/episodicMemory.js +59 -18
  76. package/src/memory/episodicMemory.ts +58 -18
  77. package/src/memory/experienceStore.js +4 -3
  78. package/src/memory/experienceStore.ts +4 -3
  79. package/src/memory/factCandidates.js +53 -1
  80. package/src/memory/factCandidates.ts +54 -1
  81. package/src/memory/factLearning.js +2 -2
  82. package/src/memory/factLearning.ts +2 -2
  83. package/src/memory/jobPolicy.js +24 -5
  84. package/src/memory/jobPolicy.ts +25 -5
  85. package/src/memory/learning.js +2 -2
  86. package/src/memory/learning.ts +2 -2
  87. package/src/memory/learningModel.js +7 -0
  88. package/src/memory/learningModel.ts +7 -0
  89. package/src/memory/managementService.js +8 -7
  90. package/src/memory/managementService.ts +16 -8
  91. package/src/memory/memoryService.js +104 -33
  92. package/src/memory/memoryService.ts +132 -28
  93. package/src/memory/projectKnowledge.js +39 -3
  94. package/src/memory/projectKnowledge.ts +45 -3
  95. package/src/memory/recallQuery.js +56 -0
  96. package/src/memory/recallQuery.ts +58 -0
  97. package/src/memory/retrieval.js +39 -10
  98. package/src/memory/retrieval.ts +46 -11
  99. package/src/memory/turnJournal.js +75 -10
  100. package/src/memory/turnJournal.ts +66 -10
  101. package/src/memory/types.ts +7 -1
  102. package/src/prompts/delegation.js +2 -1
  103. package/src/prompts/delegation.ts +3 -1
  104. package/src/prompts/policyRegistry.js +9 -12
  105. package/src/prompts/policyRegistry.ts +9 -12
  106. package/src/prompts/promptAssembly.js +6 -5
  107. package/src/prompts/promptAssembly.ts +8 -6
  108. package/src/prompts/visualPresentation.js +39 -10
  109. package/src/prompts/visualPresentation.ts +38 -9
  110. package/src/runtime/answerPreparation.js +1 -1
  111. package/src/runtime/answerPreparation.ts +1 -1
  112. package/src/runtime/fileLock.js +19 -3
  113. package/src/runtime/fileLock.ts +19 -3
  114. package/src/runtime/invocationPolicy.js +1 -1
  115. package/src/runtime/invocationPolicy.ts +1 -1
  116. package/src/runtime/outputContract.js +0 -4
  117. package/src/runtime/outputContract.ts +0 -7
  118. package/src/session/runAgentTurn.js +3 -0
  119. package/src/session/runAgentTurn.ts +3 -0
  120. package/src/team/onlineToolContract.js +0 -1
  121. package/src/team/onlineToolContract.ts +0 -1
  122. package/src/tools/advisor/advisor.js +207 -365
  123. package/src/tools/advisor/advisor.ts +211 -383
  124. package/src/tools/agent/agentTypes.js +0 -1
  125. package/src/tools/agent/agentTypes.ts +0 -1
  126. package/src/tools/agent/coordinator.js +4 -1
  127. package/src/tools/agent/coordinator.ts +4 -1
  128. package/src/tools/bash/semantics.js +4 -5
  129. package/src/tools/bash/semantics.ts +4 -5
  130. package/src/tools/capabilities.js +2 -3
  131. package/src/tools/capabilities.ts +2 -4
  132. package/src/tools/index.js +0 -16
  133. package/src/tools/index.ts +0 -16
  134. package/src/tools/memory/maintenance.js +8 -9
  135. package/src/tools/memory/maintenance.ts +13 -11
  136. package/src/tools/memory/memory.js +5 -1
  137. package/src/tools/memory/memory.ts +5 -0
  138. package/src/tools/optimizeConversation/README.md +4 -6
  139. package/src/tools/toolPromptGuides.js +2 -9
  140. package/src/tools/toolPromptGuides.ts +2 -9
  141. package/src/types.ts +28 -105
  142. package/src/ui/App.js +2 -0
  143. package/src/ui/App.tsx +1 -0
  144. package/src/ui/MessageList.js +8 -44
  145. package/src/ui/MessageList.tsx +3 -81
  146. package/src/ui/hooks/useChat.js +2 -0
  147. package/src/ui/hooks/useChat.ts +2 -0
  148. package/src/ui/toolProgress.js +1 -1
  149. package/src/ui/toolProgress.ts +1 -1
  150. package/src/web/protocol.ts +10 -3
  151. package/src/advisor/advisorCoordinator.js +0 -734
  152. package/src/advisor/advisorCoordinator.ts +0 -825
  153. package/src/cli/wizards/sshHostWizard.js +0 -156
  154. package/src/cli/wizards/sshHostWizard.tsx +0 -214
  155. package/src/context/sshHosts.js +0 -290
  156. package/src/context/sshHosts.ts +0 -312
  157. package/src/loop/publication.js +0 -94
  158. package/src/loop/publication.ts +0 -124
  159. package/src/runtime/finalAnswer.js +0 -9
  160. package/src/runtime/finalAnswer.ts +0 -13
  161. package/src/tools/advisor/advisorDecision.js +0 -79
  162. package/src/tools/advisor/advisorDecision.ts +0 -92
  163. package/src/tools/ssh/ssh.js +0 -152
  164. package/src/tools/ssh/ssh.ts +0 -167
  165. package/src/tools/ssh/sshAvailability.js +0 -35
  166. package/src/tools/ssh/sshAvailability.ts +0 -39
  167. package/src/tools/ssh/sshClient.js +0 -177
  168. package/src/tools/ssh/sshClient.ts +0 -189
  169. package/src/tools/ssh/sshDownload.js +0 -77
  170. package/src/tools/ssh/sshDownload.ts +0 -92
  171. package/src/tools/ssh/sshHostsTool.js +0 -36
  172. package/src/tools/ssh/sshHostsTool.ts +0 -48
  173. package/src/tools/ssh/sshUpload.js +0 -72
  174. package/src/tools/ssh/sshUpload.ts +0 -85
package/src/types.ts CHANGED
@@ -178,7 +178,7 @@ export type Message = (
178
178
  role: 'assistant';
179
179
  /** Persisted UI semantics; not a provider instruction or a success claim. */
180
180
  presentation?: 'progress' | 'final';
181
- /** Host-only review boundary for a delivered text answer; never model authority. */
181
+ /** @deprecated Legacy sessions only (the retired review cycle); no longer written. Stripped before any provider request. */
182
182
  advisorTaskVersion?: number;
183
183
  /** 当 tool_calls 非空时 content 通常为 null(OpenAI 协议) */
184
184
  content: string | null;
@@ -214,13 +214,13 @@ export type Message = (
214
214
  display_metadata?: ToolResultMetadata;
215
215
  /** 本地压缩策略;发送 Provider 前会剥离。 */
216
216
  tool_result_policy?: ToolResultPolicy;
217
- /** Host-only effect needed to restore the current review cycle. */
217
+ /** @deprecated Legacy sessions only; no longer written. Stripped before any provider request. */
218
218
  advisorMutatesWorkspace?: boolean;
219
219
  timestamp?: number;
220
220
  }
221
221
  ) & {
222
- /** Host-only bounded review transitions, including graceful degradation. */
223
- advisorCheckpoints?: AdvisorCheckpointMetadata[];
222
+ /** @deprecated Legacy sessions only (the retired review checkpoints); no longer written. Stripped before any provider request. */
223
+ advisorCheckpoints?: unknown[];
224
224
  /** Host-only cold history. Persist with Session; strip before any provider request. */
225
225
  advisorHistory?: { version: 1; messages: Message[] };
226
226
  /** Host-only: a deferred call never produced an execution observation. */
@@ -376,51 +376,6 @@ export interface ProcessExecutionMetadata {
376
376
  exitCode?: number | null;
377
377
  }
378
378
 
379
- export type AdvisorCheckpoint =
380
- | 'pre-execution'
381
- | 'stalled'
382
- | 'high-risk'
383
- | 'pre-delivery';
384
-
385
- export interface AdvisorVersions {
386
- taskVersion: number;
387
- workVersion: number;
388
- evidenceVersion: number;
389
- }
390
-
391
- export interface AdvisorCheckpointMetadata extends AdvisorVersions {
392
- kind: 'advisor_checkpoint';
393
- checkpoint: AdvisorCheckpoint;
394
- checkpointKey: string;
395
- status: 'required' | 'attempted-unavailable';
396
- }
397
-
398
- export interface AdvisorConsultationMetadata extends AdvisorVersions {
399
- kind: 'advisor_consultation';
400
- /** Host-recorded trigger, distinct from who emitted the tool call. Absent in old history. */
401
- triggerSource?: 'checkpoint' | 'model';
402
- triggerReason?: string;
403
- consultationId: string;
404
- checkpoint: AdvisorCheckpoint;
405
- checkpointKey: string;
406
- status: 'completed' | 'failed';
407
- }
408
-
409
- export interface AdvisorDecisionMetadata extends AdvisorVersions {
410
- kind: 'advisor_decision';
411
- consultationId: string;
412
- checkpoint: AdvisorCheckpoint;
413
- checkpointKey: string;
414
- decision: 'accept' | 'partial' | 'reject';
415
- rationale: string;
416
- acceptedPoints: string[];
417
- rejectedPoints: string[];
418
- verificationPlan: string[];
419
- evidenceRefs?: string[];
420
- /** Referenced evidence is not proof of correctness; pending never means approved. */
421
- verificationStatus?: 'evidence_linked' | 'pending';
422
- }
423
-
424
379
  /** Agent 子任务的结构化阶段进度;仅供宿主展示,不写入会话历史或发送给 LLM。 */
425
380
  export interface SubagentProgress {
426
381
  kind: 'subagent';
@@ -468,9 +423,6 @@ export type ToolResultMetadata =
468
423
  | FileDiscoveryMetadata
469
424
  | ResultManifestMetadata
470
425
  | ProcessExecutionMetadata
471
- | AdvisorCheckpointMetadata
472
- | AdvisorConsultationMetadata
473
- | AdvisorDecisionMetadata
474
426
  | BrowserDownloadMetadata;
475
427
 
476
428
  /**
@@ -576,8 +528,6 @@ export type ToolResult = { problem?: ToolProblemOutcome; observation?: ReadObser
576
528
  * 避免按工具名写特判分支。
577
529
  */
578
530
  export interface ToolCallContext {
579
- /** Run-local host initialization shared with Advisor; never a model argument. */
580
- advisorConsultation?: AdvisorConsultationMetadata;
581
531
  /** Shared per-model-response read allowance; reservations happen before IO. */
582
532
  reserveReadChars?: (requested?: number) => number;
583
533
  /** Host presentation only; cannot grant tools to a delegated agent. */
@@ -609,10 +559,11 @@ export interface ToolCallContext {
609
559
  advisorCalls?: { used: number };
610
560
  /** 区分主模型自动咨询与用户显式 /advisor ask。 */
611
561
  advisorInvocation?: 'agent' | 'manual';
612
- /** Advisor 协调器运行时桥;只存在于主循环,不暴露给模型或持久化。 */
613
- advisorRuntime?: AdvisorRuntimeBridge;
614
- /** Live host context used by the main request, not tool-provided instructions. */
615
- advisorReviewContext?: () => import('./advisor/reviewContext.js').AdvisorReviewContext;
562
+ /**
563
+ * 项目约束与记忆(它们不在对话历史里),作为"背景"附给顾问;宿主在主循环里提供,
564
+ * 不是工具参数,也不是给顾问的指令。
565
+ */
566
+ advisorBackground?: () => string;
616
567
  /**
617
568
  * 主循环使用的 provider —— Agent 等「工具内部再起子查询」的派生工具用它
618
569
  * 跑嵌套 runQuery(子 agent 与主 agent 同一模型,不另配凭据)。
@@ -696,45 +647,6 @@ export interface ToolCallContext {
696
647
  };
697
648
  }
698
649
 
699
- export interface AdvisorContextPacket {
700
- failureAttempts?: string[];
701
- deliveryDraft?: string;
702
- decisionVerification?: Pick<AdvisorDecisionMetadata, 'consultationId' | 'verificationStatus' | 'evidenceRefs' | 'verificationPlan' | 'decision' | 'rationale' | 'acceptedPoints' | 'rejectedPoints'>;
703
- objective: string;
704
- currentRequest: string;
705
- checkpoint: AdvisorCheckpoint;
706
- versions: AdvisorVersions;
707
- changedFiles: string[];
708
- evidence: string[];
709
- /** Packet excerpts are a selection, not proof the reviewer saw every stored result. */
710
- evidenceCoverage?: { available: number; included: number; omitted: number; excerpts: true };
711
- previousAdvice?: string;
712
- actionsAfterPreviousAdvice: string[];
713
- openQuestions: string[];
714
- }
715
-
716
- export type AdvisorReason = 'uncertainty' | 'plan_review' | 'delivery_review' | 'stalled' | 'user_dissatisfaction' | 'evidence_conflict';
717
-
718
- export interface AdvisorRuntimeBridge {
719
- /** Latest advice available for the main Agent's optional decision record. */
720
- readonly pendingConsultationId: string | undefined;
721
- beginConsultation(reason?: AdvisorReason): AdvisorConsultationMetadata;
722
- finishConsultation(
723
- metadata: AdvisorConsultationMetadata,
724
- ok: boolean,
725
- ): AdvisorConsultationMetadata;
726
- recordDecision(input: {
727
- consultationId: string;
728
- decision: 'accept' | 'partial' | 'reject';
729
- rationale: string;
730
- acceptedPoints?: string[];
731
- rejectedPoints?: string[];
732
- verificationPlan?: string[];
733
- evidenceRefs?: string[];
734
- }): ToolResult;
735
- contextPacket(note?: string): AdvisorContextPacket;
736
- }
737
-
738
650
  export type ToolCategory =
739
651
  | 'files'
740
652
  | 'shell'
@@ -901,10 +813,11 @@ interface ProviderCommon {
901
813
  maxTokens?: number;
902
814
 
903
815
  /**
904
- * 请求协议格式:'openai'(Chat Completions,默认)| 'anthropic'(Messages API)。
816
+ * 请求协议格式:'openai'(Chat Completions,默认)| 'openai-responses'(OpenAI Responses API)
817
+ * | 'anthropic'(Messages API)。
905
818
  * 缺省当 'openai'——兼容旧版只产出 OpenAI 格式对象的 env 自举路径。见 client.ts。
906
819
  */
907
- apiFormat?: 'openai' | 'anthropic';
820
+ apiFormat?: 'openai' | 'openai-responses' | 'anthropic';
908
821
 
909
822
  /**
910
823
  * 该模型是否支持识图(多模态视觉)。resolveProvider 从所选 ModelConfig 归一成真布尔
@@ -917,6 +830,12 @@ interface ProviderCommon {
917
830
  supportsJsonSchema?: boolean;
918
831
  /** Explicitly request provider reasoning when the endpoint supports it. */
919
832
  reasoning?: boolean;
833
+ /**
834
+ * 推理强度。openai-responses 发 `reasoning.effort`,openai(Chat Completions) 发
835
+ * `reasoning_effort`(OpenRouter 发 `reasoning.effort`)。缺省不发送,沿用服务端默认。
836
+ * 模型不认该档位时 client.ts 去掉参数重发一次,不让对话 400。
837
+ */
838
+ reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
920
839
  promptCache?: PromptCacheConfig;
921
840
 
922
841
  /**
@@ -1142,8 +1061,9 @@ export type LlmStreamEvent =
1142
1061
  * 工作过程显示阶段标签(UI 的 LiveArea 据此选择文字 / 决定是否隐藏整面板)。
1143
1062
  *
1144
1063
  * idle —— 当前没有任何工作(隐藏 LiveArea)
1145
- * thinking —— 正在准备候选答案或等待工具调用,候选正文不公开
1146
- * streaming —— 内部检查结束后,最终表达请求的真实正文流
1064
+ * thinking —— 等待首个 token、工具调用或仍可能被检查退回的私有候选
1065
+ * streaming —— 最终回答正在显示:没有检查能再拦下时边生成边实时输出;
1066
+ * 否则通过全部检查后原样一次发布
1147
1067
  * tool_executing —— 至少一个工具在跑(并行时栈式显示多个)
1148
1068
  * compacting —— 正在跑自动 / reactive / 手动压缩
1149
1069
  */
@@ -1220,7 +1140,10 @@ export interface TurnResourceUsage {
1220
1140
  }
1221
1141
 
1222
1142
  export type LoopEvent =
1223
- /** 文本流(同 LlmStreamEvent.text_delta) */
1143
+ /**
1144
+ * 对用户可见的回答正文。没有任何检查能再拦下本次回答时逐段实时发出(含工具轮的
1145
+ * 过程说明);否则候选保持私有,通过全部检查后原样一次发出。已发出的正文不会被撤回。
1146
+ */
1224
1147
  | { type: 'text'; delta: string }
1225
1148
  /**
1226
1149
  * 用户消息刚 push 进 history(loop 入口)。
@@ -1242,16 +1165,16 @@ export type LoopEvent =
1242
1165
  }
1243
1166
  /**
1244
1167
  * 内部候选正文尚不能交付,需要进入检查或补全阶段。
1245
- * 新内核候选正文不广播;textLength=0,仅表示准备/复核阶段变化。
1168
+ * 只退回从未广播的私有候选,已实时显示的正文不会被退回;textLength=0,仅表示准备/复核阶段变化。
1246
1169
  * textLength>0 仅供旧事件兼容,不应作为正常展示路径。
1247
1170
  */
1248
1171
  | {
1249
1172
  type: 'assistant_draft_discarded';
1250
1173
  reason:
1251
1174
  | 'formal_delivery'
1252
- | 'advisor_checkpoint'
1253
1175
  | 'empty_response'
1254
- | 'interactive_question';
1176
+ | 'interactive_question'
1177
+ | 'diagram_preparation';
1255
1178
  textLength: number;
1256
1179
  }
1257
1180
  /**
package/src/ui/App.js CHANGED
@@ -58,6 +58,8 @@ const CLEAR_SCREEN = '\x1b[2J\x1b[H';
58
58
  function formatProviderName(apiFormat) {
59
59
  if (apiFormat === 'anthropic')
60
60
  return 'Anthropic';
61
+ if (apiFormat === 'openai-responses')
62
+ return 'OpenAI Responses';
61
63
  if (apiFormat === 'openai')
62
64
  return 'OpenAI兼容';
63
65
  return apiFormat;
package/src/ui/App.tsx CHANGED
@@ -87,6 +87,7 @@ const CLEAR_SCREEN = '\x1b[2J\x1b[H';
87
87
 
88
88
  function formatProviderName(apiFormat: string): string {
89
89
  if (apiFormat === 'anthropic') return 'Anthropic';
90
+ if (apiFormat === 'openai-responses') return 'OpenAI Responses';
90
91
  if (apiFormat === 'openai') return 'OpenAI兼容';
91
92
  return apiFormat;
92
93
  }
@@ -35,7 +35,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
35
35
  import React from 'react';
36
36
  import { Box, Static, Text } from 'ink';
37
37
  import { conciseToolDescription } from './toolProgress.js';
38
- import { advisorOpinionText, advisorDecisionLabel, advisorEvidenceLabel } from '../advisor/presentation.js';
38
+ import { advisorOpinionText } from '../advisor/presentation.js';
39
39
  import { contentToDisplayText, contentToPlainText } from '../multimodal.js';
40
40
  import { splitThinkBlocks } from '../utils/stripThink.js';
41
41
  import { figures } from './figures.js';
@@ -104,16 +104,6 @@ export function buildToolCallIndex(history) {
104
104
  }
105
105
  return map;
106
106
  }
107
- /** 按 consultationId 关联持久化决定,供历史重载时在顾问卡片下恢复展示。 */
108
- export function buildAdvisorDecisionIndex(history) {
109
- const decisions = new Map();
110
- for (const message of history) {
111
- if (message.role !== 'tool' || message.display_metadata?.kind !== 'advisor_decision')
112
- continue;
113
- decisions.set(message.display_metadata.consultationId, message.display_metadata);
114
- }
115
- return decisions;
116
- }
117
107
  /**
118
108
  * 从 Agent 子任务报告的统计尾巴(agent.ts 固定格式
119
109
  * 「(子任务「x」[type]:N 轮 · M 次工具调用,K 次失败)」)解析统计数。
@@ -218,7 +208,6 @@ export const MessageList = React.memo(function MessageList({ history, compactGen
218
208
  const items = React.useMemo(() => {
219
209
  const turnMetas = summarizeTurn(history);
220
210
  const toolIndex = buildToolCallIndex(history);
221
- const advisorDecisions = buildAdvisorDecisionIndex(history);
222
211
  return [
223
212
  ...(bannerText
224
213
  ? [
@@ -234,10 +223,6 @@ export const MessageList = React.memo(function MessageList({ history, compactGen
234
223
  msg: m,
235
224
  turnMeta: turnMetas[idx],
236
225
  toolMeta: m.role === 'tool' ? (toolIndex.get(m.tool_call_id) ?? null) : null,
237
- advisorDecision: m.role === 'tool'
238
- && m.display_metadata?.kind === 'advisor_consultation'
239
- ? (advisorDecisions.get(m.display_metadata.consultationId) ?? null)
240
- : null,
241
226
  // 纯派生 key:有 id 用 id,没有就用 idx 兜底。绝不在 render 期 mutate 消息对象
242
227
  // (<Static> 已 commit 的行永不重绘,key 仅在 append 对账时用,idx 已足够稳定)。
243
228
  key: m.id ?? `message-${idx}`,
@@ -250,7 +235,7 @@ export const MessageList = React.memo(function MessageList({ history, compactGen
250
235
  if (item.kind === 'banner') {
251
236
  return _jsx(BannerRow, { text: item.text }, item.key);
252
237
  }
253
- return (_jsx(MessageRow, { message: item.msg, turnMeta: item.turnMeta, toolMeta: item.toolMeta, advisorDecision: item.advisorDecision, foldReasoning: foldReasoning }, item.key));
238
+ return (_jsx(MessageRow, { message: item.msg, turnMeta: item.turnMeta, toolMeta: item.toolMeta, foldReasoning: foldReasoning }, item.key));
254
239
  } }, compactGeneration));
255
240
  });
256
241
  function BannerRow({ text }) {
@@ -278,7 +263,7 @@ function formatToolHead(meta, shortId, statsTail) {
278
263
  .trim();
279
264
  return `[文件 · ${action}${target ? ` ${target}` : ''} · #${shortId}]${statsTail}`;
280
265
  }
281
- function MessageRow({ message, turnMeta, toolMeta, advisorDecision, foldReasoning, }) {
266
+ function MessageRow({ message, turnMeta, toolMeta, foldReasoning, }) {
282
267
  switch (message.role) {
283
268
  case 'system': {
284
269
  // v2.x:ephemeral system message 是 UI 临时提示(slash 命令输出等),
@@ -345,19 +330,10 @@ function MessageRow({ message, turnMeta, toolMeta, advisorDecision, foldReasonin
345
330
  const lines = terminalText(message.content).split('\n');
346
331
  // 顾问意见给更高的预览上限,并用默认亮色而非 dim 灰 —— 它是另一个模型说的话,
347
332
  // 不该和 grep 输出一样被视觉降级(见 MAX_ADVISOR_PREVIEW_LINES)。
348
- const advisorMeta = message.display_metadata?.kind === 'advisor_consultation'
349
- ? message.display_metadata
350
- : null;
351
- const decisionMeta = message.display_metadata?.kind === 'advisor_decision'
352
- ? message.display_metadata
353
- : null;
354
333
  const inferredToolName = toolMeta?.toolName
355
- ?? (advisorMeta ? 'Advisor' : null)
356
- ?? (decisionMeta ? 'AdvisorDecision' : null)
357
334
  ?? (message.display_metadata?.kind === 'result_manifest' ? 'PresentResult' : null)
358
335
  ?? (message.display_metadata?.kind === 'agent' ? 'Agent' : undefined);
359
336
  const isAdvisor = inferredToolName === 'Advisor';
360
- const isAdvisorDecision = inferredToolName === 'AdvisorDecision';
361
337
  if (isAdvisor)
362
338
  lines.splice(0, lines.length, ...terminalText(advisorOpinionText(message.content)).split('\n'));
363
339
  const visibility = toolHistoryVisibility(inferredToolName, message.content);
@@ -365,9 +341,6 @@ function MessageRow({ message, turnMeta, toolMeta, advisorDecision, foldReasonin
365
341
  const previewLines = lines.slice(0, previewCap);
366
342
  const hidden = Math.max(0, lines.length - previewCap);
367
343
  const shortId = message.tool_call_id.slice(-8);
368
- if (message.display_metadata?.kind === 'advisor_checkpoint') {
369
- return _jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsx(Text, { color: theme.subtle, wrap: "end", children: `已暂缓 · 顾问检查点 · 操作尚未执行(/show ${shortId} 查看详情,复核进展见后续记录)` }) });
370
- }
371
344
  // 头行升级:有 toolMeta(发起方反查命中)显示人话描述;Agent 子任务
372
345
  // 再解析统计尾巴显示 ✓ N 轮 · M 次工具。无 meta(历史重载等)兜底旧格式。
373
346
  const stats = inferredToolName === 'Agent' ? agentResultStats(message.content) : null;
@@ -377,25 +350,16 @@ function MessageRow({ message, turnMeta, toolMeta, advisorDecision, foldReasonin
377
350
  // 顾问头行单独成文并去掉 dim:friendlyToolDescription 没有 Advisor 分支,
378
351
  // 走兜底会显示成一串参数预览,看不出这是「第二个模型的独立意见」。
379
352
  const headText = isAdvisor
380
- ? `[顾问意见 · ${advisorMeta?.checkpoint ?? 'manual'} · #${shortId}]`
381
- : isAdvisorDecision
382
- ? `[顾问意见处理 · ${decisionMeta?.decision ?? 'unknown'} · #${shortId}]`
383
- : toolMeta
384
- ? formatToolHead(toolMeta, shortId, statsTail)
385
- : `[tool result · #${shortId}]`;
353
+ ? `[顾问意见 · #${shortId}]`
354
+ : toolMeta
355
+ ? formatToolHead(toolMeta, shortId, statsTail)
356
+ : `[tool result · #${shortId}]`;
386
357
  if (visibility === 'hidden')
387
358
  return null;
388
- if (isAdvisorDecision) {
389
- return _jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsxs(Text, { color: theme.subtle, wrap: "end", children: [decisionMeta
390
- ? `顾问意见已处理 · ${advisorDecisionLabel(decisionMeta.decision)} · ${advisorEvidenceLabel(decisionMeta.verificationStatus)}`
391
- : '顾问意见登记未完成 · 可重试', `(/show ${shortId} 查看详情)`] }) });
392
- }
393
359
  if (visibility === 'compact') {
394
360
  return (_jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsx(Text, { color: theme.subtle, dimColor: true, wrap: "end", children: terminalText(headText) }) }));
395
361
  }
396
- return (_jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, ...(isAdvisor ? {} : { dimColor: true }), wrap: "end", children: terminalText(headText) }), advisorMeta && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, wrap: "end", children: terminalText(advisorMeta.status === 'completed'
397
- ? '顾问意见已返回,尚不代表事实核验通过'
398
- : '顾问咨询未完成,已降级继续') }), advisorMeta.status === 'completed' && !advisorDecision && (_jsx(Text, { color: theme.subtle, wrap: "end", children: "\u987E\u95EE\u610F\u89C1\u5DF2\u8FD4\u56DE\uFF1B\u4E3B Agent \u7684\u6838\u9A8C\u4E0E\u91C7\u7EB3\u7ED3\u8BBA\u89C1\u540E\u7EED\u8BB0\u5F55\u3002" })), advisorDecision && (_jsx(Text, { color: theme.subtle, wrap: "end", children: terminalText(`${advisorDecision.decision} · ${advisorDecision.rationale}`) })), advisorDecision?.verificationPlan.map((item) => (_jsx(Text, { color: theme.subtle, wrap: "end", children: terminalText(`验证:${item}`) }, `advisor-card-verify-${item}`)))] })), decisionMeta && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, wrap: "end", children: terminalText(`关联咨询 ${decisionMeta.consultationId} · ${decisionMeta.rationale}`) }), decisionMeta.verificationPlan.map((item) => (_jsx(Text, { color: theme.subtle, wrap: "end", children: terminalText(`验证:${item}`) }, `advisor-verify-${item}`)))] })), previewLines.map((line, i) => (_jsx(Text, { ...(isAdvisor ? {} : { color: theme.subtle }), wrap: "end", children: line.length > 0 ? line : ' ' }, `p-${i}`))), hidden > 0 && (_jsx(Text, { color: theme.subtle, dimColor: true, children: `... ${figures.fold} 完整 ${lines.length} 行(输入 /show ${shortId} 查看)` }))] }) }));
362
+ return (_jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, ...(isAdvisor ? {} : { dimColor: true }), wrap: "end", children: terminalText(headText) }), previewLines.map((line, i) => (_jsx(Text, { ...(isAdvisor ? {} : { color: theme.subtle }), wrap: "end", children: line.length > 0 ? line : ' ' }, `p-${i}`))), hidden > 0 && (_jsx(Text, { color: theme.subtle, dimColor: true, children: `... ${figures.fold} 完整 ${lines.length} 行(输入 /show ${shortId} 查看)` }))] }) }));
399
363
  }
400
364
  }
401
365
  }
@@ -36,9 +36,9 @@ import React from 'react';
36
36
  import { Box, Static, Text } from 'ink';
37
37
 
38
38
  import { conciseToolDescription } from './toolProgress.js';
39
- import { advisorOpinionText, advisorDecisionLabel, advisorEvidenceLabel } from '../advisor/presentation.js';
39
+ import { advisorOpinionText } from '../advisor/presentation.js';
40
40
  import { contentToDisplayText, contentToPlainText } from '../multimodal.js';
41
- import type { AdvisorDecisionMetadata, Message } from '../types.js';
41
+ import type { Message } from '../types.js';
42
42
  import { splitThinkBlocks } from '../utils/stripThink.js';
43
43
  import { figures } from './figures.js';
44
44
  import { terminalText } from './terminalText.js';
@@ -72,7 +72,6 @@ type StaticItem =
72
72
  turnMeta: TurnMeta | null;
73
73
  /** tool 消息的发起方人话描述(buildToolCallIndex 反查);其余消息 null */
74
74
  toolMeta: ToolCallMeta | null;
75
- advisorDecision: AdvisorDecisionMetadata | null;
76
75
  key: string;
77
76
  };
78
77
 
@@ -167,18 +166,6 @@ export function buildToolCallIndex(history: Message[]): Map<string, ToolCallMeta
167
166
  return map;
168
167
  }
169
168
 
170
- /** 按 consultationId 关联持久化决定,供历史重载时在顾问卡片下恢复展示。 */
171
- export function buildAdvisorDecisionIndex(
172
- history: Message[],
173
- ): Map<string, AdvisorDecisionMetadata> {
174
- const decisions = new Map<string, AdvisorDecisionMetadata>();
175
- for (const message of history) {
176
- if (message.role !== 'tool' || message.display_metadata?.kind !== 'advisor_decision') continue;
177
- decisions.set(message.display_metadata.consultationId, message.display_metadata);
178
- }
179
- return decisions;
180
- }
181
-
182
169
  /**
183
170
  * 从 Agent 子任务报告的统计尾巴(agent.ts 固定格式
184
171
  * 「(子任务「x」[type]:N 轮 · M 次工具调用,K 次失败)」)解析统计数。
@@ -302,7 +289,6 @@ export const MessageList = React.memo(function MessageList({
302
289
  const items: StaticItem[] = React.useMemo(() => {
303
290
  const turnMetas = summarizeTurn(history);
304
291
  const toolIndex = buildToolCallIndex(history);
305
- const advisorDecisions = buildAdvisorDecisionIndex(history);
306
292
  return [
307
293
  ...(bannerText
308
294
  ? [
@@ -318,10 +304,6 @@ export const MessageList = React.memo(function MessageList({
318
304
  msg: m,
319
305
  turnMeta: turnMetas[idx],
320
306
  toolMeta: m.role === 'tool' ? (toolIndex.get(m.tool_call_id) ?? null) : null,
321
- advisorDecision: m.role === 'tool'
322
- && m.display_metadata?.kind === 'advisor_consultation'
323
- ? (advisorDecisions.get(m.display_metadata.consultationId) ?? null)
324
- : null,
325
307
  // 纯派生 key:有 id 用 id,没有就用 idx 兜底。绝不在 render 期 mutate 消息对象
326
308
  // (<Static> 已 commit 的行永不重绘,key 仅在 append 对账时用,idx 已足够稳定)。
327
309
  key: m.id ?? `message-${idx}`,
@@ -345,7 +327,6 @@ export const MessageList = React.memo(function MessageList({
345
327
  message={item.msg}
346
328
  turnMeta={item.turnMeta}
347
329
  toolMeta={item.toolMeta}
348
- advisorDecision={item.advisorDecision}
349
330
  foldReasoning={foldReasoning}
350
331
  />
351
332
  );
@@ -391,13 +372,11 @@ function MessageRow({
391
372
  message,
392
373
  turnMeta,
393
374
  toolMeta,
394
- advisorDecision,
395
375
  foldReasoning,
396
376
  }: {
397
377
  message: Message;
398
378
  turnMeta: TurnMeta | null;
399
379
  toolMeta?: ToolCallMeta | null;
400
- advisorDecision?: AdvisorDecisionMetadata | null;
401
380
  foldReasoning: boolean;
402
381
  }): JSX.Element | null {
403
382
  switch (message.role) {
@@ -553,30 +532,16 @@ function MessageRow({
553
532
  const lines = terminalText(message.content).split('\n');
554
533
  // 顾问意见给更高的预览上限,并用默认亮色而非 dim 灰 —— 它是另一个模型说的话,
555
534
  // 不该和 grep 输出一样被视觉降级(见 MAX_ADVISOR_PREVIEW_LINES)。
556
- const advisorMeta = message.display_metadata?.kind === 'advisor_consultation'
557
- ? message.display_metadata
558
- : null;
559
- const decisionMeta = message.display_metadata?.kind === 'advisor_decision'
560
- ? message.display_metadata
561
- : null;
562
535
  const inferredToolName = toolMeta?.toolName
563
- ?? (advisorMeta ? 'Advisor' : null)
564
- ?? (decisionMeta ? 'AdvisorDecision' : null)
565
536
  ?? (message.display_metadata?.kind === 'result_manifest' ? 'PresentResult' : null)
566
537
  ?? (message.display_metadata?.kind === 'agent' ? 'Agent' : undefined);
567
538
  const isAdvisor = inferredToolName === 'Advisor';
568
- const isAdvisorDecision = inferredToolName === 'AdvisorDecision';
569
539
  if (isAdvisor) lines.splice(0, lines.length, ...terminalText(advisorOpinionText(message.content)).split('\n'));
570
540
  const visibility = toolHistoryVisibility(inferredToolName, message.content);
571
541
  const previewCap = toolPreviewCap(inferredToolName);
572
542
  const previewLines = lines.slice(0, previewCap);
573
543
  const hidden = Math.max(0, lines.length - previewCap);
574
544
  const shortId = message.tool_call_id.slice(-8);
575
- if (message.display_metadata?.kind === 'advisor_checkpoint') {
576
- return <Box marginBottom={1} paddingLeft={2}><Text color={theme.subtle} wrap="end">
577
- {`已暂缓 · 顾问检查点 · 操作尚未执行(/show ${shortId} 查看详情,复核进展见后续记录)`}
578
- </Text></Box>;
579
- }
580
545
  // 头行升级:有 toolMeta(发起方反查命中)显示人话描述;Agent 子任务
581
546
  // 再解析统计尾巴显示 ✓ N 轮 · M 次工具。无 meta(历史重载等)兜底旧格式。
582
547
  const stats =
@@ -587,20 +552,11 @@ function MessageRow({
587
552
  // 顾问头行单独成文并去掉 dim:friendlyToolDescription 没有 Advisor 分支,
588
553
  // 走兜底会显示成一串参数预览,看不出这是「第二个模型的独立意见」。
589
554
  const headText = isAdvisor
590
- ? `[顾问意见 · ${advisorMeta?.checkpoint ?? 'manual'} · #${shortId}]`
591
- : isAdvisorDecision
592
- ? `[顾问意见处理 · ${decisionMeta?.decision ?? 'unknown'} · #${shortId}]`
555
+ ? `[顾问意见 · #${shortId}]`
593
556
  : toolMeta
594
557
  ? formatToolHead(toolMeta, shortId, statsTail)
595
558
  : `[tool result · #${shortId}]`;
596
559
  if (visibility === 'hidden') return null;
597
- if (isAdvisorDecision) {
598
- return <Box marginBottom={1} paddingLeft={2}><Text color={theme.subtle} wrap="end">
599
- {decisionMeta
600
- ? `顾问意见已处理 · ${advisorDecisionLabel(decisionMeta.decision)} · ${advisorEvidenceLabel(decisionMeta.verificationStatus)}`
601
- : '顾问意见登记未完成 · 可重试'}{`(/show ${shortId} 查看详情)`}
602
- </Text></Box>;
603
- }
604
560
  if (visibility === 'compact') {
605
561
  return (
606
562
  <Box marginBottom={1} paddingLeft={2}>
@@ -616,40 +572,6 @@ function MessageRow({
616
572
  <Text color={theme.subtle} {...(isAdvisor ? {} : { dimColor: true })} wrap="end">
617
573
  {terminalText(headText)}
618
574
  </Text>
619
- {advisorMeta && (
620
- <Box flexDirection="column">
621
- <Text color={theme.subtle} wrap="end">
622
- {terminalText(advisorMeta.status === 'completed'
623
- ? '顾问意见已返回,尚不代表事实核验通过'
624
- : '顾问咨询未完成,已降级继续')}
625
- </Text>
626
- {advisorMeta.status === 'completed' && !advisorDecision && (
627
- <Text color={theme.subtle} wrap="end">顾问意见已返回;主 Agent 的核验与采纳结论见后续记录。</Text>
628
- )}
629
- {advisorDecision && (
630
- <Text color={theme.subtle} wrap="end">
631
- {terminalText(`${advisorDecision.decision} · ${advisorDecision.rationale}`)}
632
- </Text>
633
- )}
634
- {advisorDecision?.verificationPlan.map((item) => (
635
- <Text key={`advisor-card-verify-${item}`} color={theme.subtle} wrap="end">
636
- {terminalText(`验证:${item}`)}
637
- </Text>
638
- ))}
639
- </Box>
640
- )}
641
- {decisionMeta && (
642
- <Box flexDirection="column">
643
- <Text color={theme.subtle} wrap="end">
644
- {terminalText(`关联咨询 ${decisionMeta.consultationId} · ${decisionMeta.rationale}`)}
645
- </Text>
646
- {decisionMeta.verificationPlan.map((item) => (
647
- <Text key={`advisor-verify-${item}`} color={theme.subtle} wrap="end">
648
- {terminalText(`验证:${item}`)}
649
- </Text>
650
- ))}
651
- </Box>
652
- )}
653
575
  {/* 逐行 wrap='end':整段默认 wrap 会注入真实换行,从预览复制会被硬断行 */}
654
576
  {previewLines.map((line, i) => (
655
577
  <Text key={`p-${i}`} {...(isAdvisor ? {} : { color: theme.subtle })} wrap="end">
@@ -14,6 +14,7 @@
14
14
  * 用 version 计数器驱动 setState 触发 re-render 是更顺手的写法。
15
15
  * ============================================================
16
16
  */
17
+ import { previousUserRequest } from '../../memory/recallQuery.js';
17
18
  import { stat } from 'node:fs/promises';
18
19
  import { createTurnSummary } from '../turnSummary.js';
19
20
  import { isRecoverableLoopError } from '../../runtime/eventSemantics.js';
@@ -529,6 +530,7 @@ export function useChat(args) {
529
530
  surface: 'tui',
530
531
  cwd: effectiveCwd,
531
532
  currentUserInput: trimmed,
533
+ previousUserInput: previousUserRequest(historyRef.current),
532
534
  workspaceId: workspace?.id,
533
535
  sessionId: activeSessionIdRef.current,
534
536
  interactiveAsk: true,
@@ -15,6 +15,7 @@
15
15
  * ============================================================
16
16
  */
17
17
 
18
+ import { previousUserRequest } from '../../memory/recallQuery.js';
18
19
  import { stat } from 'node:fs/promises';
19
20
  import { createTurnSummary } from '../turnSummary.js';
20
21
  import { isRecoverableLoopError } from '../../runtime/eventSemantics.js';
@@ -829,6 +830,7 @@ export function useChat(args: {
829
830
  surface: 'tui',
830
831
  cwd: effectiveCwd,
831
832
  currentUserInput: trimmed,
833
+ previousUserInput: previousUserRequest(historyRef.current),
832
834
  workspaceId: workspace?.id,
833
835
  sessionId: activeSessionIdRef.current,
834
836
  interactiveAsk: true,
@@ -38,7 +38,7 @@ export function toolBatchSummary(calls, maxItems = 2) {
38
38
  }
39
39
  /** 成功的普通工具结果不写 scrollback;失败和高价值结果仍保留。 */
40
40
  export function toolHistoryVisibility(toolName, content) {
41
- if (toolName === 'Advisor' || toolName === 'AdvisorDecision' || toolName === 'PresentResult'
41
+ if (toolName === 'Advisor' || toolName === 'PresentResult'
42
42
  || toolName === 'RememberMemory' || toolName === 'UpdateMemory' || toolName === 'ForgetMemory'
43
43
  || toolName === 'ConfirmMemory' || toolName === 'SetPersona' || toolName === 'ClearPersona')
44
44
  return 'full';
@@ -43,7 +43,7 @@ export type ToolHistoryVisibility = 'hidden' | 'compact' | 'full';
43
43
 
44
44
  /** 成功的普通工具结果不写 scrollback;失败和高价值结果仍保留。 */
45
45
  export function toolHistoryVisibility(toolName: string | undefined, content: string): ToolHistoryVisibility {
46
- if (toolName === 'Advisor' || toolName === 'AdvisorDecision' || toolName === 'PresentResult'
46
+ if (toolName === 'Advisor' || toolName === 'PresentResult'
47
47
  || toolName === 'RememberMemory' || toolName === 'UpdateMemory' || toolName === 'ForgetMemory'
48
48
  || toolName === 'ConfirmMemory' || toolName === 'SetPersona' || toolName === 'ClearPersona') return 'full';
49
49
  if (toolName === 'Agent') return 'compact';
@@ -295,7 +295,10 @@ export interface SkillInfo {
295
295
  unavailableReason?: string;
296
296
  }
297
297
 
298
- export type ApiFormat = 'openai' | 'anthropic';
298
+ export type ApiFormat = 'openai' | 'openai-responses' | 'anthropic';
299
+
300
+ /** 推理强度;缺省 = 不发送,沿用服务端对该模型的默认强度。 */
301
+ export type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
299
302
 
300
303
  /** 模型列表的一个条目(脱敏视图——apiKey 只给 configured 布尔位,不下发原文)。 */
301
304
  export interface ModelView {
@@ -317,6 +320,7 @@ export interface ModelView {
317
320
  contextWindow: number;
318
321
  maxTokens?: number;
319
322
  supportsVision?: boolean;
323
+ reasoningEffort?: ReasoningEffort;
320
324
  promptCache?: { mode: 'auto' | 'session-key' | 'disabled' };
321
325
  enabled: boolean;
322
326
  updatedAt: number;
@@ -347,10 +351,11 @@ export interface WebchatConfig {
347
351
  configured: boolean;
348
352
  enabled: boolean;
349
353
  mode: 'auto' | 'manual';
354
+ /** remind = 只提醒;followup = 实质回答未复核时再请求一次,让模型自己补问顾问。 */
355
+ enforcement: 'remind' | 'followup';
350
356
  /** 引用 models[].id;null = 未选。顾问不再自带一整套独立凭据。 */
351
357
  modelId: string | null;
352
358
  contextPolicy: 'full-relevant';
353
- shareSensitive: boolean;
354
359
  inputTokenBudget: number;
355
360
  timeoutMs: number;
356
361
  };
@@ -413,6 +418,8 @@ export interface ModelPatchFields {
413
418
  contextWindow?: number;
414
419
  maxTokens?: number;
415
420
  supportsVision?: boolean;
421
+ /** update 时 null = 清除,回到服务端对该模型的默认强度。 */
422
+ reasoningEffort?: ReasoningEffort | null;
416
423
  promptCache?: { mode: 'auto' | 'session-key' | 'disabled' };
417
424
  enabled?: boolean;
418
425
  }
@@ -431,8 +438,8 @@ export interface WebchatConfigPatch {
431
438
  clear?: boolean;
432
439
  enabled?: boolean;
433
440
  mode?: 'auto' | 'manual';
441
+ enforcement?: 'remind' | 'followup';
434
442
  modelId?: string | null;
435
- shareSensitive?: boolean;
436
443
  inputTokenBudget?: number;
437
444
  timeoutMs?: number;
438
445
  };