@jr2/orchestrator 0.6.0 → 0.7.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 (301) hide show
  1. package/console/components/app.ts +55 -15
  2. package/console/components/bottom-drawer.ts +259 -0
  3. package/console/components/drawer.ts +14 -6
  4. package/console/components/fleet.ts +36 -13
  5. package/console/components/machine-pane.ts +61 -5
  6. package/console/components/nav.ts +54 -8
  7. package/console/conversation.ts +161 -0
  8. package/console/login.ts +123 -0
  9. package/console/main.ts +600 -60
  10. package/console/store.ts +611 -64
  11. package/console/style.css +231 -0
  12. package/docs/agents-block.md +2 -2
  13. package/docs/concepts/agents-and-turns.md +86 -9
  14. package/docs/concepts/architecture.md +41 -28
  15. package/docs/concepts/callers-and-hooks.md +205 -0
  16. package/docs/concepts/charts.md +7 -5
  17. package/docs/concepts/composition.md +10 -1
  18. package/docs/concepts/converge.md +4 -2
  19. package/docs/concepts/durable-runs.md +43 -16
  20. package/docs/concepts/effects.md +50 -22
  21. package/docs/concepts/gates.md +95 -25
  22. package/docs/concepts/machines-and-workflows.md +5 -4
  23. package/docs/concepts/pools-and-sources.md +187 -11
  24. package/docs/concepts/secrets-and-trust.md +73 -33
  25. package/docs/concepts/the-menu.md +11 -0
  26. package/docs/concepts/workspaces.md +6 -5
  27. package/docs/get-started/a-model-decides.md +14 -13
  28. package/docs/get-started/an-agent-in-a-sandbox.md +43 -34
  29. package/docs/get-started/connect-a-model.md +1 -1
  30. package/docs/get-started/create-an-instance.md +17 -14
  31. package/docs/guides/add-tools-to-the-sandbox.md +55 -11
  32. package/docs/guides/answer-a-gate-from-a-forge.md +304 -0
  33. package/docs/guides/answer-a-gate.md +74 -37
  34. package/docs/guides/bind-open-parts.md +24 -8
  35. package/docs/guides/call-an-mcp-tool-from-a-machine.md +572 -0
  36. package/docs/guides/cancel-a-run.md +26 -16
  37. package/docs/guides/fix-a-failed-converge.md +18 -6
  38. package/docs/guides/give-a-caller-a-scope.md +203 -0
  39. package/docs/guides/give-an-agent-mcp-tools.md +422 -0
  40. package/docs/guides/iterate-on-a-machine-on-kind.md +10 -9
  41. package/docs/guides/let-an-agent-write-a-chart.md +9 -6
  42. package/docs/guides/look-inside-a-sandbox.md +101 -31
  43. package/docs/guides/open-the-console.md +63 -14
  44. package/docs/guides/read-a-conversation.md +225 -0
  45. package/docs/guides/run-a-chart-by-name.md +17 -16
  46. package/docs/guides/run-one-worker-per-item.md +15 -9
  47. package/docs/guides/set-an-agents-access-and-dials.md +2 -0
  48. package/docs/guides/start-a-run-for-each-alert.md +290 -0
  49. package/docs/guides/start-a-run-from-a-run.md +18 -16
  50. package/docs/guides/start-a-run.md +24 -18
  51. package/docs/guides/steer-an-agent.md +332 -0
  52. package/docs/guides/use-a-hosted-provider.md +1 -1
  53. package/docs/guides/watch-a-run.md +127 -121
  54. package/docs/guides/write-a-hook-kind.md +238 -0
  55. package/docs/guides/write-a-tool-as-an-mcp-server.md +351 -0
  56. package/docs/guides/write-a-workflow.md +17 -7
  57. package/docs/llms.txt +81 -15
  58. package/docs/reference/authoring-surface/agent.md +1 -1
  59. package/docs/reference/authoring-surface/answer.md +1 -1
  60. package/docs/reference/authoring-surface/arg.md +1 -1
  61. package/docs/reference/authoring-surface/basic.md +1 -1
  62. package/docs/reference/authoring-surface/bearer.md +1 -1
  63. package/docs/reference/authoring-surface/branchname.md +1 -1
  64. package/docs/reference/authoring-surface/carry.md +23 -0
  65. package/docs/reference/authoring-surface/chartschema.md +1 -1
  66. package/docs/reference/authoring-surface/chartschemafor.md +1 -1
  67. package/docs/reference/authoring-surface/command.md +1 -1
  68. package/docs/reference/authoring-surface/customize.md +4 -1
  69. package/docs/reference/authoring-surface/defineconfig.md +1 -1
  70. package/docs/reference/authoring-surface/defineevent.md +1 -1
  71. package/docs/reference/authoring-surface/dispatch.md +5 -4
  72. package/docs/reference/authoring-surface/fail.md +1 -1
  73. package/docs/reference/authoring-surface/file.md +1 -1
  74. package/docs/reference/authoring-surface/frompick.md +1 -1
  75. package/docs/reference/authoring-surface/gate.md +118 -0
  76. package/docs/reference/authoring-surface/group-agents.md +15 -0
  77. package/docs/reference/authoring-surface/group-charts.md +16 -0
  78. package/docs/reference/authoring-surface/group-composition.md +25 -0
  79. package/docs/reference/authoring-surface/group-config.md +17 -0
  80. package/docs/reference/authoring-surface/group-effects.md +48 -0
  81. package/docs/reference/authoring-surface/group-failure.md +13 -0
  82. package/docs/reference/authoring-surface/group-gates.md +16 -0
  83. package/docs/reference/authoring-surface/group-machine-and-events.md +15 -0
  84. package/docs/reference/authoring-surface/group-steering.md +12 -0
  85. package/docs/reference/authoring-surface/group-types-these-signatures-name.md +137 -0
  86. package/docs/reference/authoring-surface/group-workspaces-and-repos.md +15 -0
  87. package/docs/reference/authoring-surface/http.md +1 -1
  88. package/docs/reference/authoring-surface/isfailure.md +1 -1
  89. package/docs/reference/authoring-surface/isready.md +1 -1
  90. package/docs/reference/authoring-surface/jr2setup.md +13 -3
  91. package/docs/reference/authoring-surface/mcp.md +107 -0
  92. package/docs/reference/authoring-surface/open.md +5 -3
  93. package/docs/reference/authoring-surface/openbody.md +1 -1
  94. package/docs/reference/authoring-surface/paramsof.md +1 -1
  95. package/docs/reference/authoring-surface/pool.md +77 -9
  96. package/docs/reference/authoring-surface/push.md +1 -1
  97. package/docs/reference/authoring-surface/readyof.md +1 -1
  98. package/docs/reference/authoring-surface/reread.md +19 -0
  99. package/docs/reference/authoring-surface/secret.md +1 -1
  100. package/docs/reference/authoring-surface/sentby.md +1 -1
  101. package/docs/reference/authoring-surface/skip.md +22 -0
  102. package/docs/reference/authoring-surface/source.md +56 -1
  103. package/docs/reference/authoring-surface/steer.md +93 -0
  104. package/docs/reference/authoring-surface/text.md +1 -1
  105. package/docs/reference/authoring-surface/type-agentdefinition.md +14 -1
  106. package/docs/reference/authoring-surface/type-agentmcpserver.md +54 -0
  107. package/docs/reference/authoring-surface/type-anyframepath.md +1 -1
  108. package/docs/reference/authoring-surface/type-anyworktreepath.md +1 -1
  109. package/docs/reference/authoring-surface/type-binding.md +1 -1
  110. package/docs/reference/authoring-surface/type-caller.md +40 -0
  111. package/docs/reference/authoring-surface/type-callerrecord.md +32 -0
  112. package/docs/reference/authoring-surface/type-carry.md +19 -0
  113. package/docs/reference/authoring-surface/type-chainlink.md +3 -3
  114. package/docs/reference/authoring-surface/type-commandoutput.md +1 -1
  115. package/docs/reference/authoring-surface/type-customize.md +16 -1
  116. package/docs/reference/authoring-surface/type-delivered.md +17 -0
  117. package/docs/reference/authoring-surface/type-deliveredevent.md +18 -0
  118. package/docs/reference/authoring-surface/type-dispatchdefinition.md +4 -3
  119. package/docs/reference/authoring-surface/type-dispatchoutput.md +1 -1
  120. package/docs/reference/authoring-surface/type-effectbinding.md +12 -2
  121. package/docs/reference/authoring-surface/type-framepath.md +1 -1
  122. package/docs/reference/authoring-surface/type-gatebinding.md +15 -0
  123. package/docs/reference/authoring-surface/type-gatehooks.md +12 -0
  124. package/docs/reference/authoring-surface/type-gatelook.md +37 -0
  125. package/docs/reference/authoring-surface/type-gateoutcome.md +32 -0
  126. package/docs/reference/authoring-surface/type-gatereply.md +19 -0
  127. package/docs/reference/authoring-surface/type-gateslot.md +21 -0
  128. package/docs/reference/authoring-surface/type-gateslotinput.md +13 -0
  129. package/docs/reference/authoring-surface/type-gateslotparts.md +18 -0
  130. package/docs/reference/authoring-surface/type-gateslots.md +12 -0
  131. package/docs/reference/authoring-surface/type-gatetypesat.md +13 -0
  132. package/docs/reference/authoring-surface/type-hostinjectedinput.md +1 -1
  133. package/docs/reference/authoring-surface/type-httpoutput.md +1 -1
  134. package/docs/reference/authoring-surface/type-jr2config.md +37 -2
  135. package/docs/reference/authoring-surface/type-lateroutcome.md +1 -1
  136. package/docs/reference/authoring-surface/type-lends.md +5 -1
  137. package/docs/reference/authoring-surface/type-lookoutput.md +14 -0
  138. package/docs/reference/authoring-surface/type-mcpcalloutput.md +78 -0
  139. package/docs/reference/authoring-surface/type-mcpnotreturned.md +42 -0
  140. package/docs/reference/authoring-surface/type-mcpoptions.md +47 -0
  141. package/docs/reference/authoring-surface/type-mcpoutput.md +50 -0
  142. package/docs/reference/authoring-surface/type-mcpreadoutput.md +53 -0
  143. package/docs/reference/authoring-surface/type-mcpremoteserver.md +50 -0
  144. package/docs/reference/authoring-surface/type-mcpserver.md +41 -0
  145. package/docs/reference/authoring-surface/type-mcpstdioserver.md +42 -0
  146. package/docs/reference/authoring-surface/type-namedsecret.md +4 -4
  147. package/docs/reference/authoring-surface/type-openbodydeclaration.md +1 -1
  148. package/docs/reference/authoring-surface/type-openbodyoutput.md +1 -1
  149. package/docs/reference/authoring-surface/type-poolnextinput.md +1 -1
  150. package/docs/reference/authoring-surface/type-poolspec.md +11 -6
  151. package/docs/reference/authoring-surface/type-pushoutput.md +1 -1
  152. package/docs/reference/authoring-surface/type-pushsourcespec.md +38 -0
  153. package/docs/reference/authoring-surface/type-readsourcespec.md +47 -0
  154. package/docs/reference/authoring-surface/type-reposlot.md +1 -1
  155. package/docs/reference/authoring-surface/type-reread.md +18 -0
  156. package/docs/reference/authoring-surface/type-runsconfig.md +41 -0
  157. package/docs/reference/authoring-surface/type-sender.md +26 -1
  158. package/docs/reference/authoring-surface/type-sendercallerfield.md +14 -0
  159. package/docs/reference/authoring-surface/type-size.md +1 -1
  160. package/docs/reference/authoring-surface/type-skip.md +19 -0
  161. package/docs/reference/authoring-surface/type-sourcehooks.md +23 -0
  162. package/docs/reference/authoring-surface/type-sourcein.md +25 -0
  163. package/docs/reference/authoring-surface/type-sourcereply.md +18 -0
  164. package/docs/reference/authoring-surface/type-sourcespec.md +16 -7
  165. package/docs/reference/authoring-surface/type-sourceverdict.md +49 -0
  166. package/docs/reference/authoring-surface/type-standingpoolmachine.md +12 -0
  167. package/docs/reference/authoring-surface/type-standingpoolspec.md +51 -0
  168. package/docs/reference/authoring-surface/type-steerargs.md +20 -0
  169. package/docs/reference/authoring-surface/type-thinkinglevel.md +1 -1
  170. package/docs/reference/authoring-surface/type-usercontainer.md +1 -1
  171. package/docs/reference/authoring-surface/type-workspaced.md +1 -1
  172. package/docs/reference/authoring-surface/type-worktreefound.md +3 -3
  173. package/docs/reference/authoring-surface/type-worktreeinput.md +1 -1
  174. package/docs/reference/authoring-surface/type-worktreeoptions.md +1 -1
  175. package/docs/reference/authoring-surface/type-worktreeoutput.md +1 -1
  176. package/docs/reference/authoring-surface/type-worktreepath.md +1 -1
  177. package/docs/reference/authoring-surface/type-worktreeready.md +1 -1
  178. package/docs/reference/authoring-surface/type-worktreerefused.md +4 -4
  179. package/docs/reference/authoring-surface/workspace.md +1 -1
  180. package/docs/reference/authoring-surface/worktree.md +1 -1
  181. package/docs/reference/authoring-surface.md +88 -167
  182. package/docs/reference/cli.md +413 -74
  183. package/docs/reference/config.md +235 -2
  184. package/docs/reference/decisions/0002-duplex-streaming-actor.md +71 -11
  185. package/docs/reference/decisions/0005-sandbox-pod-composition.md +14 -10
  186. package/docs/reference/decisions/0006-agent-control-surface.md +4 -4
  187. package/docs/reference/decisions/0007-durable-machine-state.md +1 -1
  188. package/docs/reference/decisions/0009-cli-and-instance-interface.md +150 -49
  189. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +5 -3
  190. package/docs/reference/decisions/0011-workflow-defined-events.md +256 -12
  191. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +9 -2
  192. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +20 -14
  193. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +53 -27
  194. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +18 -14
  195. package/docs/reference/decisions/0017-pool-over-a-source-port.md +226 -12
  196. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +15 -7
  197. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +32 -18
  198. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +14 -1
  199. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +4 -4
  200. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +116 -34
  201. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +38 -37
  202. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +10 -5
  203. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +7 -6
  204. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +23 -7
  205. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +18 -10
  206. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +3 -2
  207. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +23 -18
  208. package/docs/reference/decisions/0032-the-console-unlocks-with-a-callers-credential.md +101 -0
  209. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +4 -3
  210. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +6 -6
  211. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +5 -4
  212. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +19 -19
  213. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +6 -1
  214. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +55 -40
  215. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +14 -13
  216. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +7 -0
  217. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +13 -7
  218. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +38 -30
  219. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +64 -17
  220. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +2 -1
  221. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +2 -2
  222. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-kept-for-a-set-time.md +109 -0
  223. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +51 -23
  224. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +94 -54
  225. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +101 -47
  226. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +32 -9
  227. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +17 -13
  228. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +56 -30
  229. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +35 -25
  230. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +4 -3
  231. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +37 -10
  232. package/docs/reference/decisions/0078-a-caller-comes-from-one-authenticator-seam-and-acts-within-its-scopes.md +285 -0
  233. package/docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md +198 -0
  234. package/docs/reference/decisions.md +6 -4
  235. package/docs/reference/glossary.md +96 -42
  236. package/docs/reference/hooks.md +1077 -0
  237. package/docs/reference/http-api.md +976 -149
  238. package/docs/why.md +2 -1
  239. package/package.json +10 -3
  240. package/src/actor.ts +36 -10
  241. package/src/agent.ts +50 -0
  242. package/src/assembly-checks.ts +530 -4
  243. package/src/callers.ts +245 -0
  244. package/src/chart.ts +52 -7
  245. package/src/config.ts +550 -1
  246. package/src/conversations.ts +453 -0
  247. package/src/custodian.ts +8 -2
  248. package/src/customize.ts +143 -4
  249. package/src/dispatch-effect.ts +142 -26
  250. package/src/durability.ts +2 -0
  251. package/src/duration.ts +20 -0
  252. package/src/effect-checks.ts +2 -1
  253. package/src/effect.ts +60 -7
  254. package/src/effector-wire.ts +272 -27
  255. package/src/gate-brand.ts +16 -0
  256. package/src/gate.ts +634 -48
  257. package/src/harness-client.ts +10 -4
  258. package/src/held-secrets.ts +72 -23
  259. package/src/holds.ts +2 -2
  260. package/src/hook-kinds/discord.ts +92 -0
  261. package/src/hook-kinds/door.ts +107 -0
  262. package/src/hook-kinds/github.ts +89 -0
  263. package/src/hook-kinds/gitlab.ts +72 -0
  264. package/src/hook-kinds/hook.ts +7 -0
  265. package/src/hook-kinds/index.ts +465 -0
  266. package/src/hook-kinds/slack.ts +151 -0
  267. package/src/hook-kinds/webhook.ts +113 -0
  268. package/src/hooks.ts +506 -0
  269. package/src/http-effect.ts +76 -38
  270. package/src/http.ts +889 -94
  271. package/src/index.ts +16 -5
  272. package/src/instance.ts +196 -26
  273. package/src/internal.ts +22 -3
  274. package/src/machine-doc.ts +26 -1
  275. package/src/mcp-effect.ts +424 -0
  276. package/src/mount-digest.ts +41 -7
  277. package/src/names.ts +64 -2
  278. package/src/notices.ts +138 -10
  279. package/src/open-body.ts +25 -11
  280. package/src/open-effect.ts +17 -4
  281. package/src/open.ts +4 -2
  282. package/src/parts.ts +87 -9
  283. package/src/party.ts +2 -1
  284. package/src/pick.ts +2 -2
  285. package/src/pool.ts +1142 -163
  286. package/src/registration.ts +203 -13
  287. package/src/run-host.ts +1509 -171
  288. package/src/run-list.ts +191 -0
  289. package/src/sandbox-kube.ts +53 -5
  290. package/src/secret-placement.ts +239 -33
  291. package/src/server.ts +53 -4
  292. package/src/setup.ts +72 -32
  293. package/src/snapshot-store.ts +565 -48
  294. package/src/steer.ts +111 -0
  295. package/src/stub-harness.ts +6 -2
  296. package/src/tokens.ts +263 -22
  297. package/src/wire.ts +17 -0
  298. package/src/workspace.ts +50 -6
  299. package/src/worktree.ts +3 -3
  300. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +0 -61
  301. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +0 -65
