@sema-agent/core 7.55.0 → 7.56.0

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 (418) hide show
  1. package/CHANGELOG.md +513 -0
  2. package/dist/agents/cascade.js +1 -1
  3. package/dist/agents/cc-peer-directory.js +1 -0
  4. package/dist/agents/child-model-seat.d.ts +0 -11
  5. package/dist/agents/child-model-seat.js +0 -3
  6. package/dist/agents/list-agents-tool.d.ts +3 -1
  7. package/dist/agents/list-agents-tool.js +7 -7
  8. package/dist/agents/peer-directory.d.ts +22 -4
  9. package/dist/agents/peer-directory.js +24 -2
  10. package/dist/agents/peer-session-drain.js +2 -2
  11. package/dist/agents/repair-loop.js +2 -2
  12. package/dist/agents/send-message-tool.js +4 -4
  13. package/dist/agents/subagent.d.ts +6 -4
  14. package/dist/agents/subagent.js +64 -60
  15. package/dist/agents/tool-filter.d.ts +7 -5
  16. package/dist/agents/tool-filter.js +12 -9
  17. package/dist/agents/verify.d.ts +3 -2
  18. package/dist/agents/verify.js +3 -3
  19. package/dist/brain/anthropic.js +30 -73
  20. package/dist/brain/media-degrade.d.ts +18 -7
  21. package/dist/brain/media-degrade.js +13 -2
  22. package/dist/brain/model-capability.d.ts +37 -0
  23. package/dist/brain/model-capability.js +34 -0
  24. package/dist/brain/model-presets.d.ts +2 -8
  25. package/dist/brain/model-presets.js +1 -6
  26. package/dist/brain/open-responses.js +13 -26
  27. package/dist/brain/openai.js +14 -87
  28. package/dist/brain/reasoning-request.d.ts +96 -0
  29. package/dist/brain/reasoning-request.js +174 -0
  30. package/dist/brain/reasoning.d.ts +11 -11
  31. package/dist/brain/reasoning.js +4 -3
  32. package/dist/brain/request-params.d.ts +7 -4
  33. package/dist/brain/request-params.js +7 -4
  34. package/dist/brain/status-sink.d.ts +20 -0
  35. package/dist/brain/status-sink.js +7 -0
  36. package/dist/core/a2a.d.ts +2 -1
  37. package/dist/core/a2a.js +19 -13
  38. package/dist/core/agent-definition.d.ts +10 -0
  39. package/dist/core/allow-entry.d.ts +20 -13
  40. package/dist/core/allow-entry.js +26 -22
  41. package/dist/core/allow-rule-shadow.d.ts +3 -3
  42. package/dist/core/ask-origin.d.ts +64 -18
  43. package/dist/core/ask-origin.js +63 -23
  44. package/dist/core/ask-question.d.ts +51 -8
  45. package/dist/core/ask-question.js +3 -4
  46. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  47. package/dist/core/ask-unresolvable-notice.js +16 -2
  48. package/dist/core/checkpoint-generation.d.ts +53 -0
  49. package/dist/core/checkpoint-generation.js +35 -0
  50. package/dist/core/checkpoint-queries.d.ts +180 -0
  51. package/dist/core/checkpoint-queries.js +272 -0
  52. package/dist/core/checkpoint-requirements.d.ts +13 -1
  53. package/dist/core/checkpoint-requirements.js +4 -0
  54. package/dist/core/checkpoint-store.d.ts +88 -24
  55. package/dist/core/checkpoint-store.js +24 -9
  56. package/dist/core/cross-boundary-taint.d.ts +6 -5
  57. package/dist/core/cross-boundary-taint.js +1 -3
  58. package/dist/core/decision-receipt.d.ts +37 -3
  59. package/dist/core/decision-receipt.js +17 -17
  60. package/dist/core/delegation-not-started.d.ts +6 -0
  61. package/dist/core/delegation-not-started.js +17 -0
  62. package/dist/core/engine-attestation.d.ts +93 -0
  63. package/dist/core/engine-attestation.js +70 -0
  64. package/dist/core/engine-capabilities.d.ts +4 -1
  65. package/dist/core/engine-capabilities.js +1 -1
  66. package/dist/core/engine-notice.d.ts +30 -11
  67. package/dist/core/file-history-store.d.ts +90 -14
  68. package/dist/core/file-history-store.js +23 -15
  69. package/dist/core/gate-fold.d.ts +1 -1
  70. package/dist/core/gate-fold.js +22 -10
  71. package/dist/core/gate-lanes.js +73 -64
  72. package/dist/core/gate-outcome.d.ts +26 -5
  73. package/dist/core/gate-outcome.js +26 -0
  74. package/dist/core/governance-codes.d.ts +5 -1
  75. package/dist/core/governance-codes.js +6 -0
  76. package/dist/core/hooks.d.ts +17 -16
  77. package/dist/core/hooks.js +3 -1
  78. package/dist/core/host-floor.d.ts +128 -0
  79. package/dist/core/host-floor.js +206 -0
  80. package/dist/core/host-target.d.ts +38 -3
  81. package/dist/core/host-target.js +38 -5
  82. package/dist/core/mcp.d.ts +5 -1
  83. package/dist/core/mcp.js +67 -41
  84. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  85. package/dist/core/memory-engine/engine.js +4 -4
  86. package/dist/core/memory-engine/layout.d.ts +60 -8
  87. package/dist/core/memory-engine/layout.js +65 -6
  88. package/dist/core/model-seat.d.ts +10 -3
  89. package/dist/core/mods/classic-events.d.ts +67 -0
  90. package/dist/core/mods/classic-events.js +1 -0
  91. package/dist/core/mods/dollar.d.ts +13 -0
  92. package/dist/core/mods/extension-call.d.ts +31 -0
  93. package/dist/core/mods/extension-call.js +43 -0
  94. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  95. package/dist/core/mods/kernel/dispatch.js +140 -69
  96. package/dist/core/mods/kernel/events.d.ts +47 -11
  97. package/dist/core/mods/kernel/events.js +66 -42
  98. package/dist/core/mods/kernel/index.d.ts +4 -4
  99. package/dist/core/mods/kernel/index.js +2 -2
  100. package/dist/core/mods/kernel/receive.d.ts +39 -5
  101. package/dist/core/mods/kernel/receive.js +290 -17
  102. package/dist/core/mods/kernel/registration.d.ts +33 -2
  103. package/dist/core/mods/kernel/registration.js +6 -7
  104. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  105. package/dist/core/mods/kernel/site-rules.js +24 -42
  106. package/dist/core/mods/spec-seats.d.ts +69 -0
  107. package/dist/core/mods/spec-seats.js +114 -0
  108. package/dist/core/mods/stations.d.ts +28 -8
  109. package/dist/core/mods/stations.js +29 -13
  110. package/dist/core/mods/tool-call.d.ts +79 -0
  111. package/dist/core/mods/tool-call.js +152 -0
  112. package/dist/core/namespaced-rule-name.d.ts +32 -38
  113. package/dist/core/namespaced-rule-name.js +29 -36
  114. package/dist/core/parent-spec-seat.d.ts +6 -1
  115. package/dist/core/parent-spec-seat.js +2 -0
  116. package/dist/core/park-selfcheck.js +1 -0
  117. package/dist/core/permission-rule-consent.d.ts +19 -0
  118. package/dist/core/permission-rule-consent.js +116 -26
  119. package/dist/core/permission-rule-model.d.ts +14 -3
  120. package/dist/core/permission-rule-model.js +39 -24
  121. package/dist/core/permission-rule-org.d.ts +6 -2
  122. package/dist/core/permission-rule-org.js +7 -3
  123. package/dist/core/permission-rule-provider.d.ts +5 -2
  124. package/dist/core/permission-rule-provider.js +41 -11
  125. package/dist/core/permission-rule-store.d.ts +3 -2
  126. package/dist/core/permission-rule-store.js +11 -2
  127. package/dist/core/permission-rule-sync.js +3 -2
  128. package/dist/core/permission-rule-syntax.d.ts +5 -4
  129. package/dist/core/permission-rule-syntax.js +2 -2
  130. package/dist/core/permission-rules.d.ts +4 -4
  131. package/dist/core/permission-rules.js +11 -20
  132. package/dist/core/persisted-rule-arms.d.ts +2 -2
  133. package/dist/core/persisted-rule-arms.js +10 -12
  134. package/dist/core/principal-name.d.ts +20 -0
  135. package/dist/core/principal-name.js +22 -0
  136. package/dist/core/prompt-section-seat.js +4 -6
  137. package/dist/core/protocol-http-auth.d.ts +26 -5
  138. package/dist/core/protocol-http-auth.js +137 -4
  139. package/dist/core/retired-keys.d.ts +16 -0
  140. package/dist/core/retired-keys.js +16 -4
  141. package/dist/core/rewrite-rejudge.d.ts +60 -0
  142. package/dist/core/rewrite-rejudge.js +36 -0
  143. package/dist/core/roles.d.ts +28 -1
  144. package/dist/core/roles.js +31 -19
  145. package/dist/core/rule-lane-reads.d.ts +20 -15
  146. package/dist/core/rule-lane-reads.js +45 -17
  147. package/dist/core/rule-owner.d.ts +3 -3
  148. package/dist/core/rule-owner.js +3 -2
  149. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  150. package/dist/core/runner/announce-once-ledger.js +5 -0
  151. package/dist/core/runner/assemble-result.d.ts +1 -0
  152. package/dist/core/runner/assemble-result.js +1 -1
  153. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  154. package/dist/core/runner/caller-roster.d.ts +16 -4
  155. package/dist/core/runner/caller-roster.js +33 -6
  156. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  157. package/dist/core/runner/capability-withheld-seat.js +24 -0
  158. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  159. package/dist/core/runner/classifier-ladder.js +3 -3
  160. package/dist/core/runner/construction-doors.js +3 -0
  161. package/dist/core/runner/contracts.d.ts +28 -25
  162. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  163. package/dist/core/runner/cross-boundary-lane.js +40 -27
  164. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  165. package/dist/core/runner/denial-limit-arms.js +1 -1
  166. package/dist/core/runner/file-history-request.d.ts +18 -0
  167. package/dist/core/runner/file-history-request.js +21 -13
  168. package/dist/core/runner/file-history-restore.d.ts +45 -0
  169. package/dist/core/runner/file-history-restore.js +46 -0
  170. package/dist/core/runner/gate-exit.d.ts +3 -3
  171. package/dist/core/runner/gate-exit.js +4 -3
  172. package/dist/core/runner/image.d.ts +7 -17
  173. package/dist/core/runner/image.js +9 -60
  174. package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
  175. package/dist/core/runner/permission-rule-lanes.js +26 -10
  176. package/dist/core/runner/person-path-rows.d.ts +12 -9
  177. package/dist/core/runner/person-path-rows.js +18 -7
  178. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  179. package/dist/core/runner/prepare-ask-lane.js +5 -2
  180. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  181. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  182. package/dist/core/runner/prepare-config-doors.d.ts +29 -38
  183. package/dist/core/runner/prepare-config-doors.js +42 -25
  184. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  185. package/dist/core/runner/prepare-defer-classify.js +7 -8
  186. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  187. package/dist/core/runner/prepare-file-history.js +7 -39
  188. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  189. package/dist/core/runner/prepare-gate-stations.js +10 -1
  190. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  191. package/dist/core/runner/prepare-hands-readface.js +15 -14
  192. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  193. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  194. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  195. package/dist/core/runner/prepare-park-ask.js +5 -5
  196. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  197. package/dist/core/runner/prepare-policy-chain.js +65 -72
  198. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  199. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  200. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  201. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  204. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  205. package/dist/core/runner/prepare-safety-scan.js +0 -17
  206. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  207. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  208. package/dist/core/runner/prepare-task.d.ts +1 -1
  209. package/dist/core/runner/prepare-task.js +29 -20
  210. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  211. package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
  212. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  213. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  214. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  215. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  216. package/dist/core/runner/resume-admission.js +1 -1
  217. package/dist/core/runner/resume-apply.js +11 -12
  218. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  219. package/dist/core/runner/resume-claim.d.ts +4 -2
  220. package/dist/core/runner/resume-claim.js +15 -8
  221. package/dist/core/runner/retired-runner-deps.js +1 -0
  222. package/dist/core/runner/rewind-files.d.ts +15 -0
  223. package/dist/core/runner/rewind-files.js +132 -0
  224. package/dist/core/runner/run-attachment-seats.js +2 -1
  225. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  226. package/dist/core/runner/run-brain-sinks.js +4 -2
  227. package/dist/core/runner/run-harness-handlers.js +12 -4
  228. package/dist/core/runner/run-leg.d.ts +1 -1
  229. package/dist/core/runner/run-leg.js +30 -18
  230. package/dist/core/runner/run-settle-and-teardown.js +2 -1
  231. package/dist/core/runner/run-turn-boundary.js +1 -10
  232. package/dist/core/runner/runtask.d.ts +3 -0
  233. package/dist/core/runner/runtask.js +8 -9
  234. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  235. package/dist/core/runner/session-read-file-states.js +28 -0
  236. package/dist/core/runner/session-rule-policy.js +4 -3
  237. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  238. package/dist/core/runner/shell-env-withheld.js +51 -0
  239. package/dist/core/runner/skills-seat.js +6 -2
  240. package/dist/core/runner/stream-settle-backstop.js +1 -1
  241. package/dist/core/runner/sub-agent-deny-lists.js +4 -7
  242. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  243. package/dist/core/runner/synthetic-tools.js +4 -1
  244. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  245. package/dist/core/runner/tool-disclosure.js +1 -3
  246. package/dist/core/runner/tool-end-body.d.ts +1 -1
  247. package/dist/core/runner/tool-end-body.js +10 -9
  248. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  249. package/dist/core/runner/tool-not-executed.js +11 -0
  250. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  251. package/dist/core/runner/tool-occurrence.js +7 -0
  252. package/dist/core/runner/turn-attachments.d.ts +33 -15
  253. package/dist/core/runner/turn-attachments.js +62 -37
  254. package/dist/core/runner-deps.d.ts +5 -5
  255. package/dist/core/safety-axis-vocab.d.ts +6 -4
  256. package/dist/core/safety-axis-vocab.js +6 -5
  257. package/dist/core/safety-merge-corpus.js +11 -3
  258. package/dist/core/secret-env.d.ts +26 -3
  259. package/dist/core/secret-env.js +44 -8
  260. package/dist/core/select-model.js +3 -3
  261. package/dist/core/session-policy-store.d.ts +27 -15
  262. package/dist/core/session-policy-store.js +156 -36
  263. package/dist/core/session-store.d.ts +29 -10
  264. package/dist/core/session-store.js +51 -19
  265. package/dist/core/session.d.ts +82 -16
  266. package/dist/core/session.js +53 -0
  267. package/dist/core/shell-read-silence.d.ts +11 -12
  268. package/dist/core/shell-read-silence.js +9 -5
  269. package/dist/core/shell-run-candidates.js +3 -1
  270. package/dist/core/shell-wrapper-projection.js +1 -1
  271. package/dist/core/shell-wrapper-table.d.ts +14 -7
  272. package/dist/core/shell-wrapper-table.js +5 -4
  273. package/dist/core/side-query.js +10 -1
  274. package/dist/core/skill-grant.d.ts +7 -2
  275. package/dist/core/skill-grant.js +5 -0
  276. package/dist/core/skills-directory.js +6 -2
  277. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  278. package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
  279. package/dist/core/store-contracts/file-history-store-contract.js +31 -1
  280. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  281. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  282. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  283. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  284. package/dist/core/store-contracts/session-store-contract.js +150 -14
  285. package/dist/core/stub-env.d.ts +2 -0
  286. package/dist/core/stub-env.js +1 -0
  287. package/dist/core/synthetic-read-verdict.js +3 -3
  288. package/dist/core/task-event.d.ts +32 -4
  289. package/dist/core/task-notification.d.ts +16 -12
  290. package/dist/core/task-registry.d.ts +9 -0
  291. package/dist/core/task-registry.js +11 -1
  292. package/dist/core/task-result.d.ts +18 -0
  293. package/dist/core/task-spec.d.ts +18 -13
  294. package/dist/core/tighten-task-spec.js +2 -1
  295. package/dist/core/tool-catalog-entries.d.ts +17 -0
  296. package/dist/core/tool-catalog-entries.js +13 -2
  297. package/dist/core/tool-check-reading.d.ts +11 -0
  298. package/dist/core/tool-check-reading.js +11 -6
  299. package/dist/core/tool-model-gate.d.ts +2 -2
  300. package/dist/core/tool-name-aliases.d.ts +16 -16
  301. package/dist/core/tool-name-aliases.js +13 -19
  302. package/dist/core/tool-name-readings.d.ts +5 -35
  303. package/dist/core/tool-name-readings.js +1 -9
  304. package/dist/core/tool-policy.d.ts +68 -198
  305. package/dist/core/tool-policy.js +149 -198
  306. package/dist/core/tool-result-store.js +3 -0
  307. package/dist/core/tool-roster.d.ts +14 -19
  308. package/dist/core/tool-roster.js +11 -44
  309. package/dist/core/tool-spec-members.js +7 -2
  310. package/dist/core/tool-spec.d.ts +19 -11
  311. package/dist/core/tools.js +49 -9
  312. package/dist/core/trace.d.ts +2 -2
  313. package/dist/core/types.d.ts +1 -1
  314. package/dist/core/user-attachment.d.ts +8 -1
  315. package/dist/core/user-attachment.js +64 -4
  316. package/dist/core/wiring-manifest.d.ts +9 -0
  317. package/dist/core/wiring-manifest.js +1 -0
  318. package/dist/core/workflow-journal-store.js +1 -1
  319. package/dist/engine/compaction/compaction.js +3 -2
  320. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  321. package/dist/engine/execution-env/node-execution-env.js +11 -2
  322. package/dist/engine/harness/agent-harness.d.ts +25 -1
  323. package/dist/engine/harness/agent-harness.js +54 -7
  324. package/dist/engine/harness/types.d.ts +29 -2
  325. package/dist/engine/llm/types.d.ts +28 -11
  326. package/dist/engine/loop/agent-loop.d.ts +22 -0
  327. package/dist/engine/loop/agent-loop.js +16 -26
  328. package/dist/engine/loop/types.d.ts +16 -6
  329. package/dist/engine/session/memory-repo.d.ts +9 -2
  330. package/dist/engine/session/memory-repo.js +11 -1
  331. package/dist/engine/session/repo-utils.d.ts +6 -5
  332. package/dist/engine/session/repo-utils.js +14 -6
  333. package/dist/index.d.ts +22 -10
  334. package/dist/index.js +15 -7
  335. package/dist/internal/harness-types.d.ts +1 -1
  336. package/dist/internal/llm.d.ts +1 -1
  337. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  338. package/dist/orchestration/run-workflow-tool.js +5 -3
  339. package/dist/orchestration/workflow.d.ts +3 -0
  340. package/dist/orchestration/workflow.js +36 -18
  341. package/dist/prompt-assembly/artifact.d.ts +2 -2
  342. package/dist/prompt-assembly/artifact.js +5 -3
  343. package/dist/prompt-assembly/assemble.d.ts +3 -2
  344. package/dist/prompt-assembly/assemble.js +1 -1
  345. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  346. package/dist/prompt-assembly/catalog/schema.js +34 -2
  347. package/dist/prompt-assembly/catalog/sections.js +0 -1
  348. package/dist/prompt-assembly/composer.d.ts +3 -1
  349. package/dist/prompt-assembly/composer.js +1 -1
  350. package/dist/prompt-assembly/event-registry.js +1 -0
  351. package/dist/prompt-assembly/overlay.js +3 -3
  352. package/dist/prompt-assembly/renderers.d.ts +1 -1
  353. package/dist/prompt-assembly/renderers.js +0 -3
  354. package/dist/prompt-assembly/role-base.d.ts +15 -0
  355. package/dist/prompt-assembly/role-base.js +9 -0
  356. package/dist/prompt-assembly/select.d.ts +39 -14
  357. package/dist/prompt-assembly/select.js +47 -16
  358. package/dist/prompt-assembly/sugar.d.ts +17 -11
  359. package/dist/prompt-assembly/sugar.js +8 -3
  360. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  361. package/dist/prompt-assembly/tool-catalog.js +114 -4
  362. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  363. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  364. package/dist/prompt-assembly/types.d.ts +0 -7
  365. package/dist/scenarios/full-body.d.ts +11 -11
  366. package/dist/scenarios/full-body.js +4 -3
  367. package/dist/shell/lex.js +10 -1
  368. package/dist/stores/file/adoption/adopt.js +4 -3
  369. package/dist/stores/file/adoption/marker.js +3 -2
  370. package/dist/stores/file/checkpoint-store.d.ts +21 -0
  371. package/dist/stores/file/checkpoint-store.js +38 -6
  372. package/dist/stores/file/file-history-store.js +6 -7
  373. package/dist/stores/file/index.js +2 -1
  374. package/dist/stores/file/permission-rule-adopt.js +4 -3
  375. package/dist/stores/file/permission-rule-store.js +11 -5
  376. package/dist/stores/file/session-store.d.ts +29 -6
  377. package/dist/stores/file/session-store.js +42 -50
  378. package/dist/tools/artifact/artifact-tool.js +3 -2
  379. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  380. package/dist/tools/fs/bash-program-position.js +56 -9
  381. package/dist/tools/fs/fs-bash.js +5 -5
  382. package/dist/tools/fs/fs-glob.d.ts +86 -0
  383. package/dist/tools/fs/fs-glob.js +226 -0
  384. package/dist/tools/fs/fs-read.js +14 -14
  385. package/dist/tools/fs/fs-search-tools.js +7 -7
  386. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  387. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  388. package/dist/tools/fs/pdf.d.ts +9 -6
  389. package/dist/tools/fs/pdf.js +3 -3
  390. package/dist/tools/fs/program-read-model.d.ts +57 -7
  391. package/dist/tools/fs/program-read-model.js +11 -1
  392. package/dist/tools/fs/program-read-model.rows.js +78 -21
  393. package/dist/tools/fs/read-deny-home.js +3 -2
  394. package/dist/tools/fs/removal-targets.d.ts +17 -7
  395. package/dist/tools/fs/removal-targets.js +47 -20
  396. package/dist/tools/fs/search.d.ts +10 -0
  397. package/dist/tools/fs/search.js +20 -26
  398. package/dist/tools/fs/shell-read-argv.js +89 -12
  399. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  400. package/dist/tools/fs/shell-read-bindings.js +41 -0
  401. package/dist/tools/fs/shell-read-check.js +6 -19
  402. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  403. package/dist/tools/fs/shell-read-environment.js +3 -2
  404. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  405. package/dist/tools/fs/shell-read-establish.js +19 -20
  406. package/dist/tools/fs/shell-read-plan.js +24 -16
  407. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  408. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  409. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  410. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  411. package/dist/tools/fs/shell-reentry-text.js +40 -2
  412. package/dist/tools/todo.js +63 -63
  413. package/dist/tools/web.d.ts +19 -14
  414. package/dist/tools/web.js +38 -55
  415. package/package.json +1 -1
  416. package/test/export-surface.snapshot.json +143 -5
  417. package/wire-changes/core@7.56.0.json +3891 -0
  418. package/wire-changes/mods-kernel@7.56.0.json +303 -0
