@qduc/term2 0.31.1 → 0.32.1

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 (294) hide show
  1. package/README.md +52 -370
  2. package/dist/agent.d.ts +2 -1
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +11 -1
  5. package/dist/agent.js.map +1 -1
  6. package/dist/app.d.ts +3 -1
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +44 -4
  9. package/dist/app.js.map +1 -1
  10. package/dist/build-info.json +2 -2
  11. package/dist/cli.js +13 -3
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/goal-command.d.ts.map +1 -1
  14. package/dist/commands/goal-command.js +9 -8
  15. package/dist/commands/goal-command.js.map +1 -1
  16. package/dist/commands/retry-failed-turn-command.d.ts.map +1 -1
  17. package/dist/commands/retry-failed-turn-command.js +3 -4
  18. package/dist/commands/retry-failed-turn-command.js.map +1 -1
  19. package/dist/components/InputBox.js +16 -9
  20. package/dist/components/InputBox.js.map +1 -1
  21. package/dist/components/layout/BackgroundTasksPanel.d.ts.map +1 -1
  22. package/dist/components/layout/BackgroundTasksPanel.js +6 -8
  23. package/dist/components/layout/BackgroundTasksPanel.js.map +1 -1
  24. package/dist/components/layout/BottomArea.d.ts.map +1 -1
  25. package/dist/components/layout/BottomArea.js +13 -11
  26. package/dist/components/layout/BottomArea.js.map +1 -1
  27. package/dist/components/message/MessageList.d.ts +3 -1
  28. package/dist/components/message/MessageList.d.ts.map +1 -1
  29. package/dist/components/message/MessageList.js +5 -2
  30. package/dist/components/message/MessageList.js.map +1 -1
  31. package/dist/components/message/SessionBoundary.d.ts +11 -0
  32. package/dist/components/message/SessionBoundary.d.ts.map +1 -0
  33. package/dist/components/message/SessionBoundary.js +22 -0
  34. package/dist/components/message/SessionBoundary.js.map +1 -0
  35. package/dist/components/prompt/ApprovalPrompt.d.ts.map +1 -1
  36. package/dist/components/prompt/ApprovalPrompt.js +22 -1
  37. package/dist/components/prompt/ApprovalPrompt.js.map +1 -1
  38. package/dist/contracts/provider-input.d.ts +10 -0
  39. package/dist/contracts/provider-input.d.ts.map +1 -1
  40. package/dist/contracts/provider-input.js.map +1 -1
  41. package/dist/contracts/run-termination.d.ts +3 -1
  42. package/dist/contracts/run-termination.d.ts.map +1 -1
  43. package/dist/hooks/settings-completion-config.d.ts.map +1 -1
  44. package/dist/hooks/settings-completion-config.js +1 -0
  45. package/dist/hooks/settings-completion-config.js.map +1 -1
  46. package/dist/lib/agent-chat-service.d.ts +6 -0
  47. package/dist/lib/agent-chat-service.d.ts.map +1 -1
  48. package/dist/lib/agent-chat-service.js +29 -5
  49. package/dist/lib/agent-chat-service.js.map +1 -1
  50. package/dist/lib/agent-client.d.ts +6 -0
  51. package/dist/lib/agent-client.d.ts.map +1 -1
  52. package/dist/lib/agent-client.js +82 -24
  53. package/dist/lib/agent-client.js.map +1 -1
  54. package/dist/lib/agent-configuration.d.ts +7 -3
  55. package/dist/lib/agent-configuration.d.ts.map +1 -1
  56. package/dist/lib/agent-configuration.js +10 -4
  57. package/dist/lib/agent-configuration.js.map +1 -1
  58. package/dist/lib/agent-factory.d.ts.map +1 -1
  59. package/dist/lib/agent-factory.js +15 -4
  60. package/dist/lib/agent-factory.js.map +1 -1
  61. package/dist/non-interactive.d.ts +5 -0
  62. package/dist/non-interactive.d.ts.map +1 -1
  63. package/dist/non-interactive.js +63 -6
  64. package/dist/non-interactive.js.map +1 -1
  65. package/dist/prompts/durable-goal-context.d.ts.map +1 -1
  66. package/dist/prompts/durable-goal-context.js +12 -2
  67. package/dist/prompts/durable-goal-context.js.map +1 -1
  68. package/dist/prompts/durable-goal-context.ts +13 -2
  69. package/dist/providers/ai-sdk-openrouter.provider.js +3 -2
  70. package/dist/providers/ai-sdk-openrouter.provider.js.map +1 -1
  71. package/dist/providers/ai-sdk-streamed-model.d.ts.map +1 -1
  72. package/dist/providers/ai-sdk-streamed-model.js +12 -2
  73. package/dist/providers/ai-sdk-streamed-model.js.map +1 -1
  74. package/dist/providers/codex-responses-model.d.ts.map +1 -1
  75. package/dist/providers/codex-responses-model.js +35 -16
  76. package/dist/providers/codex-responses-model.js.map +1 -1
  77. package/dist/providers/openai-chat-completions-model.d.ts.map +1 -1
  78. package/dist/providers/openai-chat-completions-model.js +11 -3
  79. package/dist/providers/openai-chat-completions-model.js.map +1 -1
  80. package/dist/services/agent-runtime/application-run-loop.d.ts +34 -1
  81. package/dist/services/agent-runtime/application-run-loop.d.ts.map +1 -1
  82. package/dist/services/agent-runtime/application-run-loop.js +174 -33
  83. package/dist/services/agent-runtime/application-run-loop.js.map +1 -1
  84. package/dist/services/agent-runtime/context-compaction/index.d.ts.map +1 -1
  85. package/dist/services/agent-runtime/context-compaction/index.js +65 -16
  86. package/dist/services/agent-runtime/context-compaction/index.js.map +1 -1
  87. package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts +7 -1
  88. package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts.map +1 -1
  89. package/dist/services/agent-runtime/context-compaction/local-context-compactor.js +115 -20
  90. package/dist/services/agent-runtime/context-compaction/local-context-compactor.js.map +1 -1
  91. package/dist/services/agent-runtime/model-context-policy.d.ts +21 -0
  92. package/dist/services/agent-runtime/model-context-policy.d.ts.map +1 -0
  93. package/dist/services/agent-runtime/model-context-policy.js +46 -0
  94. package/dist/services/agent-runtime/model-context-policy.js.map +1 -0
  95. package/dist/services/agent-runtime/request-input-limit.d.ts +31 -0
  96. package/dist/services/agent-runtime/request-input-limit.d.ts.map +1 -0
  97. package/dist/services/agent-runtime/request-input-limit.js +86 -0
  98. package/dist/services/agent-runtime/request-input-limit.js.map +1 -0
  99. package/dist/services/agent-runtime/run-budget.d.ts +3 -5
  100. package/dist/services/agent-runtime/run-budget.d.ts.map +1 -1
  101. package/dist/services/agent-runtime/run-budget.js.map +1 -1
  102. package/dist/services/agent-runtime/tool-call-execution.d.ts +24 -2
  103. package/dist/services/agent-runtime/tool-call-execution.d.ts.map +1 -1
  104. package/dist/services/agent-runtime/tool-call-execution.js +36 -6
  105. package/dist/services/agent-runtime/tool-call-execution.js.map +1 -1
  106. package/dist/services/agent-runtime/tool-invocation-context.d.ts +24 -12
  107. package/dist/services/agent-runtime/tool-invocation-context.d.ts.map +1 -1
  108. package/dist/services/agent-runtime/tool-invocation-context.js +38 -27
  109. package/dist/services/agent-runtime/tool-invocation-context.js.map +1 -1
  110. package/dist/services/approval/approval-replay.d.ts +15 -24
  111. package/dist/services/approval/approval-replay.d.ts.map +1 -1
  112. package/dist/services/approval/approval-replay.js +12 -30
  113. package/dist/services/approval/approval-replay.js.map +1 -1
  114. package/dist/services/approval/non-interactive-approval-policy.d.ts.map +1 -1
  115. package/dist/services/approval/non-interactive-approval-policy.js +11 -0
  116. package/dist/services/approval/non-interactive-approval-policy.js.map +1 -1
  117. package/dist/services/approval/tool-approval-batch-coordinator.d.ts.map +1 -1
  118. package/dist/services/approval/tool-approval-batch-coordinator.js +0 -5
  119. package/dist/services/approval/tool-approval-batch-coordinator.js.map +1 -1
  120. package/dist/services/conversation/conversation-checkpoint-provenance.d.ts.map +1 -1
  121. package/dist/services/conversation/conversation-checkpoint-provenance.js +10 -2
  122. package/dist/services/conversation/conversation-checkpoint-provenance.js.map +1 -1
  123. package/dist/services/conversation/conversation-events.d.ts +2 -0
  124. package/dist/services/conversation/conversation-events.d.ts.map +1 -1
  125. package/dist/services/conversation/conversation-events.js.map +1 -1
  126. package/dist/services/conversation/conversation-orchestrator.d.ts +1 -1
  127. package/dist/services/conversation/conversation-orchestrator.d.ts.map +1 -1
  128. package/dist/services/conversation/conversation-orchestrator.js +14 -2
  129. package/dist/services/conversation/conversation-orchestrator.js.map +1 -1
  130. package/dist/services/conversation/conversation-replay.d.ts.map +1 -1
  131. package/dist/services/conversation/conversation-replay.js +78 -3
  132. package/dist/services/conversation/conversation-replay.js.map +1 -1
  133. package/dist/services/conversation/conversation-service.d.ts +2 -2
  134. package/dist/services/conversation/conversation-service.d.ts.map +1 -1
  135. package/dist/services/conversation/conversation-service.js +5 -1
  136. package/dist/services/conversation/conversation-service.js.map +1 -1
  137. package/dist/services/conversation/conversation-state-projector.d.ts +1 -0
  138. package/dist/services/conversation/conversation-state-projector.d.ts.map +1 -1
  139. package/dist/services/conversation/conversation-state-projector.js +5 -1
  140. package/dist/services/conversation/conversation-state-projector.js.map +1 -1
  141. package/dist/services/conversation/durable-goal-stop-check.d.ts +141 -0
  142. package/dist/services/conversation/durable-goal-stop-check.d.ts.map +1 -0
  143. package/dist/services/conversation/durable-goal-stop-check.js +351 -0
  144. package/dist/services/conversation/durable-goal-stop-check.js.map +1 -0
  145. package/dist/services/conversation/durable-goal.d.ts +16 -1
  146. package/dist/services/conversation/durable-goal.d.ts.map +1 -1
  147. package/dist/services/conversation/durable-goal.js +8 -0
  148. package/dist/services/conversation/durable-goal.js.map +1 -1
  149. package/dist/services/conversation/local-checkpoint-projection.d.ts.map +1 -1
  150. package/dist/services/conversation/local-checkpoint-projection.js +12 -1
  151. package/dist/services/conversation/local-checkpoint-projection.js.map +1 -1
  152. package/dist/services/conversation/session-browser.d.ts +2 -0
  153. package/dist/services/conversation/session-browser.d.ts.map +1 -1
  154. package/dist/services/conversation/session-browser.js +23 -8
  155. package/dist/services/conversation/session-browser.js.map +1 -1
  156. package/dist/services/conversation/session-index/session-index-worker-client.d.ts +3 -0
  157. package/dist/services/conversation/session-index/session-index-worker-client.d.ts.map +1 -1
  158. package/dist/services/conversation/session-index/session-index-worker-client.js +6 -1
  159. package/dist/services/conversation/session-index/session-index-worker-client.js.map +1 -1
  160. package/dist/services/conversation/session-index/session-index-worker.d.ts +16 -1
  161. package/dist/services/conversation/session-index/session-index-worker.d.ts.map +1 -1
  162. package/dist/services/conversation/session-index/session-index-worker.js +16 -0
  163. package/dist/services/conversation/session-index/session-index-worker.js.map +1 -1
  164. package/dist/services/conversation-agent-client.d.ts +1 -0
  165. package/dist/services/conversation-agent-client.d.ts.map +1 -1
  166. package/dist/services/logging/conversation-log-events.d.ts +7 -0
  167. package/dist/services/logging/conversation-log-events.d.ts.map +1 -1
  168. package/dist/services/logging/conversation-log-events.js.map +1 -1
  169. package/dist/services/retry/retry-classifier.d.ts.map +1 -1
  170. package/dist/services/retry/retry-classifier.js +2 -1
  171. package/dist/services/retry/retry-classifier.js.map +1 -1
  172. package/dist/services/retry/retry-error-classification.d.ts.map +1 -1
  173. package/dist/services/retry/retry-error-classification.js +1 -0
  174. package/dist/services/retry/retry-error-classification.js.map +1 -1
  175. package/dist/services/service-interfaces.d.ts +2 -0
  176. package/dist/services/service-interfaces.d.ts.map +1 -1
  177. package/dist/services/session/initial-turn-recovery-handler.d.ts.map +1 -1
  178. package/dist/services/session/initial-turn-recovery-handler.js +6 -0
  179. package/dist/services/session/initial-turn-recovery-handler.js.map +1 -1
  180. package/dist/services/session/session-composition.d.ts.map +1 -1
  181. package/dist/services/session/session-composition.js +7 -5
  182. package/dist/services/session/session-composition.js.map +1 -1
  183. package/dist/services/session/session-manager.d.ts +2 -0
  184. package/dist/services/session/session-manager.d.ts.map +1 -1
  185. package/dist/services/session/session-manager.js +10 -0
  186. package/dist/services/session/session-manager.js.map +1 -1
  187. package/dist/services/session/session-stream-processor.d.ts.map +1 -1
  188. package/dist/services/session/session-stream-processor.js +11 -0
  189. package/dist/services/session/session-stream-processor.js.map +1 -1
  190. package/dist/services/session/session-tool-tracker.d.ts +18 -1
  191. package/dist/services/session/session-tool-tracker.d.ts.map +1 -1
  192. package/dist/services/session/session-tool-tracker.js +38 -1
  193. package/dist/services/session/session-tool-tracker.js.map +1 -1
  194. package/dist/services/session/terminal-result-collector.d.ts.map +1 -1
  195. package/dist/services/session/terminal-result-collector.js +3 -0
  196. package/dist/services/session/terminal-result-collector.js.map +1 -1
  197. package/dist/services/session/turn-workflow.d.ts.map +1 -1
  198. package/dist/services/session/turn-workflow.js +3 -0
  199. package/dist/services/session/turn-workflow.js.map +1 -1
  200. package/dist/services/settings/settings-env.d.ts.map +1 -1
  201. package/dist/services/settings/settings-env.js +6 -0
  202. package/dist/services/settings/settings-env.js.map +1 -1
  203. package/dist/services/settings/settings-persistence.d.ts +2 -1
  204. package/dist/services/settings/settings-persistence.d.ts.map +1 -1
  205. package/dist/services/settings/settings-persistence.js +1 -1
  206. package/dist/services/settings/settings-persistence.js.map +1 -1
  207. package/dist/services/settings/settings-schema.d.ts +7 -1
  208. package/dist/services/settings/settings-schema.d.ts.map +1 -1
  209. package/dist/services/settings/settings-schema.js +17 -6
  210. package/dist/services/settings/settings-schema.js.map +1 -1
  211. package/dist/services/settings/settings-service.d.ts +3 -0
  212. package/dist/services/settings/settings-service.d.ts.map +1 -1
  213. package/dist/services/settings/settings-service.js +74 -31
  214. package/dist/services/settings/settings-service.js.map +1 -1
  215. package/dist/services/settings/settings-sources.d.ts +1 -0
  216. package/dist/services/settings/settings-sources.d.ts.map +1 -1
  217. package/dist/services/settings/settings-sources.js +1 -0
  218. package/dist/services/settings/settings-sources.js.map +1 -1
  219. package/dist/services/settings/settings-ui-metadata.js +1 -1
  220. package/dist/services/settings/settings-ui-metadata.js.map +1 -1
  221. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts +1 -1
  222. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts.map +1 -1
  223. package/dist/services/settings/test-helpers/settings-consumer-inventory.js +1 -0
  224. package/dist/services/settings/test-helpers/settings-consumer-inventory.js.map +1 -1
  225. package/dist/services/subagents/execution-runner.d.ts.map +1 -1
  226. package/dist/services/subagents/execution-runner.js +16 -3
  227. package/dist/services/subagents/execution-runner.js.map +1 -1
  228. package/dist/services/subagents/nested-runner.d.ts.map +1 -1
  229. package/dist/services/subagents/nested-runner.js +3 -2
  230. package/dist/services/subagents/nested-runner.js.map +1 -1
  231. package/dist/services/tool-execution-ledger.d.ts +22 -0
  232. package/dist/services/tool-execution-ledger.d.ts.map +1 -1
  233. package/dist/services/tool-execution-ledger.js +40 -3
  234. package/dist/services/tool-execution-ledger.js.map +1 -1
  235. package/dist/services/workflow-evolution/cli.d.ts +2 -0
  236. package/dist/services/workflow-evolution/cli.d.ts.map +1 -0
  237. package/dist/services/workflow-evolution/cli.js +26 -0
  238. package/dist/services/workflow-evolution/cli.js.map +1 -0
  239. package/dist/services/workflow-evolution/demo.d.ts +18 -0
  240. package/dist/services/workflow-evolution/demo.d.ts.map +1 -0
  241. package/dist/services/workflow-evolution/demo.js +177 -0
  242. package/dist/services/workflow-evolution/demo.js.map +1 -0
  243. package/dist/services/workflow-evolution/experiment.d.ts +304 -0
  244. package/dist/services/workflow-evolution/experiment.d.ts.map +1 -0
  245. package/dist/services/workflow-evolution/experiment.js +251 -0
  246. package/dist/services/workflow-evolution/experiment.js.map +1 -0
  247. package/dist/services/workflow-evolution/ledger.d.ts +5 -0
  248. package/dist/services/workflow-evolution/ledger.d.ts.map +1 -0
  249. package/dist/services/workflow-evolution/ledger.js +57 -0
  250. package/dist/services/workflow-evolution/ledger.js.map +1 -0
  251. package/dist/skins/rail/status.d.ts.map +1 -1
  252. package/dist/skins/rail/status.js +21 -11
  253. package/dist/skins/rail/status.js.map +1 -1
  254. package/dist/tools/agent/goal-check.d.ts +23 -0
  255. package/dist/tools/agent/goal-check.d.ts.map +1 -0
  256. package/dist/tools/agent/goal-check.js +79 -0
  257. package/dist/tools/agent/goal-check.js.map +1 -0
  258. package/dist/tools/system/run-code/run-code-runtime.d.ts.map +1 -1
  259. package/dist/tools/system/run-code/run-code-runtime.js +3 -1
  260. package/dist/tools/system/run-code/run-code-runtime.js.map +1 -1
  261. package/dist/tools/tool-names.d.ts +1 -0
  262. package/dist/tools/tool-names.d.ts.map +1 -1
  263. package/dist/tools/tool-names.js +1 -0
  264. package/dist/tools/tool-names.js.map +1 -1
  265. package/dist/tools/types.d.ts +21 -0
  266. package/dist/tools/types.d.ts.map +1 -1
  267. package/dist/tools/types.js +7 -0
  268. package/dist/tools/types.js.map +1 -1
  269. package/dist/utils/conversation/conversation-event-handler.d.ts.map +1 -1
  270. package/dist/utils/conversation/conversation-event-handler.js +7 -1
  271. package/dist/utils/conversation/conversation-event-handler.js.map +1 -1
  272. package/dist/utils/output/text-snippet.js +25 -33
  273. package/dist/utils/output/text-snippet.js.map +1 -1
  274. package/dist/utils/streaming/extract-command-messages.d.ts +2 -0
  275. package/dist/utils/streaming/extract-command-messages.d.ts.map +1 -1
  276. package/dist/utils/streaming/extract-command-messages.js +4 -0
  277. package/dist/utils/streaming/extract-command-messages.js.map +1 -1
  278. package/dist/utils/value-suggestions.d.ts.map +1 -1
  279. package/dist/utils/value-suggestions.js +1 -0
  280. package/dist/utils/value-suggestions.js.map +1 -1
  281. package/package.json +3 -5
  282. package/dist/prompts/durable-goal-context.test.ts +0 -56
  283. package/dist/prompts/explorer-delegation-contract.test.ts +0 -44
  284. package/dist/prompts/memory-recall-notice.test.ts +0 -50
  285. package/dist/prompts/orchestrator-prompt.test.ts +0 -111
  286. package/dist/prompts/prefix-quality.test.ts +0 -115
  287. package/dist/prompts/prompt-constructor.test.ts +0 -423
  288. package/dist/prompts/prompt-profiles.test.ts +0 -22
  289. package/dist/prompts/reasoning-efficiency.test.ts +0 -12
  290. package/dist/prompts/search-via-shell.test.ts +0 -69
  291. package/dist/prompts/steering-notice.test.ts +0 -36
  292. package/dist/prompts/subagent-delegation.test.ts +0 -112
  293. package/dist/prompts/subagents/worker-prompt.test.ts +0 -54
  294. package/dist/prompts/unified-gpt-prompt.test.ts +0 -53
