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
@@ -1,5 +1,5 @@
1
1
  import { dirname, resolve } from 'node:path';
2
- import type { AdvisorCoordinator } from '../advisor/advisorCoordinator.js';
2
+ import type { AdvisorNudge } from '../advisor/advisorNudge.js';
3
3
  import { countTextTokens } from '../context/tokenCounter.js';
4
4
  import { StallGuard, type StallObservation } from '../harness/stallGuard.js';
5
5
  import { loadProjectPromptInstructions } from '../prompts/projectInstructions.js';
@@ -21,12 +21,12 @@ export type WorkerOutcome = {
21
21
  interface ToolExecutorInput {
22
22
  options: Pick<RunQueryOptions,
23
23
  'signal' | 'sessionState' | 'agentHandoff' | 'hasQueuedInput' |
24
- 'advisorCheckpoints' | 'toolBoundaryLabel' | 'toolGate' |
24
+ 'toolBoundaryLabel' | 'toolGate' |
25
25
  'onToolStart' | 'onToolEnd' | 'commitFormalDelivery'>;
26
26
  runtimeContext: AgentRuntimeContext;
27
27
  toolCallContext: ToolCallContext;
28
28
  currentEffectiveToolSet: EffectiveToolSet;
29
- advisorCoordinator: AdvisorCoordinator;
29
+ advisorNudge: AdvisorNudge;
30
30
  stallGuard: StallGuard;
31
31
  modelEnvironmentCwd: string;
32
32
  observedRuleScopes: Map<string, string>;
@@ -41,7 +41,7 @@ export function createToolExecutor(input: ToolExecutorInput) {
41
41
  runtimeContext,
42
42
  toolCallContext,
43
43
  currentEffectiveToolSet,
44
- advisorCoordinator,
44
+ advisorNudge,
45
45
  stallGuard,
46
46
  modelEnvironmentCwd,
47
47
  observedRuleScopes,
@@ -56,7 +56,6 @@ export function createToolExecutor(input: ToolExecutorInput) {
56
56
  const runOneImpl = async (
57
57
  tc: ToolCall,
58
58
  reportProgress?: (message: string, detail?: import('../types.js').ToolProgressDetail) => void,
59
- advisorConsultation?: import('../types.js').AdvisorConsultationMetadata,
60
59
  ): Promise<WorkerOutcome> => {
61
60
  let started = false;
62
61
  try {
@@ -76,8 +75,9 @@ export function createToolExecutor(input: ToolExecutorInput) {
76
75
  result: { ok: false, disposition: 'deferred', error: 'aborted' },
77
76
  };
78
77
  }
79
- const advisorAvailable = currentEffectiveToolSet.names.has('Advisor');
80
- if (!advisorAvailable && stallGuard.shouldReject(tc)) {
78
+ // Rejecting a third identical failing call is the guard's own job, advisor or
79
+ // not: the advisor is only a reminder now, so nothing else stops the loop.
80
+ if (stallGuard.shouldReject(tc)) {
81
81
  return {
82
82
  tc,
83
83
  result: {
@@ -112,21 +112,6 @@ export function createToolExecutor(input: ToolExecutorInput) {
112
112
  },
113
113
  };
114
114
  }
115
- const checkpoint =
116
- options.advisorCheckpoints === false
117
- ? { allow: true as const }
118
- : advisorCoordinator.beforeTool(tc, {
119
- ...advisorSemanticsFor(
120
- tc,
121
- toolCallContext,
122
- currentEffectiveToolSet.tools.find((tool) => tool.name === tc.function.name),
123
- { treatVerificationAsReadOnly: true },
124
- ),
125
- retriesFailure: stallGuard.shouldReject(tc),
126
- });
127
- if (!checkpoint.allow) {
128
- return { tc, result: checkpoint.deferred! };
129
- }
130
115
  // 工具执行闸门:宿主注入后覆盖所有工具,包括只读工具。deny → 把 reason 当
131
116
  // tool_result 回填,模型据此改道/如实报告,不抛异常不中断整轮。宿主异常一律 deny。
132
117
  // Keep the host gate's side-effect classification identical to the
@@ -267,7 +252,6 @@ export function createToolExecutor(input: ToolExecutorInput) {
267
252
  options.onToolStart?.(tc.function.name, tc.id);
268
253
  result = await executeToolFn(tc.function.name, tc.function.arguments, signal, {
269
254
  ...toolCallContext,
270
- advisorConsultation,
271
255
  delegationTools: currentEffectiveToolSet.tools,
272
256
  cwd: sessionState?.activeWorktree?.path ?? toolCallContext.cwd,
273
257
  toolCallId: tc.id,
@@ -303,10 +287,9 @@ export function createToolExecutor(input: ToolExecutorInput) {
303
287
  };
304
288
  }
305
289
  }
306
- if (tc.function.name === 'Advisor' || tc.function.name === 'AdvisorDecision') {
307
- // 串行批次内下一项可能就是 AdvisorDecision/受保护写入,必须立即推进协调器状态。
308
- advisorCoordinator.observeToolResult(tc, result);
309
- }
290
+ // A successful consultation lets the model try the failing path again: the
291
+ // guard stops counting those failures against it.
292
+ if (tc.function.name === 'Advisor' && result.ok) stallGuard.noteConsultation();
310
293
  started = false;
311
294
  options.onToolEnd?.(tc.id, false);
312
295
  return { tc, result };
@@ -324,37 +307,11 @@ export function createToolExecutor(input: ToolExecutorInput) {
324
307
  };
325
308
 
326
309
  const runOne = async (tc: ToolCall, reportProgress?: Parameters<typeof runOneImpl>[1]): Promise<WorkerOutcome> => {
327
- // Also settle denied/invalid/unavailable calls that never reached the
328
- // provider adapter. This records a real attempt, not an ignored reminder.
329
- let consultation;
330
- if (tc.function.name === 'Advisor') {
331
- let reason: import('../types.js').AdvisorReason | undefined;
332
- try {
333
- reason = JSON.parse(tc.function.arguments).reason;
334
- } catch {
335
- /* validation handles malformed input */
336
- }
337
- consultation = advisorCoordinator.beginConsultation(reason);
338
- }
339
- const outcome = await runOneImpl(tc, reportProgress, consultation);
340
- if (
341
- consultation &&
342
- outcome.result.metadata?.kind !== 'advisor_consultation' &&
343
- !(!outcome.result.ok && outcome.result.error === 'aborted')
344
- ) {
345
- outcome.result = {
346
- ...outcome.result,
347
- metadata: advisorCoordinator.finishConsultation(consultation, outcome.result.ok),
348
- };
349
- }
350
- const metadata = outcome.result.metadata;
351
- if ((metadata?.kind === 'advisor_decision' && outcome.result.ok) || metadata?.kind === 'advisor_consultation') {
352
- if (metadata.checkpoint === 'stalled') stallGuard.completeReview(metadata.checkpointKey.split(':').at(-1)!);
353
- }
310
+ const outcome = await runOneImpl(tc, reportProgress);
354
311
  const failure = stallGuard.observeAttempt(tc, outcome.result);
355
312
  if (failure.stalled && failure.signature) {
356
313
  failureReviews.push(failure);
357
- advisorCoordinator.requireFailureReview(failure.signature, failure.attempts ?? []);
314
+ advisorNudge.notifyStalled(failure.signature);
358
315
  }
359
316
  return outcome;
360
317
  };
@@ -35,19 +35,8 @@ export function friendlyToolDescription(toolName, rawArgsJson, fileLabel) {
35
35
  return `技能 · ${truncate(args.name, 60)}`;
36
36
  case 'SearchSkills':
37
37
  return `查找技能 · ${truncate(args.query, 60)}`;
38
- case 'Advisor': {
39
- const reasons = {
40
- plan_review: '执行前评审',
41
- delivery_review: '交付前核验',
42
- stalled: '分析重复失败',
43
- uncertainty: '核查不确定问题',
44
- user_dissatisfaction: '复核用户反馈',
45
- evidence_conflict: '核查证据冲突',
46
- };
47
- return `咨询顾问 · ${reasons[String(args.reason)] ?? '独立第二意见'}`;
48
- }
49
- case 'AdvisorDecision':
50
- return `顾问建议 · ${truncate(args.decision ?? args.action, 40) || '记录核验与采纳结论'}`;
38
+ case 'Advisor':
39
+ return `咨询顾问 · ${args.reviewMode === 'full' ? '完整代码审查' : '独立第二意见'}`;
51
40
  case 'AskUserQuestion':
52
41
  return '询问关键决策';
53
42
  case 'PresentResult':
@@ -35,19 +35,8 @@ export function friendlyToolDescription(
35
35
  return `技能 · ${truncate(args.name, 60)}`;
36
36
  case 'SearchSkills':
37
37
  return `查找技能 · ${truncate(args.query, 60)}`;
38
- case 'Advisor': {
39
- const reasons: Record<string, string> = {
40
- plan_review: '执行前评审',
41
- delivery_review: '交付前核验',
42
- stalled: '分析重复失败',
43
- uncertainty: '核查不确定问题',
44
- user_dissatisfaction: '复核用户反馈',
45
- evidence_conflict: '核查证据冲突',
46
- };
47
- return `咨询顾问 · ${reasons[String(args.reason)] ?? '独立第二意见'}`;
48
- }
49
- case 'AdvisorDecision':
50
- return `顾问建议 · ${truncate(args.decision ?? args.action, 40) || '记录核验与采纳结论'}`;
38
+ case 'Advisor':
39
+ return `咨询顾问 · ${args.reviewMode === 'full' ? '完整代码审查' : '独立第二意见'}`;
51
40
  case 'AskUserQuestion':
52
41
  return '询问关键决策';
53
42
  case 'PresentResult':
@@ -2,8 +2,7 @@ import { isReadOnlyShellCommand, isVerificationShellCommand, isAdvisorInspection
2
2
  import { toolEffectFor } from '../tools/capabilities.js';
3
3
  import { getToolByName, getToolGateDetails } from '../tools/index.js';
4
4
  export function advisorSemanticsFor(call, context, tool,
5
- // 默认 false:只有 advisor 检查点/记账(beforeTool、observeToolResult、
6
- // 持久化的 advisorMutatesWorkspace 标注)才传 true。工作区租约判定
5
+ // 默认 false:只有顾问提醒的记账(AdvisorNudge.observeToolResult)才传 true。工作区租约判定
7
6
  // (needsWorkspaceLease)必须保持严格定义不受影响——验证类命令仍可能写
8
7
  // 构建产物/缓存,并发场景下让它绕开租约会重新引入竞态。
9
8
  opts) {
@@ -26,8 +25,8 @@ opts) {
26
25
  try {
27
26
  const input = JSON.parse(call.function.arguments || '{}');
28
27
  if (typeof input.command === 'string') {
29
- // 跑测试/构建/lint 只是核对现状,不该被当成"开始实施改动"而白白烧掉
30
- // pre-execution 检查点——即使它们可能写构建产物/缓存,不满足
28
+ // 跑测试/构建/lint 只是核对现状,不该被当成"开始实施改动"而过早提醒
29
+ // "动手前先咨询"——即使它们可能写构建产物/缓存,不满足
31
30
  // isReadOnlyShellCommand 的并发安全定义(见 opts 注释,那个场景仍要严格)。
32
31
  isReadOnly =
33
32
  isReadOnlyShellCommand(input.command) ||
@@ -1,4 +1,3 @@
1
- import type { AdvisorToolSemantics } from '../advisor/advisorCoordinator.js';
2
1
  import { isReadOnlyShellCommand, isVerificationShellCommand, isAdvisorInspectionCommand } from '../tools/bash/semantics.js';
3
2
  import { toolEffectFor } from '../tools/capabilities.js';
4
3
  import { getToolByName, getToolGateDetails } from '../tools/index.js';
@@ -7,12 +6,11 @@ export function advisorSemanticsFor(
7
6
  call: ToolCall,
8
7
  context?: ToolCallContext,
9
8
  tool?: Tool,
10
- // 默认 false:只有 advisor 检查点/记账(beforeTool、observeToolResult、
11
- // 持久化的 advisorMutatesWorkspace 标注)才传 true。工作区租约判定
9
+ // 默认 false:只有顾问提醒的记账(AdvisorNudge.observeToolResult)才传 true。工作区租约判定
12
10
  // (needsWorkspaceLease)必须保持严格定义不受影响——验证类命令仍可能写
13
11
  // 构建产物/缓存,并发场景下让它绕开租约会重新引入竞态。
14
12
  opts?: { treatVerificationAsReadOnly?: boolean },
15
- ): AdvisorToolSemantics {
13
+ ): { mutatesWorkspace: boolean } {
16
14
  const definition = tool ?? getToolByName(call.function.name);
17
15
  const gate = context ? getToolGateDetails(call.function.name, call.function.arguments, context) : undefined;
18
16
  // Reuse the tool's side-effect contract, including shell/scripts, Trash and
@@ -33,8 +31,8 @@ export function advisorSemanticsFor(
33
31
  command?: unknown;
34
32
  };
35
33
  if (typeof input.command === 'string') {
36
- // 跑测试/构建/lint 只是核对现状,不该被当成"开始实施改动"而白白烧掉
37
- // pre-execution 检查点——即使它们可能写构建产物/缓存,不满足
34
+ // 跑测试/构建/lint 只是核对现状,不该被当成"开始实施改动"而过早提醒
35
+ // "动手前先咨询"——即使它们可能写构建产物/缓存,不满足
38
36
  // isReadOnlyShellCommand 的并发安全定义(见 opts 注释,那个场景仍要严格)。
39
37
  isReadOnly =
40
38
  isReadOnlyShellCommand(input.command) ||