@@ -7,6 +7,7 @@ import { budgetInvokedSkillsRetention, computeFileLists, createFileOps, extractF
7
7
  import { ENGINE_AUTHORITY_ENVELOPE_TAGS, sanitizeUntrustedText } from "../../core/untrusted-text.js";
8
8
  import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
9
9
  import { thrownText } from "../../core/thrown-value.js";
10
+ import { capabilityHeld } from "../../brain/model-capability.js";
10
11
  function safeJsonStringify(value) {
11
12
  try {
12
13
  return JSON.stringify(value) ?? "undefined";
@@ -576,7 +577,7 @@ First, inside an <analysis>...</analysis> block, note what is new since the prev
576
577
  Keep each section concise. Preserve exact file paths, function names, and error messages.`;
577
578
  function createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel) {
578
579
  const options = { maxTokens, signal, apiKey, headers };
579
- if (model.reasoning && thinkingLevel) {
580
+ if (capabilityHeld(model, "reasoning") && thinkingLevel) {
580
581
  options.reasoning = thinkingLevel;
581
582
  }
582
583
  return options;
@@ -868,7 +869,7 @@ async function summarizeWithLengthRecovery(label, model, context, baseMaxTokens,
868
869
  ? Math.max(baseMaxTokens, model.contextWindow - estimateSummarizationInputTokens(context, cpt) - SUMMARY_WINDOW_MARGIN)
869
870
  : Number.POSITIVE_INFINITY;
870
871
  const cap = Math.min(modelCap, windowCap);
871
- let maxTokens = Math.min(cap, model.reasoning ? Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR) : baseMaxTokens);
872
+ let maxTokens = Math.min(cap, capabilityHeld(model, "reasoning") ? Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR) : baseMaxTokens);
872
873
  for (let attempt = 0;; attempt++) {
873
874
  const canEscalate = attempt < SUMMARY_MAX_ESCALATIONS && maxTokens < cap;
874
875
  const response = await completeSummarization(model, context, createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel), streamFn, runtime);
@@ -88,9 +88,13 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
88
88
  /** `ExecutionEnv.cdPath` = the `CDPATH` the shell child receives, read LIVE off the same merge each exec gets (never the
89
89
  * engine process's own environment): its entries, `[]` when the child gets none. Residual: a per-exec `env.CDPATH`. */
90
90
  get cdPath(): readonly string[];
91
- /** The environment the next shell child would receive, for a READ (the scrub seat is a no-op: a read reports nothing).
92
- * `undefined` when no child would be spawned at all — the policy is refused against the own credentials declared
93
- * since construction, and every spawn throws that reason — so a reader sees "the child gets none", never a throw. */
91
+ /** `ExecutionEnv.withheldEnv` = what the same merge withholds from the shell child (an entry `shellEnv` re-supplies is
92
+ * no loss), read LIVE; `[]` when no child would be spawned at all. Residual: a per-exec `env` re-supplying one. */
93
+ get withheldEnv(): readonly SecretEnvFinding[];
94
+ /** The environment the next shell child would receive, for a READ (the scrub seat is the reader's collector or a
95
+ * no-op: a read announces nothing). `undefined` when no child would be spawned at all — the policy is refused against
96
+ * the own credentials declared since construction, and every spawn throws that reason — so a reader sees "the child
97
+ * gets none", never a throw. */
94
98
  private childEnvForRead;
95
99
  private shellPath?;
96
100
  private shellEnv?;
@@ -116,6 +116,10 @@ function toFileError(error, path) {
116
116
  return new FileError("not_directory", message, path, cause);
117
117
  case "EISDIR":
118
118
  return new FileError("is_directory", message, path, cause);
119
+ case "ENAMETOOLONG":
120
+ if (path !== undefined && path.split(/[\\/]/).some((part) => Buffer.byteLength(part, "utf8") > 255))
121
+ return new FileError("name_too_long", message, path, cause);
122
+ break;
119
123
  case "EINVAL":
120
124
  return new FileError("invalid", message, path, cause);
121
125
  default:
@@ -321,10 +325,15 @@ export class NodeExecutionEnv {
321
325
  const value = this.childEnvForRead()?.CDPATH;
322
326
  return value === undefined || value === "" ? [] : value.split(":");
323
327
  }
324
- childEnvForRead() {
328
+ get withheldEnv() {
329
+ let withheld = [];
330
+ this.childEnvForRead((f) => (withheld = f));
331
+ return withheld;
332
+ }
333
+ childEnvForRead(collect = () => { }) {
325
334
  if (inheritEnvPolicyProblem(this.inheritEnv) !== undefined)
326
335
  return undefined;
327
- return getShellEnv(this.inheritEnv, this.shellEnv, undefined, () => { });
336
+ return getShellEnv(this.inheritEnv, this.shellEnv, undefined, collect);
328
337
  }
329
338
  shellPath;
330
339
  shellEnv;
@@ -1,6 +1,6 @@
1
1
  import type { ActorAssertion, AssistantMessage, ImageContent, Model, TextContent, UserMessage, UserMessageAttachment } from "../llm/index.js";
2
2
  import { type ToolTurnRepair } from "../llm/index.js";
3
- import { type ExecutedToolCallOutcome } from "../loop/agent-loop.js";
3
+ import { runToolCall, type ExecutedToolCallOutcome } from "../loop/agent-loop.js";
4
4
  import type { HaltRemainingDirective } from "../loop/types.js";
5
5
  import type { AgentMessage, AgentTool, AgentToolCall, LoopMalformedToolUseRecovery, LoopThinkingOnlyRecovery, LoopTruncatedOutputRecovery, QueueMode, ThinkingLevel } from "../loop/types.js";
6
6
  import { type EngineSegment } from "../../core/untrusted-text.js";
@@ -174,6 +174,8 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
174
174
  private readonly seatCutSources;
175
175
  private trailingBatchEndedOn?;
176
176
  private turnCutConsumed?;
177
+ private readonly committedEntryIds;
178
+ private readonly answerSources;
177
179
  /** backlog #389 — one-way latch set by {@link abort}. Read by `drainQueuedMessages`: no boundary may
178
180
  * hand a queued frame to the model once the run is unwinding, and — crucially — none may SPLICE one
179
181
  * out of the queue either (that would delete the terminal undrained account the abort path owes it). */
@@ -308,6 +310,8 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
308
310
  private maxOutputTokensPerCall?;
309
311
  private stallTimeoutsPerCall?;
310
312
  private abortResultDetails?;
313
+ private executeTool?;
314
+ private activeRun?;
311
315
  private loopTrace?;
312
316
  private onToolInputValidationFault?;
313
317
  private onToolMediaRefused?;
@@ -509,6 +513,15 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
509
513
  * the loop takes the run-terminal path and never reports that settlement, so the consumption is recorded here, the
510
514
  * only point that can see the causation (synchronous, single-threaded). A LATER abort is the run's own ending. */
511
515
  private cutSeat;
516
+ /** The entry ids of the committed messages an answer `prompt()` returned was read from, in conversation order: the
517
+ * final assistant message, or every member of the continuation chain merged into it (members never appended — an
518
+ * empty failure — have no id). Bound to the returned object, so a prompt that rejects, or one overlapping another,
519
+ * hands its caller nothing to misread. Empty for `undefined` (no answer, read from nothing); `undefined` when the
520
+ * sources are not this harness's to state — an object it did not return, or an answer read from a message the
521
+ * transcript held before the run began whose append this harness never saw. */
522
+ answerEntryIdsOf(answer: AssistantMessage | undefined): readonly string[] | undefined;
523
+ /** Record what an answer was read from (the append receipts of its source messages) and hand the answer back. */
524
+ private answeredFrom;
512
525
  /** The harness's statement of what this run's halt (and its stop siblings) did — {@link HaltConsumption}. Readable
513
526
  * during the run and after `prompt()` settled (cleared by the NEXT prompt). */
514
527
  haltConsumption(): HaltConsumption;
@@ -550,6 +563,17 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
550
563
  finalizeToolCall(toolCall: AgentToolCall, args: unknown, executed: ExecutedToolCallOutcome): Promise<ExecutedToolCallOutcome & {
551
564
  toolCall: AgentToolCall;
552
565
  }>;
566
+ /**
567
+ * A call the host makes while a run is running (an extension's `$.tool.call`): the loop's own per-call pipeline
568
+ * ({@link runToolCall}) under the run's config and current roster — announced, judged at the gate, executed through the
569
+ * execution seat, finalized and closed on the run's event stream — with no model message carrying it and nothing added
570
+ * to the transcript. `admit` reads the tool the name resolves to before anything is announced; its throw is the caller's.
571
+ * Throws when no run is running or the run mounts no tool of that name.
572
+ */
573
+ callTool(toolCall: AgentToolCall, signal: AbortSignal | undefined, admit: (tool: AgentTool) => void): Promise<Awaited<ReturnType<typeof runToolCall>>["finalized"]>;
574
+ /** Whether the loop would run this call beside others (`isBatchSafeToolCall`, the partitioner's own predicate) on the running
575
+ * prompt's roster — false for a name it does not mount, and when no prompt is running. */
576
+ isBatchSafe(toolName: string, args: unknown): boolean;
553
577
  getModel(): Model;
554
578
  /** The ref that chose the CURRENT model — {@link getModel}'s companion (a word re-resolves, an object pins). */
555
579
  getModelRef(): import("../../core/model-seat.js").ModelRef;
@@ -1,5 +1,5 @@
1
- import { createAssistantMessageEventStream, ensureToolTurnInvariants, snapshotActorAssertion, stripEngineMetadata, userAttachmentOf } from "../llm/index.js";
2
- import { finalizeToolOutcome, runAgentLoop } from "../loop/agent-loop.js";
1
+ import { createAssistantMessageEventStream, ensureToolTurnInvariants, findToolByName, snapshotActorAssertion, stripEngineMetadata, userAttachmentOf } from "../llm/index.js";
2
+ import { finalizeToolOutcome, isBatchSafeToolCall, runAgentLoop, runToolCall } from "../loop/agent-loop.js";
3
3
  import { resolveAgentCoreStreamFn } from "../loop/runtime-deps.js";
4
4
  import { normalizeEngineSegments } from "../../core/untrusted-text.js";
5
5
  import { isCredentialHeaderName } from "../../core/secret-env.js";
@@ -208,6 +208,8 @@ export class AgentHarness {
208
208
  seatCutSources = new WeakMap();
209
209
  trailingBatchEndedOn;
210
210
  turnCutConsumed;
211
+ committedEntryIds = new WeakMap();
212
+ answerSources = new WeakMap();
211
213
  aborting = false;
212
214
  drainedPendingInjection = [];
213
215
  runAbortController;
@@ -295,6 +297,8 @@ export class AgentHarness {
295
297
  maxOutputTokensPerCall;
296
298
  stallTimeoutsPerCall;
297
299
  abortResultDetails;
300
+ executeTool;
301
+ activeRun;
298
302
  loopTrace;
299
303
  onToolInputValidationFault;
300
304
  onToolMediaRefused;
@@ -331,6 +335,7 @@ export class AgentHarness {
331
335
  this.maxOutputTokensPerCall = options.maxOutputTokensPerCall;
332
336
  this.stallTimeoutsPerCall = options.stallTimeoutsPerCall;
333
337
  this.abortResultDetails = options.abortResultDetails;
338
+ this.executeTool = options.executeTool;
334
339
  this.loopTrace = options.loopTrace;
335
340
  this.onToolInputValidationFault = options.onToolInputValidationFault;
336
341
  this.onToolMediaRefused = options.onToolMediaRefused;
@@ -650,6 +655,7 @@ export class AgentHarness {
650
655
  ...(this.maxOutputTokensPerCall !== undefined ? { maxTokensPerCall: this.maxOutputTokensPerCall } : {}),
651
656
  ...(this.stallTimeoutsPerCall !== undefined ? { stallTimeoutsPerCall: this.stallTimeoutsPerCall } : {}),
652
657
  ...(this.abortResultDetails !== undefined ? { abortResultDetails: this.abortResultDetails } : {}),
658
+ ...(this.executeTool !== undefined ? { executeTool: this.executeTool } : {}),
653
659
  ...(this.onToolInputValidationFault !== undefined ? { onToolInputValidationFault: this.onToolInputValidationFault } : {}),
654
660
  ...(this.onToolMediaRefused !== undefined ? { onToolMediaRefused: this.onToolMediaRefused } : {}),
655
661
  ...(this.resilience !== undefined ? { resilience: this.resilience } : {}),
@@ -834,6 +840,7 @@ export class AgentHarness {
834
840
  let entryId;
835
841
  if (!isEmptyFailureAssistant(event.message)) {
836
842
  entryId = await this.session.appendMessage(event.message);
843
+ this.committedEntryIds.set(event.message, entryId);
837
844
  this.settleInjectedFrame(event.message, entryId);
838
845
  if (entryId !== undefined && event.message.role === "toolResult" && typeof event.message.toolCallId === "string") {
839
846
  try {
@@ -943,9 +950,12 @@ export class AgentHarness {
943
950
  const setTurnState = (nextTurnState) => {
944
951
  activeTurnState = nextTurnState;
945
952
  };
953
+ const loopConfig = this.createLoopConfig(getTurnState, setTurnState, beforeResult?.systemPrompt);
954
+ const emitRunEvent = (event) => this.handleAgentEvent(event, abortController.signal);
955
+ this.activeRun = { config: loopConfig, context: () => this.createContext(getTurnState(), beforeResult?.systemPrompt), emit: emitRunEvent, signal: abortController.signal };
946
956
  const runResultPromise = (async () => {
947
957
  try {
948
- return await runAgentLoop(takePrompts, this.createContext(turnState, beforeResult?.systemPrompt), this.createLoopConfig(getTurnState, setTurnState, beforeResult?.systemPrompt), (event) => this.handleAgentEvent(event, abortController.signal), abortController.signal, this.createStreamFn(getTurnState), undefined, this.loopTrace, {
958
+ return await runAgentLoop(takePrompts, this.createContext(turnState, beforeResult?.systemPrompt), loopConfig, emitRunEvent, abortController.signal, this.createStreamFn(getTurnState), undefined, this.loopTrace, {
949
959
  ...(options?.settleUnansweredToolCalls !== undefined
950
960
  ? {
951
961
  settle: {
@@ -975,13 +985,14 @@ export class AgentHarness {
975
985
  for (let i = newMessages.length - 1; i >= 0; i--) {
976
986
  const message = newMessages[i];
977
987
  if (message.role === "assistant") {
978
- return mergeTruncatedOutputChain(newMessages, i);
988
+ const answer = mergeTruncatedOutputChain(newMessages, i);
989
+ return this.answeredFrom(answer.message, answer.members);
979
990
  }
980
991
  }
981
992
  if (this.stopRequested || abortController.signal.aborted)
982
993
  return undefined;
983
994
  if (this.trailingBatchEndedOn !== undefined)
984
- return this.trailingBatchEndedOn;
995
+ return this.answeredFrom(this.trailingBatchEndedOn, [this.trailingBatchEndedOn]);
985
996
  throw new AgentHarnessError("invalid_state", "AgentHarness prompt completed without an assistant message");
986
997
  }
987
998
  finally {
@@ -990,6 +1001,7 @@ export class AgentHarness {
990
1001
  }
991
1002
  finally {
992
1003
  this.runAbortController = undefined;
1004
+ this.activeRun = undefined;
993
1005
  }
994
1006
  }
995
1007
  }
@@ -1145,6 +1157,21 @@ export class AgentHarness {
1145
1157
  if (runQuietBefore && this.runAbortController?.signal.aborted === true)
1146
1158
  this.turnCutConsumed = { source };
1147
1159
  }
1160
+ answerEntryIdsOf(answer) {
1161
+ return answer === undefined ? [] : this.answerSources.get(answer);
1162
+ }
1163
+ answeredFrom(answer, members) {
1164
+ const ids = [];
1165
+ for (const m of members) {
1166
+ const id = this.committedEntryIds.get(m);
1167
+ if (id !== undefined)
1168
+ ids.push(id);
1169
+ else if (this.runHistory?.has(m) === true)
1170
+ return answer;
1171
+ }
1172
+ this.answerSources.set(answer, ids);
1173
+ return answer;
1174
+ }
1148
1175
  haltConsumption() {
1149
1176
  const turnCut = this.turnCutConsumed?.source;
1150
1177
  return {
@@ -1244,6 +1271,23 @@ export class AgentHarness {
1244
1271
  finalizeToolCall(toolCall, args, executed) {
1245
1272
  return finalizeToolOutcome(toolCall, executed, (result, isError) => this.afterToolCallHook(toolCall, args, result, isError), this.onToolMediaRefused);
1246
1273
  }
1274
+ async callTool(toolCall, signal, admit) {
1275
+ const run = this.activeRun;
1276
+ if (run === undefined)
1277
+ throw new AgentHarnessError("invalid_state", "a host's tool call runs inside a running prompt, and none is running");
1278
+ const context = run.context();
1279
+ const tool = findToolByName(context.tools, toolCall.name);
1280
+ if (tool === undefined)
1281
+ throw new AgentHarnessError("invalid_state", `no tool named "${toolCall.name}" in this run (it has ${(context.tools ?? []).map((t) => t.name).join(", ") || "none"})`);
1282
+ admit(tool);
1283
+ const both = signal !== undefined ? AbortSignal.any([signal, run.signal]) : run.signal;
1284
+ return (await runToolCall(context, undefined, toolCall, run.config, both, run.emit)).finalized;
1285
+ }
1286
+ isBatchSafe(toolName, args) {
1287
+ const tools = this.activeRun?.context().tools;
1288
+ const tool = findToolByName(tools, toolName);
1289
+ return tool !== undefined && isBatchSafeToolCall(tool, { type: "toolCall", id: "", name: toolName, arguments: (typeof args === "object" && args !== null ? args : {}) });
1290
+ }
1247
1291
  getModel() {
1248
1292
  return this.model;
1249
1293
  }
@@ -1463,6 +1507,7 @@ function mergeTruncatedOutputChain(messages, lastAssistantIndex) {
1463
1507
  const last = messages[lastAssistantIndex];
1464
1508
  const lastText = last.content.map((c) => (c.type === "text" ? c.text : "")).join("");
1465
1509
  const parts = [];
1510
+ const members = [last];
1466
1511
  let i = lastAssistantIndex;
1467
1512
  while (i - 2 >= 0) {
1468
1513
  const mid = messages[i - 1];
@@ -1477,18 +1522,20 @@ function mergeTruncatedOutputChain(messages, lastAssistantIndex) {
1477
1522
  if (!step)
1478
1523
  break;
1479
1524
  parts.unshift(head.content.map((c) => (c.type === "text" ? c.text : "")).join(""));
1525
+ members.unshift(head);
1480
1526
  i = i - 2;
1481
1527
  }
1482
1528
  if (parts.length === 0) {
1483
- return last;
1529
+ return { message: last, members };
1484
1530
  }
1485
- return {
1531
+ const message = {
1486
1532
  ...last,
1487
1533
  content: [
1488
1534
  { type: "text", text: parts.join("") + lastText },
1489
1535
  ...last.content.filter((c) => c.type !== "text"),
1490
1536
  ],
1491
1537
  };
1538
+ return { message, members };
1492
1539
  }
1493
1540
  function toLintErrorObject(value, fallbackMessage) {
1494
1541
  if (value instanceof Error) {
@@ -2,6 +2,7 @@ import type { PromptEpochDescriptor } from "../../prompt-assembly/epoch.js";
2
2
  import type { DocumentContent, ImageContent, Model, SimpleStreamOptions, TextContent, Transport } from "../llm/index.js";
3
3
  import type { AfterToolCallResult, AgentEvent, AgentMessage, AgentTool, BeforeToolCallResult, QueueMode, ThinkingLevel } from "../loop/types.js";
4
4
  import type { AgentCoreRuntimeDeps } from "../loop/runtime-deps.js";
5
+ import type { SecretEnvFinding } from "../../core/secret-env.js";
5
6
  /** Result of a fallible operation. Expected failures are returned as `ok: false` instead of thrown. */
6
7
  export type Result<TValue, TError> = {
7
8
  ok: true;
@@ -103,7 +104,11 @@ export interface WriteReceipt {
103
104
  created: boolean;
104
105
  }
105
106
  /** Stable, backend-independent file error codes returned by {@link FileSystem} file operations. */
106
- export type FileErrorCode = "aborted" | "not_found" | "permission_denied" | "not_directory" | "is_directory" | "invalid" | "not_supported"
107
+ export type FileErrorCode = "aborted" | "not_found" | "permission_denied" | "not_directory" | "is_directory"
108
+ /** A name this filesystem cannot hold (POSIX `ENAMETOOLONG` for a path component past `NAME_MAX`) — nothing can be there, and
109
+ * a program that opens it fails the same way: an absence as conclusive as `not_found`. A path past `PATH_MAX` whose
110
+ * components are short is not this word (such a file may exist, reached from a directory below it). */
111
+ | "name_too_long" | "invalid" | "not_supported"
107
112
  /** Exclusive create refused because the path already exists ({@link FileSystem.writeFileExclusive},
108
113
  * POSIX `O_EXCL` shape). Discriminable so a caller can distinguish "lost the create race" from a
109
114
  * write failure and give honest guidance instead of overwriting. */
@@ -550,6 +555,11 @@ export interface ExecutionEnv extends FileSystem, Shell {
550
555
  readonly homeDir?: string;
551
556
  /** #1554 — the `CDPATH` entries the shell child receives (`[]` = none), or `"unknown"` when the adapter cannot say. */
552
557
  readonly cdPath: readonly string[] | "unknown";
558
+ /** #1963 — the entries of the environment the shell child inherits that it does NOT receive: the findings of the one
559
+ * composition its spawns read (`inheritedHostEnv(policy, findings)`), less the keys the adapter's explicit grants
560
+ * re-supply — names and rules, never a value. `[]` = none withheld, or none inherited (a shell environment built
561
+ * rather than inherited from this process); `"unknown"` = the adapter cannot say. A read: it announces nothing. */
562
+ readonly withheldEnv: readonly SecretEnvFinding[] | "unknown";
553
563
  }
554
564
  /** Base fields shared by append-only session tree entries. */
555
565
  export interface SessionTreeEntryBase {
@@ -916,6 +926,16 @@ export interface SessionMetadata {
916
926
  /** WHO owns this row, recorded by the write that creates it and changed by no later write; `null` = anonymous; absent reads as `null`. */
917
927
  owner?: string | null;
918
928
  }
929
+ /**
930
+ * One row of {@link SessionRepo.list}: the row's metadata, plus the newest activity the repo records for the row. `lastActiveAt` is
931
+ * epoch ms — on the File repo its log's modification time (every write to a row is an append to its log, and {@link SessionRepo.touch}
932
+ * moves the same time), on the in-memory repo its last {@link SessionRepo.touch} (it never sees its sessions' writes). Absent = the repo
933
+ * records none; a reader then takes the row's `createdAt`. It is what the repo records, never what one process saw — so a dropped
934
+ * cache, a restart or another replica reads the same time, and only a later activity moves it.
935
+ */
936
+ export type SessionRow<TMetadata extends SessionMetadata = SessionMetadata> = TMetadata & {
937
+ readonly lastActiveAt?: number;
938
+ };
919
939
  /** One row's owner, occupant (`undefined` = unknown) and active leaf (`null` = none), read in ONE read so the three answer for one row generation. */
920
940
  export interface SessionHead {
921
941
  readonly owner: string | null;
@@ -1078,7 +1098,12 @@ export interface SessionForkOptions {
1078
1098
  export interface SessionRepo<TMetadata extends SessionMetadata = SessionMetadata, TCreateOptions extends SessionCreateOptions = SessionCreateOptions, TListOptions = void> {
1079
1099
  create(options: TCreateOptions): Promise<Session<TMetadata>>;
1080
1100
  open(metadata: TMetadata): Promise<Session<TMetadata>>;
1081
- list(options?: TListOptions): Promise<TMetadata[]>;
1101
+ /** Every ordinary row (placed rows are not listed), each with the newest write the repo holds for it ({@link SessionRow}), in no
1102
+ * promised order. The source `TtlSessionStore.list` reads; the store, not the repo, orders, filters and pages. */
1103
+ list(options?: TListOptions): Promise<SessionRow<TMetadata>[]>;
1104
+ /** Record activity on the row now: the time {@link list} answers as the row's `lastActiveAt` moves to now. A missing row is a no-op; a
1105
+ * fault rejects. Optional: a repo without it records only what its writes record. */
1106
+ touch?(sessionId: string): Promise<void>;
1082
1107
  delete(metadata: TMetadata): Promise<void>;
1083
1108
  /** A fork is a NEW row: `options.id` equal to the source's id is refused (`invalid_fork_target`) — onto its source it would mint a new occupant over the source's own transcript. */
1084
1109
  fork(source: TMetadata, options: SessionForkOptions & TCreateOptions): Promise<Session<TMetadata>>;
@@ -1464,6 +1489,8 @@ export interface AgentHarnessOptions<TSkill extends Skill = Skill, TPromptTempla
1464
1489
  * texts themselves never change.
1465
1490
  */
1466
1491
  abortResultDetails?: () => Record<string, unknown> | undefined;
1492
+ /** The host's station around one tool execution, forwarded verbatim to the loop config (`AgentLoopConfig.executeTool`). */
1493
+ executeTool?: import("../loop/types.js").AgentLoopConfig["executeTool"];
1467
1494
  /**
1468
1495
  * C2: the loop's recovery/terminal trace sink, forwarded to `runAgentLoop`'s trace
1469
1496
  * parameter (previously test-only — never passed in production, so the loop's six self-heal
@@ -5,6 +5,7 @@ import type { ProviderCondition, ProviderConditionSource } from "../../brain/pro
5
5
  import type { RequestRoute, RouteCarrierBag, RouteCredentialSource } from "../../brain/request-route.js";
6
6
  export type { RouteCredentialSource } from "../../brain/request-route.js";
7
7
  import type { ModelOutputInvalidCause } from "./tool-turns.js";
8
+ import type { PromptTraitName, TraitCondition } from "../../prompt-assembly/catalog/schema.js";
8
9
  export type KnownApi = "openai-completions" | "mistral-conversations" | "openai-responses" | "azure-openai-responses" | "openai-chatgpt-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-vertex";
9
10
  export type Api = KnownApi | (string & {});
10
11
  export type KnownImagesApi = "openrouter-images";
@@ -697,11 +698,24 @@ export interface Tool<TParameters extends TSchema = TSchema> {
697
698
  /** VENDORED EDIT (design/115 P0): canonical tool renames keep old model/SDK wire names as aliases. */
698
699
  aliases?: string[];
699
700
  description: string;
700
- /** R2 双形轴 — classic-profile description variant (see ToolSpec.descriptionClassic). Swapped in
701
- * for `description` at mount time when the run's promptProfile is "classic"; absent = one form. */
702
- descriptionClassic?: string;
701
+ /** The description's conditional variants (see ToolSpec.descriptionVariants): at mount, the first whose traits
702
+ * condition holds over the run's traits replaces `description`; none holds ⇒ `description`. */
703
+ descriptionVariants?: readonly ToolDescriptionVariant[];
703
704
  parameters: TParameters;
704
705
  }
706
+ /**
707
+ * One conditional variant of a tool's description — the tool card's variant table is these, first match wins, with
708
+ * `description` as the unconditional last entry. Chosen by the run's prompt traits through the same trait reading the
709
+ * prompt catalog's variants use; the variant chosen is reported in the tool's `cardId` (`<card>#<id>`).
710
+ */
711
+ export interface ToolDescriptionVariant {
712
+ /** The variant's name in the tool's card id: non-empty, at most 64 characters of `[A-Za-z0-9._-]`, unique per tool. */
713
+ readonly id: string;
714
+ /** The trait condition (`allOf` / `noneOf`, trait names) under which this text replaces `description`. */
715
+ readonly traits: TraitCondition;
716
+ /** The description text (non-blank). */
717
+ readonly text: string;
718
+ }
705
719
  export interface Context {
706
720
  systemPrompt?: string;
707
721
  /**
@@ -924,7 +938,9 @@ export interface Model<TApi extends Api = Api> {
924
938
  api: TApi;
925
939
  provider: Provider;
926
940
  baseUrl: string;
927
- reasoning: boolean;
941
+ /** Declares reasoning (thinking keys): `true` / `false`, absent = not declared. Read only through `capabilityOf`
942
+ * (`brain/model-capability.ts`), which also says what an undeclared capability means. */
943
+ reasoning?: boolean;
928
944
  /**
929
945
  * design/111 — this model's DEFAULT thinking level (per-model preset). The thinking-resolution chain is
930
946
  * `spec.thinking ?? role.thinking ?? model.defaultThinking` (prepare-task) — a caller/role still overrides, but
@@ -940,7 +956,8 @@ export interface Model<TApi extends Api = Api> {
940
956
  * Missing keys use provider defaults. null marks a level as unsupported.
941
957
  */
942
958
  thinkingLevelMap?: ThinkingLevelMap;
943
- input: ("text" | "image")[];
959
+ /** Declares image input: a list with `"image"` = on, without = off, absent = not declared (same reader as `reasoning`). */
960
+ input?: ("text" | "image")[];
944
961
  cost?: {
945
962
  input: number;
946
963
  output: number;
@@ -996,13 +1013,13 @@ export interface Model<TApi extends Api = Api> {
996
1013
  /** Extra request HEADERS merged into the provider call. Cannot override auth / content-type / version. */
997
1014
  headers?: Record<string, string>;
998
1015
  /**
999
- * design/119 S3: model-declared system-prompt guidance sections, appended to
1000
- * the assembled system prompt. This is the declarative home for per-model behavioral patches (CC
1001
- * ships Fable-5 "mitigations" baked behind model-name checks; sema keeps the MECHANISM generic —
1002
- * any Model can carry guidance — and the CONTENT as preset data, zero model-name matching in core).
1003
- * Each entry is one section; joined with blank lines.
1016
+ * The prompt traits this model has: the reference's capability names that gate prompt text (`PROMPT_TRAITS`), its
1017
+ * bundle names (`PROMPT_TRAIT_BUNDLES`, expanded to their members), or a deployment's own `x-<namespace>-<name>`.
1018
+ * The prompt catalog and every overlay's `when.traits` select on them; the engine never derives them from `id`. An
1019
+ * EXACT set — nothing is added to what it lists (declare `lean_prompt` for the lean shape). Absent ⇒
1020
+ * `["lean_prompt"]`. A name that is none of these refuses the task (`config.prompt_trait_unknown`).
1004
1021
  */
1005
- promptGuidance?: string[];
1022
+ promptTraits?: readonly PromptTraitName[];
1006
1023
  /** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
1007
1024
  compat?: TApi extends "openai-completions" ? OpenAICompletionsCompat : TApi extends "openai-responses" ? OpenAIResponsesCompat : TApi extends "anthropic-messages" ? AnthropicMessagesCompat : never;
1008
1025
  }
@@ -154,11 +154,33 @@ type ExecutedToolCallBatch = {
154
154
  messages: ToolResultMessage[];
155
155
  terminate: boolean;
156
156
  };
157
+ /**
158
+ * ONE call through the loop's per-call pipeline — announced, prepared (the gate included), executed through the execution
159
+ * seat, finalized, closed. The sequential lane runs each call through it and adds the call's tool-result message; a host's
160
+ * own call (`AgentHarness.callTool`) runs it with no model message and adds nothing. The partitioned and streaming lanes run
161
+ * the same steps in two phases.
162
+ */
163
+ export declare function runToolCall(currentContext: AgentContext, assistantMessage: AssistantMessage | undefined, toolCall: AgentToolCall, config: AgentLoopConfig, signal: AbortSignal | undefined, emit: AgentEventSink): Promise<{
164
+ finalized: FinalizedToolCallOutcome;
165
+ halt?: HaltRemainingDirective;
166
+ }>;
167
+ /**
168
+ * Partition rule: a call is batch-safe ONLY if its arguments
169
+ * VALIDATE against the tool's schema (CC `safeParse` — a malformed call never rides a parallel batch;
170
+ * it stays a singleton and surfaces its validation error at execution) AND the tool/hook opts in.
171
+ * The hook sees the validated+coerced args — same as CC handing `parsed.data` to `isConcurrencySafe`.
172
+ */
173
+ export declare function isBatchSafeToolCall(tool: AgentTool | undefined, toolCall: AgentToolCall): boolean;
157
174
  /** An executed call's raw outcome, before (and, from {@link finalizeToolOutcome}, after) the post-execution half. */
158
175
  export type ExecutedToolCallOutcome = {
159
176
  result: AgentToolResult<unknown>;
160
177
  isError: boolean;
161
178
  };
179
+ type FinalizedToolCallOutcome = {
180
+ toolCall: AgentToolCall;
181
+ result: AgentToolResult<unknown>;
182
+ isError: boolean;
183
+ };
162
184
  /**
163
185
  * THE reading a value gets on its way to becoming a call's arguments: the tool's own preparation (`prepareArguments` —
164
186
  * a default filled in, an alias folded), then the schema's coercions ({@link validateToolArguments}). The loop reads the
@@ -802,27 +802,7 @@ async function executeToolCallsSequential(currentContext, assistantMessage, tool
802
802
  const messages = [];
803
803
  for (let i = 0; i < toolCalls.length; i++) {
804
804
  const toolCall = toolCalls[i];
805
- await emit({
806
- type: "tool_execution_start",
807
- toolCallId: toolCall.id,
808
- toolName: toolCall.name,
809
- args: toolCall.arguments,
810
- });
811
- const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
812
- let finalized;
813
- let halt;
814
- if (preparation.kind === "immediate") {
815
- finalized = {
816
- toolCall,
817
- result: preparation.result,
818
- isError: preparation.isError,
819
- };
820
- halt = preparation.halt;
821
- }
822
- else {
823
- finalized = await executePreparedWithDisclosure(currentContext, assistantMessage, preparation, config, signal, emit);
824
- }
825
- await emitToolExecutionEnd(finalized, emit);
805
+ const { finalized, halt } = await runToolCall(currentContext, assistantMessage, toolCall, config, signal, emit);
826
806
  const toolResultMessage = createToolResultMessage(finalized);
827
807
  await emitToolResultMessage(toolResultMessage, emit);
828
808
  finalizedCalls.push(finalized);
@@ -846,6 +826,15 @@ async function executeToolCallsSequential(currentContext, assistantMessage, tool
846
826
  terminate: shouldTerminateToolBatch(finalizedCalls),
847
827
  };
848
828
  }
829
+ export async function runToolCall(currentContext, assistantMessage, toolCall, config, signal, emit) {
830
+ await emit({ type: "tool_execution_start", toolCallId: toolCall.id, toolName: toolCall.name, args: toolCall.arguments });
831
+ const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
832
+ const finalized = preparation.kind === "immediate"
833
+ ? { toolCall, result: preparation.result, isError: preparation.isError }
834
+ : await executePreparedWithDisclosure(currentContext, assistantMessage, preparation, config, signal, emit);
835
+ await emitToolExecutionEnd(finalized, emit);
836
+ return { finalized, ...(preparation.kind === "immediate" && preparation.halt !== undefined ? { halt: preparation.halt } : {}) };
837
+ }
849
838
  async function settleHaltedToolCall(toolCall, halt, emit) {
850
839
  await emit({
851
840
  type: "tool_execution_start",
@@ -887,7 +876,7 @@ function isCallConcurrencySafe(tool, args) {
887
876
  return false;
888
877
  }
889
878
  }
890
- function isBatchSafeToolCall(tool, toolCall) {
879
+ export function isBatchSafeToolCall(tool, toolCall) {
891
880
  if (!tool)
892
881
  return false;
893
882
  let args;
@@ -1108,7 +1097,7 @@ class StreamToolExecutor {
1108
1097
  return;
1109
1098
  }
1110
1099
  entry.prepared = preparation;
1111
- entry.executed = await executePreparedToolCall(preparation, this.signal, this.emit, this.config.abortResultDetails, (error) => this.retainCancellation(error));
1100
+ entry.executed = await executePreparedToolCall(preparation, this.signal, this.emit, this.config.executeTool, this.config.abortResultDetails, (error) => this.retainCancellation(error));
1112
1101
  }
1113
1102
  catch (error) {
1114
1103
  if (isAbortSemanticsError(error))
@@ -1395,7 +1384,7 @@ async function prepareToolCall(currentContext, assistantMessage, toolCall, confi
1395
1384
  };
1396
1385
  }
1397
1386
  }
1398
- async function executePreparedToolCall(prepared, signal, emit, abortResultDetails, onLateCancellation) {
1387
+ async function executePreparedToolCall(prepared, signal, emit, executeTool, abortResultDetails, onLateCancellation) {
1399
1388
  const updateEvents = [];
1400
1389
  let acceptingUpdates = true;
1401
1390
  if (signal?.aborted) {
@@ -1404,7 +1393,7 @@ async function executePreparedToolCall(prepared, signal, emit, abortResultDetail
1404
1393
  const work = (async () => {
1405
1394
  let outcome;
1406
1395
  try {
1407
- const result = await prepared.tool.execute(prepared.toolCall.id, prepared.args, signal, (partialResult) => {
1396
+ const body = () => prepared.tool.execute(prepared.toolCall.id, prepared.args, signal, (partialResult) => {
1408
1397
  if (!acceptingUpdates) {
1409
1398
  return;
1410
1399
  }
@@ -1427,6 +1416,7 @@ async function executePreparedToolCall(prepared, signal, emit, abortResultDetail
1427
1416
  });
1428
1417
  updateEvents.push(delivery);
1429
1418
  });
1419
+ const result = executeTool !== undefined ? await executeTool({ toolCall: prepared.toolCall, tool: prepared.tool, args: prepared.args }, body, signal) : await body();
1430
1420
  outcome = { result, isError: result.isError === true };
1431
1421
  }
1432
1422
  catch (error) {
@@ -1507,7 +1497,7 @@ function raiseFatalCancellation(executor) {
1507
1497
  async function executePreparedWithDisclosure(currentContext, assistantMessage, prepared, config, signal, emit) {
1508
1498
  let executed;
1509
1499
  try {
1510
- executed = await executePreparedToolCall(prepared, signal, emit, config.abortResultDetails);
1500
+ executed = await executePreparedToolCall(prepared, signal, emit, config.executeTool, config.abortResultDetails);
1511
1501
  }
1512
1502
  catch (error) {
1513
1503
  if (isAbortSemanticsError(error))
@@ -127,9 +127,9 @@ export interface AfterToolCallResult {
127
127
  }
128
128
  /** Context passed to `beforeToolCall`. */
129
129
  export interface BeforeToolCallContext {
130
- /** The assistant message that requested the tool call. */
131
- assistantMessage: AssistantMessage;
132
- /** The raw tool call block from `assistantMessage.content`. */
130
+ /** The assistant message that requested the tool call — absent for a host's own call (an extension's `$.tool.call`), which no model message carried. */
131
+ assistantMessage?: AssistantMessage;
132
+ /** The raw tool call block (from `assistantMessage.content` when a model message carried it). */
133
133
  toolCall: AgentToolCall;
134
134
  /** Validated tool arguments for the target tool schema. */
135
135
  args: unknown;
@@ -142,9 +142,9 @@ export interface BeforeToolCallContext {
142
142
  }
143
143
  /** Context passed to `afterToolCall`. */
144
144
  export interface AfterToolCallContext {
145
- /** The assistant message that requested the tool call. */
146
- assistantMessage: AssistantMessage;
147
- /** The raw tool call block from `assistantMessage.content`. */
145
+ /** The assistant message that requested the tool call — absent for a host's own call (an extension's `$.tool.call`), which no model message carried. */
146
+ assistantMessage?: AssistantMessage;
147
+ /** The raw tool call block (from `assistantMessage.content` when a model message carried it). */
148
148
  toolCall: AgentToolCall;
149
149
  /** Validated tool arguments for the target tool schema. */
150
150
  args: unknown;
@@ -564,6 +564,16 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
564
564
  * signal re-check, which has always minted its abort result with no details.
565
565
  */
566
566
  abortResultDetails?: () => Record<string, unknown> | undefined;
567
+ /**
568
+ * The host's station around every tool execution, between the gate's allow and the body: `run` runs the body as the loop
569
+ * would (at most once), and what the station returns is the result the loop finalizes — it may answer without running it,
570
+ * and honors `signal`. Absent ⇒ the loop runs the body itself.
571
+ */
572
+ executeTool?: (call: {
573
+ readonly toolCall: AgentToolCall;
574
+ readonly tool: AgentTool;
575
+ readonly args: unknown;
576
+ }, run: () => Promise<AgentToolResult<unknown>>, signal: AbortSignal | undefined) => Promise<AgentToolResult<unknown>>;
567
577
  /**
568
578
  * Fault seat for a THROWING {@link AgentTool.validateInput}: the loop reads the throw as "no
569
579
  * verdict" (the call proceeds to the gate as if the tool had no validator) and reports the fault