@@ -1,423 +0,0 @@
1
- import { it, expect } from 'vitest';
2
- import { readFileSync } from 'node:fs';
3
- import { join } from 'node:path';
4
- import { buildPromptSpec } from './prompt-constructor.js';
5
- import { resolveProfile } from '../services/profiles/index.js';
6
- import { getAgentDefinition } from '../agent.js';
7
- import { createMockSettingsService } from '../services/settings/settings-service.mock.js';
8
- import { ExecutionContext } from '../services/execution-context.js';
9
- import { BackgroundShellRegistry } from '../services/shell/background-shell-registry.js';
10
- import { BackgroundShellOutputStore } from '../services/shell/background-shell-output-store.js';
11
- import { BackgroundShellWatches } from '../services/shell/background-shell-watches.js';
12
- import { SessionBrowser } from '../services/conversation/session-browser.js';
13
- import { RUN_CODE_PROHIBITED_TOOLS } from '../tools/system/run-code/run-code.js';
14
- import { getBackgroundShellAddendum } from './background-shell.js';
15
- import { getSubagentDelegationAddendum } from './subagent-delegation.js';
16
- import { getDirectEditorToolsAddendum, getScriptPrimaryToolsAddendum } from './tool-surface-guidance.js';
17
-
18
- it('guides run_code exact searches and syntax-sensitive data', () => {
19
- const guidance = getScriptPrimaryToolsAddendum('editors');
20
-
21
- expect(guidance).toContain('fixed_strings: true');
22
- expect(guidance).toContain('pattern` is a regular expression');
23
- expect(guidance).toContain('pass it through the `run_code` `inputs` parameter');
24
- expect(guidance).toContain(
25
- '- For multiline edit text or data containing quotes, backticks, or `${...}`, pass it through the `run_code` `inputs` parameter instead of embedding it in JavaScript source.',
26
- );
27
- });
28
-
29
- it('names only editors on the active run_code editing surface and identifies shell as direct-only', () => {
30
- const patchSurface = buildPromptSpec({
31
- model: 'gpt-5.6',
32
- profile: profile('builtin:standard'),
33
- runCodeEnabled: true,
34
- editorSurface: 'patch',
35
- }).inlineSections.join('\n');
36
- const otherSurface = buildPromptSpec({
37
- model: 'claude-3.7-sonnet',
38
- profile: profile('builtin:standard'),
39
- runCodeEnabled: true,
40
- editorSurface: 'editors',
41
- }).inlineSections.join('\n');
42
- const noWriteSurface = buildPromptSpec({
43
- model: 'claude-3.7-sonnet',
44
- profile: profile('builtin:standard'),
45
- runCodeEnabled: true,
46
- editorSurface: 'none',
47
- }).inlineSections.join('\n');
48
-
49
- expect(patchSurface).toContain('`tools.apply_patch`');
50
- expect(patchSurface).not.toContain('`tools.create_file`');
51
- expect(patchSurface).not.toContain('`tools.search_replace`');
52
- expect(patchSurface).toContain('create new files with a `*** Add File:` patch');
53
- expect(otherSurface).toContain('`tools.create_file`');
54
- expect(otherSurface).toContain('`tools.search_replace`');
55
- expect(otherSurface).not.toContain('`tools.apply_patch`');
56
- expect(noWriteSurface).not.toContain('`tools.apply_patch`');
57
- expect(noWriteSurface).not.toContain('`tools.create_file`');
58
- expect(noWriteSurface).not.toContain('`tools.search_replace`');
59
- for (const surface of [patchSurface, otherSurface, noWriteSurface]) {
60
- expect(surface).toContain('`tools.shell` does not exist inside `run_code`');
61
- }
62
- expect(patchSurface).toContain('Do not write files with');
63
- expect(otherSurface).toContain('Do not write files with');
64
- expect(patchSurface).toContain('heredocs, Python, or other shell tricks');
65
- expect(otherSurface).toContain('heredocs, Python, or other shell tricks');
66
- for (const surface of [patchSurface, otherSurface, noWriteSurface]) {
67
- expect(surface).toContain('Do not use Python to read files when `tools.read_file` is available');
68
- }
69
- expect(noWriteSurface).not.toContain('Do not write files with');
70
- expect(noWriteSurface).toContain('## File, search, and web tools');
71
- expect(noWriteSurface).toContain('tools.grep({ pattern, fixed_strings: true })');
72
- expect(noWriteSurface).not.toContain('\\n\\n');
73
- expect(patchSurface).toContain('`shell` is a direct tool');
74
- expect(patchSurface).toContain('File, search, web, and edit tools are not on your direct tool list.');
75
- expect(otherSurface).toContain('File, search, web, and edit tools are not on your direct tool list.');
76
- expect(noWriteSurface).toContain('File, search, and web tools are not on your direct tool list.');
77
- expect(patchSurface).toContain('`tools.shell` does not exist inside `run_code`');
78
- });
79
-
80
- const fullCapabilityLogging = {
81
- debug: () => {},
82
- info: () => {},
83
- warn: () => {},
84
- error: () => {},
85
- security: () => {},
86
- setCorrelationId: () => {},
87
- clearCorrelationId: () => {},
88
- getCorrelationId: () => undefined,
89
- } as any;
90
-
91
- function fullCapabilityTools() {
92
- const settingsService = createMockSettingsService({
93
- 'agent.model': 'gpt-4o',
94
- 'agent.smartModel': 'gpt-4o',
95
- 'app.searchViaShell': 'off',
96
- enable_agent_workflow: true,
97
- 'sandbox.enabled': true,
98
- });
99
- const executionContext = new ExecutionContext();
100
- const backgroundShellRegistry = new BackgroundShellRegistry();
101
- const store = new BackgroundShellOutputStore();
102
- const backgroundShellOutput = {
103
- store,
104
- watches: new BackgroundShellWatches({ store, scheduler: { schedule: () => 0, cancel: () => {} } }),
105
- };
106
- const skillsService = {
107
- getAvailableSkillsForModel: () => [{ name: 'measurement', location: '/tmp/measurement', body: '' }],
108
- getSkillCatalog: () => '',
109
- } as any;
110
- const sessionBrowser = new SessionBrowser(() => ({ projectPath: process.cwd() }));
111
- const status = {
112
- runId: 'measurement',
113
- role: 'worker',
114
- status: 'completed',
115
- task: 'measurement',
116
- taskPreview: 'measurement',
117
- startedAt: 0,
118
- elapsedMs: 0,
119
- toolCounts: {},
120
- } as any;
121
- return getAgentDefinition(
122
- {
123
- settingsService,
124
- loggingService: fullCapabilityLogging,
125
- executionContext,
126
- askMentor: async () => 'mentor',
127
- runSubagent: async () => ({ finalText: 'subagent' }),
128
- runSubagentAsync: async () => ({ runId: 'measurement', role: 'worker', status: 'running', task: 'measurement' }),
129
- getSubagentResult: async () => ({
130
- agentId: 'measurement',
131
- role: 'worker',
132
- status: 'completed',
133
- finalText: 'subagent',
134
- filesChanged: [],
135
- toolsUsed: [],
136
- }),
137
- getSubagentStatus: () => status,
138
- sendSubagentMessage: () => ({ ok: true, runId: 'measurement', status: 'running', delivery: 'queued' }),
139
- cancelSubagentRun: () => ({ ok: true, runId: 'measurement', status: 'cancelling' }),
140
- getAskUserAnswer: () => 'answer',
141
- skillsService,
142
- agentRuntime: { agent: () => ({} as any) },
143
- backgroundShellRegistry: backgroundShellRegistry as any,
144
- backgroundShellOutput,
145
- sessionBrowser,
146
- requestSessionRollover: () => ({} as any),
147
- configureTaskCheckIn: () => ({} as any),
148
- setTaskCheckInPolicy: () => {},
149
- },
150
- 'gpt-4o',
151
- ).tools;
152
- }
153
-
154
- const profile = (id: string) => resolveProfile(id);
155
-
156
- it('buildPromptSpec selects the profile identity and model-family base prompt', () => {
157
- expect(buildPromptSpec({ model: 'gpt-5.5', profile: profile('builtin:lite') }).basePromptContent).toBeTruthy();
158
- expect(buildPromptSpec({ model: 'claude-3-sonnet', profile: profile('builtin:standard') }).basePromptFile).toBe(
159
- 'anthropic.md',
160
- );
161
- expect(buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:standard') }).basePromptFile).toBe(
162
- 'simple_v4.md',
163
- );
164
- });
165
-
166
- it('buildPromptSpec keeps all non-lite built-in profiles prompt-spec equivalent', () => {
167
- const specs = ['standard', 'plan', 'mentor', 'orchestrator'].map((id) =>
168
- buildPromptSpec({ model: 'gpt-5.6', profile: profile(`builtin:${id}`) }),
169
- );
170
- expect(specs[1]).toEqual(specs[0]);
171
- expect(specs[2]).toEqual(specs[0]);
172
- expect(specs[3]).toEqual(specs[0]);
173
- expect(buildPromptSpec({ model: 'gpt-5.6', profile: profile('builtin:lite') })).not.toEqual(specs[0]);
174
- });
175
-
176
- it('buildPromptSpec composes file fragments in stable order', () => {
177
- const spec = buildPromptSpec({
178
- model: 'gpt-5.4-mini',
179
- profile: profile('builtin:standard'),
180
- searchViaShell: true,
181
- });
182
-
183
- expect(spec.fragmentFiles).toEqual([
184
- 'approval-model.md',
185
- 'worktree-hygiene.md',
186
- 'plan-mode-stub.md',
187
- 'pair-mode-stub.md',
188
- 'mentor-mode-stub.md',
189
- 'orchestrator-mode-stub.md',
190
- ]);
191
-
192
- expect(spec.inlineSections).toContainEqual(expect.stringContaining('## Shell Sandbox'));
193
- });
194
-
195
- it('does not teach loaded run_code instruction surfaces to call script-only tools directly', () => {
196
- const tools = fullCapabilityTools();
197
- const scriptOnly = tools.filter((tool) => !RUN_CODE_PROHIBITED_TOOLS.has(tool.name)).map((tool) => tool.name);
198
- const surfaces = ['lite.md', 'session-browser.md', 'orchestrator.md', 'gpt.md'].map((file) =>
199
- readFileSync(join(import.meta.dirname, file), 'utf8'),
200
- );
201
- surfaces.push(
202
- getScriptPrimaryToolsAddendum('editors'),
203
- getBackgroundShellAddendum(),
204
- getSubagentDelegationAddendum({ backgroundEnabled: true, controlsEnabled: true, foregroundEnabled: false }),
205
- );
206
-
207
- const directReferences = scriptOnly.flatMap((name) => {
208
- const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
209
- // This preceding-dot exclusion is load-bearing: tools.<name> is the valid
210
- // script reference form and must not count as a bare direct-tool reference.
211
- const pattern = new RegExp(`(?<![A-Za-z0-9_.])${escaped}(?![A-Za-z0-9_])`);
212
- return surfaces.some((surface) => pattern.test(surface)) ? [name] : [];
213
- });
214
-
215
- expect(directReferences).toEqual([]);
216
- });
217
-
218
- it('selects script-primary vs direct-editor guidance from runCodeEnabled', () => {
219
- const enabled = buildPromptSpec({
220
- model: 'gpt-5.6',
221
- profile: profile('builtin:standard'),
222
- runCodeEnabled: true,
223
- editorSurface: 'patch',
224
- });
225
- const disabled = buildPromptSpec({
226
- model: 'gpt-5.6',
227
- profile: profile('builtin:standard'),
228
- runCodeEnabled: false,
229
- });
230
- expect(enabled.inlineSections.join('\n')).toContain(getScriptPrimaryToolsAddendum('patch'));
231
- expect(enabled.inlineSections.join('\n')).not.toContain(getDirectEditorToolsAddendum());
232
- expect(disabled.inlineSections.join('\n')).toContain(getDirectEditorToolsAddendum());
233
- expect(disabled.inlineSections.join('\n')).not.toContain(getScriptPrimaryToolsAddendum('patch'));
234
- });
235
-
236
- it('buildPromptSpec ships the approval mechanism to every non-lite profile', () => {
237
- for (const model of ['gpt-5.6-sol', 'gpt-5.5', 'gpt-5.4', 'gpt-4o', 'claude-opus-4', 'kimi-k2']) {
238
- const spec = buildPromptSpec({ model, profile: profile('builtin:standard') });
239
- expect(spec.fragmentFiles).toContain('approval-model.md');
240
- }
241
-
242
- const orchestrator = buildPromptSpec({ model: 'gpt-5.6-sol', profile: profile('builtin:orchestrator') });
243
- expect(orchestrator.fragmentFiles).toContain('approval-model.md');
244
-
245
- const lite = buildPromptSpec({ model: 'gpt-5.6-sol', profile: profile('builtin:lite') });
246
- expect(lite.fragmentFiles).not.toContain('approval-model.md');
247
- });
248
-
249
- it('buildPromptSpec attaches the Plan Mode stub in standard and plan mode so the instruction prefix stays cache-stable', () => {
250
- const standard = buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:standard') });
251
- expect(standard.fragmentFiles.includes('plan-mode-stub.md')).toBe(true);
252
- expect(standard.fragmentFiles.includes('plan-mode-info.md')).toBe(false);
253
-
254
- const plan = buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:plan') });
255
- expect(plan.fragmentFiles.includes('plan-mode-stub.md')).toBe(true);
256
- expect(plan.fragmentFiles.includes('plan-mode-info.md')).toBe(false);
257
- expect(plan.fragmentFiles).toEqual(standard.fragmentFiles);
258
- });
259
-
260
- it('buildPromptSpec keeps all non-lite mode stubs stable while lite stays minimal', () => {
261
- const lite = buildPromptSpec({ model: 'gpt-5.5', profile: profile('builtin:lite') });
262
- expect(lite.fragmentFiles.includes('plan-mode-info.md')).toBe(false);
263
- expect(lite.fragmentFiles.includes('plan-mode-stub.md')).toBe(false);
264
- expect(lite.fragmentFiles.includes('mentor-mode-stub.md')).toBe(false);
265
- expect(lite.fragmentFiles.includes('orchestrator-mode-stub.md')).toBe(false);
266
-
267
- const orchestrator = buildPromptSpec({ model: 'gpt-5.5', profile: profile('builtin:orchestrator') });
268
- expect(orchestrator.fragmentFiles.includes('plan-mode-info.md')).toBe(false);
269
- expect(orchestrator.fragmentFiles.includes('plan-mode-stub.md')).toBe(true);
270
- expect(orchestrator.fragmentFiles.includes('mentor-mode-stub.md')).toBe(true);
271
- expect(orchestrator.fragmentFiles.includes('orchestrator-mode-stub.md')).toBe(true);
272
- });
273
-
274
- it('buildPromptSpec keeps the non-lite instruction prefix identical across modes', () => {
275
- const standard = buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:standard') });
276
- const plan = buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:plan') });
277
- const mentor = buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:mentor') });
278
- const orchestrator = buildPromptSpec({ model: 'gpt-4o', profile: profile('builtin:orchestrator') });
279
-
280
- expect(plan).toEqual(standard);
281
- expect(mentor).toEqual(standard);
282
- expect(orchestrator).toEqual(standard);
283
- });
284
-
285
- it('buildPromptSpec includes subagent delegation for orchestrator mode', () => {
286
- const orchestrator = buildPromptSpec({
287
- model: 'gpt-5.5',
288
- profile: profile('builtin:orchestrator'),
289
- runSubagentEnabled: true,
290
- codeContextEnabled: true,
291
- searchViaShell: false,
292
- });
293
- expect(orchestrator.inlineSections.some((s) => s.includes('Delegating to subagents'))).toBe(true);
294
- expect(orchestrator.inlineSections.some((s) => s.includes('Delegate when it provides meaningful leverage'))).toBe(
295
- true,
296
- );
297
- expect(orchestrator.inlineSections.some((s) => s.includes('Delegate workspace inspection'))).toBe(false);
298
- expect(orchestrator.inlineSections.some((s) => s.includes('Code Context'))).toBe(false);
299
- });
300
-
301
- it('buildPromptSpec uses lite base and skips worktree-hygiene fragment in lite mode', () => {
302
- const lite = buildPromptSpec({
303
- model: 'gpt-5.5',
304
- profile: profile('builtin:lite'),
305
- codeContextEnabled: true,
306
- searchViaShell: false,
307
- });
308
- expect(lite.basePromptFile).toBeUndefined();
309
- expect(lite.basePromptContent).toBeTruthy();
310
- expect(lite.fragmentFiles.includes('worktree-hygiene.md')).toBe(false);
311
- // Shell sandbox plus tool-surface routing are added inline in lite mode.
312
- expect(lite.inlineSections.length).toBe(2);
313
- expect(lite.inlineSections[0]).toContain('## Shell Sandbox');
314
- expect(lite.inlineSections[1]).toContain('## File, search, and edit tools');
315
- });
316
-
317
- it('buildPromptSpec excludes shell-sandbox when sandbox is disabled', () => {
318
- const spec = buildPromptSpec({
319
- model: 'gpt-4o',
320
- profile: profile('builtin:standard'),
321
- sandboxEnabled: false,
322
- });
323
- expect(spec.inlineSections.some((s) => s.includes('## Shell Sandbox'))).toBe(false);
324
- expect(spec.fragmentFiles.includes('worktree-hygiene.md')).toBe(true);
325
- });
326
-
327
- it('buildPromptSpec tells the model to wait for background shell completion instead of polling', () => {
328
- const spec = buildPromptSpec({
329
- model: 'gpt-4o',
330
- profile: profile('builtin:standard'),
331
- backgroundShellEnabled: true,
332
- });
333
- const guidance = spec.inlineSections.join('\n');
334
-
335
- expect(guidance).toContain('Background shell jobs');
336
- expect(guidance).toContain('`background: true`');
337
- expect(guidance).toContain('do NOT call `tools.get_shell_job(...)` as a polling loop');
338
- expect(guidance.toLowerCase()).toContain('end the current turn and wait for the automatic completion notification');
339
- expect(guidance.toLowerCase()).toContain('do not run `sleep` merely to wait');
340
- });
341
-
342
- it('includes one memory guidance section and gates the pinned context by regular memory mode', () => {
343
- const args = {
344
- model: 'gpt-4o',
345
- profile: profile('builtin:standard'),
346
- memoryGuidance: 'Memory guidance',
347
- memoryContext: 'Global-only index',
348
- };
349
- const enabled = buildPromptSpec({ ...args, memoryEnabled: true });
350
- expect(enabled.inlineSections.filter((section) => section === 'Memory guidance')).toHaveLength(1);
351
- expect(enabled.inlineSections).toContain('Global-only index');
352
- expect(buildPromptSpec({ ...args, memoryEnabled: false }).inlineSections).not.toContain('Global-only index');
353
- expect(
354
- buildPromptSpec({ ...args, profile: profile('builtin:lite'), memoryEnabled: true }).inlineSections,
355
- ).not.toContain('Global-only index');
356
- });
357
-
358
- it('buildPromptSpec includes unified background delegation guidance when background execution is enabled', () => {
359
- const spec = buildPromptSpec({
360
- model: 'gpt-4o',
361
- profile: profile('builtin:standard'),
362
- runSubagentEnabled: true,
363
- runSubagentAsyncEnabled: true,
364
- });
365
- expect(spec.inlineSections.some((s) => s.includes('execution: "background"'))).toBe(true);
366
- expect(spec.inlineSections.some((s) => s.includes('run_subagent_async'))).toBe(false);
367
- expect(spec.inlineSections.some((s) => s.includes('get_subagent_result'))).toBe(true);
368
- expect(spec.inlineSections.some((s) => s.includes('explorer'))).toBe(true);
369
- expect(spec.inlineSections.some((s) => s.includes('worker'))).toBe(true);
370
- expect(spec.inlineSections.some((s) => s.includes('mentor'))).toBe(true);
371
- });
372
-
373
- it('buildPromptSpec tells orchestrators to trust successful delegation and wait without duplicating it', () => {
374
- const spec = buildPromptSpec({
375
- model: 'gpt-4o',
376
- profile: profile('builtin:orchestrator'),
377
- runSubagentEnabled: true,
378
- runSubagentAsyncEnabled: true,
379
- });
380
- const guidance = spec.inlineSections.join('\n');
381
-
382
- expect(guidance).toContain('`execution: "background"`');
383
- expect(guidance).toContain('A returned handle with `status: "running"` means delegation succeeded');
384
- expect(guidance).toContain('Do not duplicate or independently perform the delegated unit');
385
- expect(guidance.toLowerCase()).toContain('end the current turn and wait for the completion notification');
386
- expect(guidance).toContain('inlines the full result so you can continue directly');
387
- expect(guidance).toContain('do NOT call `tools.get_subagent_result(...)` immediately');
388
- expect(guidance).toContain('Active runs are refused rather than awaited');
389
- expect(guidance).not.toContain('Use `run_subagent` only');
390
- });
391
-
392
- it('buildPromptSpec excludes async subagent guidance in lite mode', () => {
393
- const spec = buildPromptSpec({
394
- model: 'gpt-4o',
395
- profile: profile('builtin:lite'),
396
- runSubagentAsyncEnabled: true,
397
- });
398
- expect(spec.inlineSections.some((s) => s.includes('Asynchronous subagents'))).toBe(false);
399
- });
400
-
401
- it('buildPromptSpec excludes async subagent guidance when disabled', () => {
402
- const spec = buildPromptSpec({
403
- model: 'gpt-4o',
404
- profile: profile('builtin:standard'),
405
- runSubagentAsyncEnabled: false,
406
- });
407
- expect(spec.inlineSections.some((s) => s.includes('Asynchronous subagents'))).toBe(false);
408
- });
409
-
410
- it('background shell addendum teaches explicit finite timeouts for long-lived work', () => {
411
- const spec = buildPromptSpec({
412
- model: 'gpt-4o',
413
- profile: profile('builtin:standard'),
414
- backgroundShellEnabled: true,
415
- });
416
- const guidance = spec.inlineSections.join('\n');
417
-
418
- expect(guidance).toContain('must pass an explicit finite `timeout_ms`');
419
- expect(guidance).toContain('two hours for a watcher');
420
- expect(guidance).toContain('15 minutes for a full-suite gate');
421
- expect(guidance).toContain('never detach a job with nohup to escape the registry');
422
- expect(guidance).toContain('Attach `monitor` in the same launch call');
423
- });
@@ -1,22 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { it, expect } from 'vitest';
4
- import { PROMPT_PROFILES, selectPromptProfile } from './prompt-profiles.js';
5
-
6
- const PROMPTS_DIR = import.meta.dirname;
7
-
8
- it('every prompt profile points at base and fragment files that exist on disk', () => {
9
- const missing = PROMPT_PROFILES.flatMap((profile) =>
10
- [profile.basePromptFile, ...(profile.fragmentFiles ?? [])]
11
- .filter((file) => !fs.existsSync(path.join(PROMPTS_DIR, file)))
12
- .map((file) => `${profile.id} -> ${file}`),
13
- );
14
-
15
- expect(missing).toEqual([]);
16
- });
17
-
18
- it('selectPromptProfile resolves a profile for any model string', () => {
19
- for (const model of ['gpt-5.6', 'gpt-5.5', 'claude-opus-5', 'kimi-k2.5', 'some-unknown-model', '']) {
20
- expect(selectPromptProfile({ model, liteMode: false }).basePromptFile).toBeTruthy();
21
- }
22
- });
@@ -1,12 +0,0 @@
1
- import { it, expect } from 'vitest';
2
- import { getReasoningEfficiencyAddendum } from './reasoning-efficiency.js';
3
-
4
- it('getReasoningEfficiencyAddendum returns a non-empty string with guidance keywords', () => {
5
- const addendum = getReasoningEfficiencyAddendum();
6
-
7
- expect(typeof addendum).toBe('string');
8
- expect(addendum.length > 0).toBe(true);
9
- expect(addendum.includes('### Reasoning Efficiency Guidelines')).toBe(true);
10
- expect(addendum.includes('Treat confirmed context as settled')).toBe(true);
11
- expect(addendum.includes('End when done')).toBe(true);
12
- });
@@ -1,69 +0,0 @@
1
- import { it, expect } from 'vitest';
2
- import { getSearchViaShellAddendum } from './search-via-shell.js';
3
-
4
- function includesWord(text: string, word: string): boolean {
5
- return new RegExp(`\\b${word}\\b`, 'i').test(text);
6
- }
7
-
8
- it('getSearchViaShellAddendum recommends rg and fd when both available', () => {
9
- const result = getSearchViaShellAddendum({
10
- checkBinary: () => true,
11
- });
12
-
13
- expect(includesWord(result, 'rg')).toBe(true);
14
- expect(includesWord(result, 'fd')).toBe(true);
15
- expect(includesWord(result, 'grep')).toBe(false);
16
- expect(includesWord(result, 'find')).toBe(false);
17
- expect(result.toLowerCase().includes('hygiene')).toBe(true);
18
- });
19
-
20
- it('getSearchViaShellAddendum falls back to grep when rg is missing', () => {
21
- const result = getSearchViaShellAddendum({
22
- checkBinary: (cmd) => cmd === 'fd',
23
- });
24
-
25
- expect(includesWord(result, 'rg')).toBe(false);
26
- expect(includesWord(result, 'grep')).toBe(true);
27
- expect(includesWord(result, 'fd')).toBe(true);
28
- expect(includesWord(result, 'find')).toBe(false);
29
- });
30
-
31
- it('getSearchViaShellAddendum falls back to find when fd is missing', () => {
32
- const result = getSearchViaShellAddendum({
33
- checkBinary: (cmd) => cmd === 'rg',
34
- });
35
-
36
- expect(includesWord(result, 'rg')).toBe(true);
37
- expect(includesWord(result, 'fd')).toBe(false);
38
- expect(includesWord(result, 'find')).toBe(true);
39
- });
40
-
41
- it('getSearchViaShellAddendum falls back to grep and find when both missing', () => {
42
- const result = getSearchViaShellAddendum({
43
- checkBinary: () => false,
44
- });
45
-
46
- expect(includesWord(result, 'rg')).toBe(false);
47
- expect(includesWord(result, 'grep')).toBe(true);
48
- expect(includesWord(result, 'fd')).toBe(false);
49
- expect(includesWord(result, 'find')).toBe(true);
50
- expect(result.toLowerCase().includes('hygiene')).toBe(true);
51
- });
52
-
53
- it('getSearchViaShellAddendum warns that pathless rg reads stdin', () => {
54
- const result = getSearchViaShellAddendum({
55
- checkBinary: () => true,
56
- });
57
-
58
- expect(result.toLowerCase()).toContain('explicit path');
59
- expect(result.toLowerCase()).toContain('stdin');
60
- });
61
-
62
- it('getSearchViaShellAddendum warns about find -regex alternation ordering', () => {
63
- const result = getSearchViaShellAddendum({
64
- checkBinary: () => false,
65
- });
66
-
67
- expect(result).toContain('-regex');
68
- expect(result.toLowerCase()).toContain('longest alternative first');
69
- });
@@ -1,36 +0,0 @@
1
- import { expect, it } from 'vitest';
2
- import { stripSteeringNotice, withSteeringNotice } from './steering-notice.js';
3
-
4
- it('steering distinguishes side questions, added constraints, replacement, and queued tasks', () => {
5
- const text = withSteeringNotice('How far along are you?');
6
- expect(text).toContain('before your next tool call');
7
- expect(text).toContain('continue the pending work in the same response');
8
- expect(text).toContain('Incorporate corrections and new constraints');
9
- expect(text).toContain('pauses, cancels, or replaces');
10
- expect(text).toContain('unrelated task');
11
- expect(text).toContain('How far along are you?');
12
- });
13
-
14
- it.each(['How far along are you?', 'Keep the API compatible.\nAlso update the docs.', 'Stop.'])(
15
- 'steering round-trips user text: %s',
16
- (text) => expect(stripSteeringNotice(withSteeringNotice(text))).toBe(text),
17
- );
18
-
19
- it('still strips the original notice from saved conversation messages', () => {
20
- const legacy = `[Steering message: the user sent this while you were working, so it arrives mid-turn rather than as a new turn.
21
- - If it changes what you should be doing, change direction now and drop the superseded plan.
22
- - If it does not bear on the work in progress, treat it as the next task rather than an interruption: acknowledge it, finish what you are doing, and handle it after.]`;
23
- expect(stripSteeringNotice(`${legacy}\n\nKeep the API compatible.`)).toBe('Keep the API compatible.');
24
- });
25
-
26
- it('leaves ordinary user messages unchanged', () => {
27
- expect(stripSteeringNotice('No steering notice here.')).toBe('No steering notice here.');
28
- });
29
-
30
- it('strips the previous status-aware notice from saved conversation messages', () => {
31
- const previous = `[Steering message: the user sent this while you were working, so it arrives mid-turn rather than as a new turn.
32
- - For status or side questions, answer briefly, then resume the active task.
33
- - Incorporate corrections and new constraints while preserving the active objective, unless the user explicitly pauses, cancels, or replaces it. Drop only superseded work.
34
- - For an unrelated task, acknowledge it, finish the active task, then handle it unless the user explicitly changes priority.]`;
35
- expect(stripSteeringNotice(`${previous}\n\nWhat is done so far?`)).toBe('What is done so far?');
36
- });