package/docs/why.md CHANGED
@@ -47,7 +47,8 @@ cannot be the right one for each of them.
47
47
 
48
48
  The You band of the diagram holds the clients of jr2. The [Orchestrator](reference/glossary.md#orchestrator) is an HTTP
49
49
  API. The [jr2 CLI](reference/glossary.md#jr2-cli) and the [Console](reference/glossary.md#console) are its clients, and
50
- your own app, such as a webhook, can be one too. For example, a client can start a run with
50
+ your own app, such as a CI job or a bridge to a chat service, can be one too. An outside service, such as a forge, sends
51
+ its deliveries to a [Hook](reference/glossary.md#hook). For example, a client can start a run with
51
52
  [`POST /workflows/:name/runs`](reference/http-api.md#post-workflows-name-runs). In the diagram, a
52
53
  [Gate](reference/glossary.md#gate) in the state `approval` asks you, and you answer from any of these clients, with
53
54
  [`POST /runs/:runId/gates/:gate/events`](reference/http-api.md#post-runs-runid-gates-gate-events).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jr2/orchestrator",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "The jr2 Orchestrator: xstate runtime, HTTP API and Console, and the kit pieces a Workflow imports.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -31,6 +31,12 @@
31
31
  "exports": {
32
32
  ".": "./src/index.ts",
33
33
  "./internal": "./src/internal.ts",
34
+ "./hooks": "./src/hook-kinds/index.ts",
35
+ "./hooks/github": "./src/hook-kinds/github.ts",
36
+ "./hooks/gitlab": "./src/hook-kinds/gitlab.ts",
37
+ "./hooks/slack": "./src/hook-kinds/slack.ts",
38
+ "./hooks/discord": "./src/hook-kinds/discord.ts",
39
+ "./hooks/webhook": "./src/hook-kinds/webhook.ts",
34
40
  "./tsconfig.instance.json": "./tsconfig.instance.json"
35
41
  },
36
42
  "types": "./src/index.ts",
@@ -38,15 +44,16 @@
38
44
  "@hono/node-server": "^2.0.6",
39
45
  "elkjs": "^0.11.1",
40
46
  "hono": "^4.12.27",
47
+ "jose": "^6.2.3",
41
48
  "preact": "^10.29.8",
42
49
  "ts-blank-space": "^0.9.0",
43
50
  "xstate": "^5.18.0",
44
51
  "zod": "^4.4.3",
45
- "@jr2/agent-protocol": "0.6.0"
52
+ "@jr2/agent-protocol": "0.7.0"
46
53
  },
47
54
  "devDependencies": {
48
55
  "@types/node": "^26.0.1",
49
- "@jr2/harness": "0.6.0"
56
+ "@jr2/harness": "0.7.0"
50
57
  },
51
58
  "files": [
52
59
  "bin",
package/src/actor.ts CHANGED
@@ -56,9 +56,15 @@ import type { HarnessRestarts, MemoryKill } from "./workspace.ts";
56
56
  import { INSTANCE_HARNESS_SERVICE } from "./names.ts";
57
57
  import { SENDER_KEY } from "@jr2/agent-protocol";
58
58
  import { agentAddress, agentSlot, continuedIid, allowedPicks, resolveAccepts, runBindingOf } from "./registration.ts";
59
- import type { NoticeScope } from "./notices.ts";
59
+ import type { LedgerBody, NoticeScope } from "./notices.ts";
60
60
  import { restOf } from "./rest.ts";
61
- import { SUBMISSION_HARNESS_RESTARTED, SUBMISSION_RUNAWAY, type Notice, type PodMemoryKill } from "./wire.ts";
61
+ import {
62
+ SUBMISSION_HARNESS_RESTARTED,
63
+ SUBMISSION_RUNAWAY,
64
+ type Notice,
65
+ type PodMemoryKill,
66
+ type SteeringMessage,
67
+ } from "./wire.ts";
62
68
  import type { AbortCause } from "./wire.ts";
63
69
 
64
70
  /**
@@ -123,6 +129,14 @@ export type AgentAdmission = {
123
129
  */
124
130
  agent?: string;
125
131
  endpoint?: string;
132
+ /**
133
+ * The pod and the slot of the conversation (ADR-0076) — stamped by the ACTOR at ledger time, like
134
+ * `agent`. The kept conversation's route takes entries for this conversation only from this pod's
135
+ * control token, for this slot (ADR-0023). It reads the ledger and not the live registration,
136
+ * because the ledger outlives the Turn and the run.
137
+ */
138
+ sandbox?: string;
139
+ slot?: string;
126
140
  };
127
141
 
128
142
  /**
@@ -367,6 +381,8 @@ export type AgentAdmitOptions = {
367
381
  /** The pending notices in this admission's scope (ADR-0062), for the Briefing's Turn part. Not
368
382
  * on the persisted input either: they are the Orchestrator's, and delivered once. */
369
383
  notices?: Notice[];
384
+ /** The Steering messages held for this Agent slot (ADR-0002), delivered by the rules of a notice. */
385
+ steering?: SteeringMessage[];
370
386
  /** The admission is for a conversation that `holds` said the Harness keeps (ADR-0062): the
371
387
  * re-admission after a cut, and a continued Turn. That "kept" can be a timeout's, so a Harness
372
388
  * that keeps none refuses it and seats none; `admit` then rejects with an error whose `notKept`
@@ -739,7 +755,10 @@ export function agentActorWith(
739
755
  // Per iid, the notices a step boundary's surface read reserved and the Harness has not yet
740
756
  // acknowledged (ADR-0062): by the id the read named, every id it stands for — equal notices
741
757
  // are said once — and what each was raised as, for `reraiseUnheard`.
742
- const boundary = new Map<string, Map<string, Array<{ id: string; raised: { notice: Notice; source?: string } }>>>();
758
+ const boundary = new Map<
759
+ string,
760
+ Map<string, Array<{ id: string; raised: { notice: LedgerBody; source?: string } }>>
761
+ >();
743
762
  const registerSurface = (iid: string) =>
744
763
  disposers.push(
745
764
  binding.table.register({
@@ -842,6 +861,8 @@ export function agentActorWith(
842
861
  instanceId: currentIid,
843
862
  agent: input.agentName,
844
863
  endpoint,
864
+ ...(sandbox === undefined ? {} : { sandbox }),
865
+ slot,
845
866
  ...(input.turnId === undefined ? {} : { turnId: input.turnId }),
846
867
  },
847
868
  delivered,
@@ -994,7 +1015,7 @@ export function agentActorWith(
994
1015
  // reserved for this Turn until the Harness acknowledges the append. A guard kill's audience
995
1016
  // leaves out the conversations its `bash` answer told, which only the pod's list says — so when
996
1017
  // one is among them, the list is read first, and a read that could not tell takes no guard kill.
997
- const readBoundary = async (iid: string): Promise<Array<{ id: string; notice: Notice }>> => {
1018
+ const readBoundary = async (iid: string): Promise<Array<{ id: string; notice: LedgerBody }>> => {
998
1019
  if (stopped || iid !== currentIid || binding.takeNotices === undefined) return [];
999
1020
  const scope: NoticeScope = { ...noticeScope, taker: iid };
1000
1021
  if (noticeWorkspace !== undefined) {
@@ -1016,7 +1037,7 @@ export function agentActorWith(
1016
1037
  const taken = binding.takeNotices(scope);
1017
1038
  const held = boundary.get(iid) ?? new Map();
1018
1039
  const said = new Map<string, string>();
1019
- const out: Array<{ id: string; notice: Notice }> = [];
1040
+ const out: Array<{ id: string; notice: LedgerBody }> = [];
1020
1041
  taken.ids.forEach((id, i) => {
1021
1042
  const raised = taken.raised?.[i] ?? { notice: taken.notices[i]! };
1022
1043
  const key = JSON.stringify(raised.notice);
@@ -1078,7 +1099,7 @@ export function agentActorWith(
1078
1099
  // the Harness last read its surface, `heard` before that — and whether an unheard one carried
1079
1100
  // the Turn's task. Collected across the Turn, so a re-admission onto a lost conversation tells
1080
1101
  // the Agent all of them again.
1081
- type Raised = { notice: Notice; source?: string };
1102
+ type Raised = { notice: LedgerBody; source?: string };
1082
1103
  // `fresh`: a fresh Turn's "this conversation is new", which rides an admission as `extra` and so
1083
1104
  // is kept in no ledger — an unread one is carried again by the next re-admission.
1084
1105
  const carriedBy = new Map<string, { heard: Raised[]; unheard: Raised[]; task: boolean; fresh: Notice[] }>();
@@ -1125,7 +1146,7 @@ export function agentActorWith(
1125
1146
  : unsaid.length > 0
1126
1147
  ? { workspace: noticeWorkspace, taker, only: unsaid }
1127
1148
  : undefined;
1128
- const none = { ids: [] as string[], notices: [] as Notice[], raised: [] as Raised[] };
1149
+ const none = { ids: [] as string[], notices: [] as LedgerBody[], raised: [] as Raised[] };
1129
1150
  const restored =
1130
1151
  opts.include && opts.include.length > 0
1131
1152
  ? (binding.takeNotices?.({ ...noticeScope, taker, only: opts.include }) ?? none)
@@ -1143,12 +1164,16 @@ export function agentActorWith(
1143
1164
  // cut pick never got (ADR-0031), whose one path to the model is this admission. One "this
1144
1165
  // conversation is new" is enough, whichever path brought it.
1145
1166
  let fresh = false;
1146
- const notices = [...taken.notices, ...(opts.extra ?? [])].filter((n) => {
1167
+ const bodies = [...taken.notices, ...(opts.extra ?? [])].filter((n) => {
1147
1168
  if (n.kind !== "conversation-new") return true;
1148
1169
  if (fresh) return false;
1149
1170
  fresh = true;
1150
1171
  return true;
1151
1172
  });
1173
+ // The two kinds of body ride the admission apart (ADR-0062): a notice is a fact, and a
1174
+ // Steering message an author's text, which the Harness frames by its author.
1175
+ const notices = bodies.filter((n): n is Notice => n.kind !== "steering");
1176
+ const steering = bodies.filter((n): n is SteeringMessage => n.kind === "steering");
1152
1177
  // `served` is per Instance ID, and a nudge or a wake reuses the Turn's: it must be read again
1153
1178
  // before this admission counts as heard (`reraiseUnheard`). An admission that fails puts the
1154
1179
  // mark back — what an earlier one carried was heard.
@@ -1161,6 +1186,7 @@ export function agentActorWith(
1161
1186
  slot,
1162
1187
  signal: controller.signal,
1163
1188
  ...(notices.length ? { notices } : {}),
1189
+ ...(steering.length ? { steering } : {}),
1164
1190
  ...(opts.kept ? { kept: true } : {}),
1165
1191
  });
1166
1192
  } catch (err) {
@@ -1213,12 +1239,12 @@ export function agentActorWith(
1213
1239
  if (gone) bucket.heard = [];
1214
1240
  if (!read) bucket.unheard = [];
1215
1241
  for (const { notice, source } of again) {
1216
- const to = notice.scope === "conversation" ? conversation : noticeWorkspace;
1242
+ const to = notice.scope === "conversation" ? conversation : notice.scope === "slot" ? slot : noticeWorkspace;
1217
1243
  if (to === undefined) continue;
1218
1244
  // A Workspace notice is pending again for the conversation that carried it, which did not
1219
1245
  // hear it; the others it reached keep theirs.
1220
1246
  if (binding.restoreNotice) binding.restoreNotice(notice, to, source, iid);
1221
- else binding.raiseNotice?.(notice, to);
1247
+ else if (notice.kind !== "steering") binding.raiseNotice?.(notice, to);
1222
1248
  if (source !== undefined) restored.push(source);
1223
1249
  }
1224
1250
  }
package/src/agent.ts CHANGED
@@ -58,6 +58,44 @@ export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhi
58
58
  * tells what each value gives. */
59
59
  export type WorkspaceAccess = "write" | "read" | "none";
60
60
 
61
+ // One entry of an Agent's `mcp` list (ADR-0079): a server of the config's `mcp` block, by its name,
62
+ // and the allowlist. An object, so that `resources` can join `tools` later. The TYPE cannot say
63
+ // which servers take a list: that is the config's (remote or stdio), so `jr2 up` says it.
64
+ /**
65
+ * One MCP server that an Agent uses, and the tools that it may call there.
66
+ *
67
+ * - `server` is a name of the `mcp` block of `jr2.config.ts`. `jr2 up` refuses a name that the
68
+ * block does not declare, and prints the `customize()` line that binds the Agent to one it does.
69
+ * - `tools` is the allowlist. A remote server needs it: a list of tool names, or `"*"` for every
70
+ * tool. The Harness offers and runs only those tools. When Workspace code in the Agent's Sandbox
71
+ * can spend the server's secret, `jr2 up` takes only `"*"`, because a list would then not be a
72
+ * limit. A stdio server takes no `tools`: the Agent gets every tool of the server.
73
+ *
74
+ * The model reads each tool as `mcp__<server>__<tool>`. A tool name in the list must keep that name
75
+ * within `[A-Za-z0-9_-]` and 128 characters.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * import { agent } from "@jr2/orchestrator";
80
+ *
81
+ * export const triage = agent({
82
+ * model: "anthropic/claude-haiku-5-5",
83
+ * instructions: "You read the ticket and post a summary to the channel.",
84
+ * workspace: "none",
85
+ * mcp: [{ server: "slack-acme", tools: ["post_message", "read_channel"] }],
86
+ * });
87
+ * ```
88
+ *
89
+ * @see docs/reference/decisions/0079-an-agent-holds-mcp-tools-a-machine-calls-them-as-an-effect-and-the-machine-is-the-approval.md
90
+ */
91
+ export type AgentMcpServer = {
92
+ /** A server name of the `mcp` block of `jr2.config.ts`. */
93
+ server: string;
94
+ /** The allowlist: tool names of the server, or `"*"` for every tool. Required for a remote
95
+ * server; absent for a stdio server. */
96
+ tools?: readonly string[] | "*";
97
+ };
98
+
61
99
  // The plain-data Agent definition (ADR-0018): IDENTITY plus one default. A Turn's Frame — what it
62
100
  // is about and where it works — is not here and cannot be (ADR-0057): a Worktree exists only
63
101
  // once a run has cut it, so no definition written before the run could name one.
@@ -130,6 +168,18 @@ export type AgentDefinition = {
130
168
  * - `"none"`: no Working tools. The Agent only reads its prompt and picks from its Menu. Its Turn
131
169
  * runs on the Instance Harness, not in a Sandbox, so it needs no `workspace()` around it. */
132
170
  workspace?: WorkspaceAccess;
171
+ // Reach for tools (ADR-0079): names only. The url and the secret are the Instance's, in the
172
+ // config's `mcp` block, so a packaged Machine ships no credential and a composer rebinds the list.
173
+ /** The MCP servers whose tools the Agent gets, each with its allowlist: see
174
+ * {@link AgentMcpServer}. The tools join the Agent's tools, after its Working tools and before
175
+ * its Menu. A call to one is not a pick, and the Turn goes on after it. Default: none. A composer
176
+ * replaces the whole list with `customize(machine, { agents: { <slot>: { mcp: [...] } } })`. */
177
+ mcp?: readonly AgentMcpServer[];
178
+ // Read by the Orchestrator alone (ADR-0002): the admission strips it, and the model never reads it.
179
+ /** May a Caller send this Agent a Steering message? Default: `true`. With `false`,
180
+ * `POST /runs/:runId/steering` and `jr2 steer` refuse it, and `GET /runs/:runId/agents` says
181
+ * `steerable: false`. The Machine can still steer the Agent with the `steer` action. */
182
+ steerable?: boolean;
133
183
  };
134
184
 
135
185
  // The Agent as an author DECLARES it (ADR-0054): the definition, except that `model` may be Open —