@jr2/orchestrator 0.4.1 → 0.6.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 (361) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +478 -0
  10. package/docs/concepts/architecture.md +243 -0
  11. package/docs/concepts/charts.md +146 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +257 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +658 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +298 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +306 -0
  20. package/docs/concepts/the-menu.md +381 -0
  21. package/docs/concepts/workspaces.md +756 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +383 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +993 -0
  27. package/docs/get-started/install.md +130 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +308 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +224 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/cut-a-worktree.md +560 -0
  34. package/docs/guides/fix-a-failed-converge.md +361 -0
  35. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  36. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  37. package/docs/guides/let-an-agent-write-a-chart.md +230 -0
  38. package/docs/guides/look-inside-a-sandbox.md +177 -0
  39. package/docs/guides/mirror-the-kit-images.md +176 -0
  40. package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -0
  41. package/docs/guides/open-the-console.md +91 -0
  42. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  43. package/docs/guides/push-and-sign-a-branch.md +532 -0
  44. package/docs/guides/run-a-chart-by-name.md +270 -0
  45. package/docs/guides/run-a-command-or-call-a-url.md +587 -0
  46. package/docs/guides/run-one-worker-per-item.md +322 -0
  47. package/docs/guides/set-an-agents-access-and-dials.md +420 -0
  48. package/docs/guides/size-a-workspace.md +217 -0
  49. package/docs/guides/start-a-run-from-a-run.md +237 -0
  50. package/docs/guides/start-a-run.md +207 -0
  51. package/docs/guides/upgrade-the-kit-version.md +240 -0
  52. package/docs/guides/use-a-hosted-provider.md +214 -0
  53. package/docs/guides/use-a-local-model.md +313 -0
  54. package/docs/guides/watch-a-run.md +349 -0
  55. package/docs/guides/write-a-workflow.md +318 -0
  56. package/docs/index.md +44 -0
  57. package/docs/llms.txt +237 -0
  58. package/docs/reference/authoring-surface/agent.md +151 -0
  59. package/docs/reference/authoring-surface/answer.md +156 -0
  60. package/docs/reference/authoring-surface/arg.md +82 -0
  61. package/docs/reference/authoring-surface/basic.md +62 -0
  62. package/docs/reference/authoring-surface/bearer.md +53 -0
  63. package/docs/reference/authoring-surface/branchname.md +15 -0
  64. package/docs/reference/authoring-surface/chartschema.md +23 -0
  65. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  66. package/docs/reference/authoring-surface/command.md +206 -0
  67. package/docs/reference/authoring-surface/customize.md +64 -0
  68. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  69. package/docs/reference/authoring-surface/defineevent.md +114 -0
  70. package/docs/reference/authoring-surface/dispatch.md +126 -0
  71. package/docs/reference/authoring-surface/fail.md +96 -0
  72. package/docs/reference/authoring-surface/file.md +142 -0
  73. package/docs/reference/authoring-surface/frompick.md +277 -0
  74. package/docs/reference/authoring-surface/http.md +259 -0
  75. package/docs/reference/authoring-surface/isfailure.md +58 -0
  76. package/docs/reference/authoring-surface/isready.md +14 -0
  77. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  78. package/docs/reference/authoring-surface/open.md +105 -0
  79. package/docs/reference/authoring-surface/openbody.md +86 -0
  80. package/docs/reference/authoring-surface/paramsof.md +143 -0
  81. package/docs/reference/authoring-surface/pool.md +186 -0
  82. package/docs/reference/authoring-surface/push.md +130 -0
  83. package/docs/reference/authoring-surface/readyof.md +21 -0
  84. package/docs/reference/authoring-surface/secret.md +139 -0
  85. package/docs/reference/authoring-surface/sentby.md +83 -0
  86. package/docs/reference/authoring-surface/source.md +51 -0
  87. package/docs/reference/authoring-surface/text.md +62 -0
  88. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  89. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  90. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  91. package/docs/reference/authoring-surface/type-agentslots.md +15 -0
  92. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  93. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  94. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  95. package/docs/reference/authoring-surface/type-arg.md +19 -0
  96. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  97. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  98. package/docs/reference/authoring-surface/type-binding.md +61 -0
  99. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  100. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  101. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  102. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  103. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  104. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  105. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  106. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  107. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  108. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  109. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  110. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  111. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  112. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  113. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  114. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  115. package/docs/reference/authoring-surface/type-childat.md +12 -0
  116. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  117. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  118. package/docs/reference/authoring-surface/type-commandinput.md +20 -0
  119. package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
  120. package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
  121. package/docs/reference/authoring-surface/type-customize.md +111 -0
  122. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  123. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  124. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  125. package/docs/reference/authoring-surface/type-dispatchoutput.md +72 -0
  126. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  127. package/docs/reference/authoring-surface/type-duration.md +15 -0
  128. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  129. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  130. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  131. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  132. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  133. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  134. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  135. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  136. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  137. package/docs/reference/authoring-surface/type-failure.md +19 -0
  138. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  139. package/docs/reference/authoring-surface/type-filebody.md +37 -0
  140. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  141. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  142. package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
  143. package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
  144. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  145. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  146. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  147. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +95 -0
  149. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  150. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  151. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  152. package/docs/reference/authoring-surface/type-lends.md +38 -0
  153. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  154. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  155. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  156. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  157. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  158. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
  159. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  160. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  161. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  162. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  163. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  164. package/docs/reference/authoring-surface/type-opencommandinput.md +22 -0
  165. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  166. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  167. package/docs/reference/authoring-surface/type-openof.md +12 -0
  168. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  169. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  170. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +26 -0
  171. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
  172. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  173. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  174. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  175. package/docs/reference/authoring-surface/type-pushinput.md +34 -0
  176. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  177. package/docs/reference/authoring-surface/type-pushoutput.md +149 -0
  178. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  179. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  180. package/docs/reference/authoring-surface/type-reached.md +12 -0
  181. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  182. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  183. package/docs/reference/authoring-surface/type-sandboxoptions.md +84 -0
  184. package/docs/reference/authoring-surface/type-secret.md +25 -0
  185. package/docs/reference/authoring-surface/type-sender.md +19 -0
  186. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  187. package/docs/reference/authoring-surface/type-size.md +85 -0
  188. package/docs/reference/authoring-surface/type-slothandles.md +24 -0
  189. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  190. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  191. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  192. package/docs/reference/authoring-surface/type-text.md +19 -0
  193. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  194. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  195. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  196. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  197. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  198. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  199. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  200. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  201. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  202. package/docs/reference/authoring-surface/type-workspaced.md +115 -0
  203. package/docs/reference/authoring-surface/type-workspacehandles.md +22 -0
  204. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  205. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  206. package/docs/reference/authoring-surface/type-workspaceoptions.md +27 -0
  207. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  208. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  209. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  210. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  211. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  212. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  213. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  214. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  215. package/docs/reference/authoring-surface/workspace.md +287 -0
  216. package/docs/reference/authoring-surface/worktree.md +71 -0
  217. package/docs/reference/authoring-surface.md +217 -0
  218. package/docs/reference/cli.md +433 -0
  219. package/docs/reference/config.md +765 -0
  220. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
  221. package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
  222. package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
  223. package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
  224. package/docs/reference/decisions/0006-agent-control-surface.md +50 -0
  225. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  226. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  227. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  228. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  229. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  230. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  231. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +175 -0
  232. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  233. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +271 -0
  234. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
  235. package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -0
  236. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  237. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +287 -0
  238. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  239. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +101 -0
  240. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  241. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +175 -0
  242. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -0
  243. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  244. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  245. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +245 -0
  246. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -0
  247. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  248. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  249. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +193 -0
  250. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  251. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +126 -0
  252. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  253. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  254. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  255. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  256. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  257. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  258. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  259. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  260. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  261. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  262. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  263. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  264. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  265. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  266. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  267. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  268. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +238 -0
  269. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
  270. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -0
  271. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  272. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  273. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  274. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  275. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +108 -0
  276. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -0
  277. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  278. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  279. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +239 -0
  280. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -0
  281. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  282. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  283. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +552 -0
  284. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
  285. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -0
  286. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  287. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +334 -0
  288. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  289. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  290. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  291. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  292. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
  293. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
  294. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  295. package/docs/reference/decisions.md +86 -0
  296. package/docs/reference/glossary.md +687 -0
  297. package/docs/reference/http-api.md +1386 -0
  298. package/docs/reference/machines.md +189 -0
  299. package/docs/reference/mechanism-events.md +72 -0
  300. package/docs/why.md +207 -0
  301. package/package.json +5 -3
  302. package/src/actor.ts +694 -106
  303. package/src/agent.ts +114 -38
  304. package/src/ambient.ts +3 -4
  305. package/src/assembly-checks.ts +189 -7
  306. package/src/cause.ts +234 -0
  307. package/src/chart.ts +345 -46
  308. package/src/charts.ts +43 -8
  309. package/src/config.ts +440 -178
  310. package/src/custodian.lua +17 -5
  311. package/src/custodian.ts +325 -99
  312. package/src/customize.ts +199 -49
  313. package/src/dispatch-effect.ts +945 -0
  314. package/src/door-compat.ts +217 -0
  315. package/src/durability.ts +11 -4
  316. package/src/effect-checks.ts +50 -3
  317. package/src/effect.ts +641 -128
  318. package/src/effector-wire.ts +165 -13
  319. package/src/fail.ts +222 -0
  320. package/src/harness-client.ts +587 -50
  321. package/src/harness-env.ts +33 -0
  322. package/src/held-secrets.ts +125 -16
  323. package/src/holds.ts +3 -0
  324. package/src/http-effect.ts +556 -58
  325. package/src/http.ts +480 -30
  326. package/src/index.ts +74 -82
  327. package/src/instance.ts +68 -8
  328. package/src/internal.ts +85 -0
  329. package/src/kube-client.ts +6 -3
  330. package/src/machine-doc.ts +24 -7
  331. package/src/mechanism-routes.ts +168 -0
  332. package/src/model-keys.generated.ts +53 -0
  333. package/src/model-keys.ts +42 -58
  334. package/src/names.ts +19 -6
  335. package/src/notices.ts +483 -41
  336. package/src/open-body.ts +242 -40
  337. package/src/open-effect.ts +81 -8
  338. package/src/open.ts +90 -6
  339. package/src/parts.ts +213 -30
  340. package/src/party.ts +101 -2
  341. package/src/pick.ts +497 -11
  342. package/src/pool.ts +282 -50
  343. package/src/registration.ts +133 -12
  344. package/src/repo-identity.ts +7 -3
  345. package/src/repos.ts +22 -3
  346. package/src/run-host.ts +665 -45
  347. package/src/run-output.ts +38 -0
  348. package/src/sandbox-effect.ts +457 -71
  349. package/src/sandbox-kube.ts +66 -17
  350. package/src/secret-placement.ts +59 -17
  351. package/src/server.ts +3 -0
  352. package/src/setup.ts +325 -62
  353. package/src/size.ts +121 -9
  354. package/src/snapshot-store.ts +54 -10
  355. package/src/stub-harness.ts +44 -16
  356. package/src/timers.ts +14 -1
  357. package/src/tokens.ts +107 -32
  358. package/src/vocabulary.ts +88 -14
  359. package/src/wire.ts +100 -26
  360. package/src/workspace.ts +771 -238
  361. package/src/worktree.ts +249 -0
@@ -0,0 +1,142 @@
1
+ ---
2
+ title: file
3
+ description: "Make a Worktree file the body of an `http` Effect: `body: file(\"dist/report.pdf\")`."
4
+ ---
5
+
6
+ # `file`
7
+
8
+ Function, in `@jr2/orchestrator/src/http-effect.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
9
+
10
+ ```ts
11
+ function file<S extends z.ZodType | undefined = undefined>(path: FromInput<S, string>, options: {
12
+ segments?: FromInput<S, readonly string[]>;
13
+ contentType?: string;
14
+ } = {}): FileBody<S>
15
+ ```
16
+
17
+ Make a Worktree file the body of an `http` Effect: `body: file("dist/report.pdf")`. The Effect
18
+ then runs in the Sandbox Effector of the Workspace whose body invokes it. Under a Workspace with
19
+ Repo Slots, the invoke's input names the Worktree: `input: { worktree: "/work/app/fix" }`. It is a
20
+ Worktree that a cut of this run made. That Effector opens the file in that Worktree and sends it.
21
+ In a Workspace with no Repo Slot, the input names no `worktree`, and the path is relative to
22
+ `/work`, the folder that its steps share. Use it with `PUT`, `POST` or `PATCH`. `path` and
23
+ `segments` can be functions of the input of the Effect.
24
+
25
+ Some inputs, paths and files give the output `refused`, and then nothing is sent. The `worktree`
26
+ has no cut in this Sandbox: `no cut made <path> in this Sandbox: cut it with worktree(); nothing
27
+ was sent`. Or the input names a `worktree` in a Workspace with no Repo Slot. Or the path has a
28
+ symlink in it, has `..`, or is absolute. Or the file is a FIFO, a directory, or a file with more
29
+ than one link.
30
+
31
+ It refuses, when you call it:
32
+ - a path that is not a string or a function: `file(path): the path is a string, or a function of
33
+ the Effect's input that returns one`
34
+
35
+ And when `http` takes the definition:
36
+ - a method other than `PUT`, `POST` and `PATCH`: `http({ method: "<method>", body: file(...) }):
37
+ a file body is sent with PUT, POST, PATCH (ADR-0068)`
38
+ - a `request` beside it: ``http({ body: file(...), request }): with a file body the run's part
39
+ is file()'s — its path, from the input if it must be, and its `segments` — so write no
40
+ `request` (ADR-0068)``
41
+ - a `content-type` header and `contentType`: `http({ headers, body: file(path, { contentType })
42
+ }): "content-type" is set by file()'s contentType — write one of them (ADR-0067)`
43
+
44
+ And at `jr2 up`, an Effect that no `workspace()` invokes: `workflow "<workflow>": the http Effect
45
+ "<slot>" sends a Worktree file as its body, and no workspace() invokes it — outside a Workspace
46
+ there is no Worktree to read; invoke it from a workspace()'s body, or send a json or text body
47
+ (ADR-0068)`.
48
+
49
+ And when it starts, under a Workspace with Repo Slots, an input with no `worktree`: ``http
50
+ "<slot>" reads a Worktree file, under a Workspace with Repo Slots, and its input names no
51
+ `worktree` ``.
52
+
53
+ **Parameters**
54
+
55
+ - `path` ([`FromInput`](type-frominput.md)): The file, relative to the Worktree that `worktree` of the input names, or to
56
+ `/work` in a Workspace with no Repo Slot: a string, or a function of the input of the Effect
57
+ that gives one.
58
+ - `options`: Optional. Each field says what it does.
59
+
60
+ - `segments` (optional): `FromInput<S, readonly string[]>`
61
+
62
+ Path segments that jr2 adds to the end of the url, as `path` does in `request` for a json or
63
+ text body. A list of strings, or a function of the input of the Effect that gives one.
64
+ - `contentType` (optional): `string`
65
+
66
+ The content type of the body. Default `application/octet-stream`. Do not write it beside a
67
+ `content-type` header.
68
+
69
+ **Returns**: The `body` of an `http` Effect.
70
+
71
+ **Example**
72
+
73
+ ```ts
74
+ import {
75
+ bearer,
76
+ command,
77
+ fail,
78
+ file,
79
+ http,
80
+ isReady,
81
+ jr2Setup,
82
+ secret,
83
+ workspace,
84
+ worktree,
85
+ type Workspaced,
86
+ } from "@jr2/orchestrator";
87
+
88
+ type Input = Workspaced<{}, "app">;
89
+
90
+ const reportTree = (context: Input) => `${context.workspace.repos.app}/report` as const;
91
+
92
+ const body = jr2Setup({
93
+ types: {} as { context: Input; input: Input },
94
+ actors: {
95
+ cut: worktree(),
96
+ build: command(["npm", "run", "report"]),
97
+ upload: http({
98
+ method: "PUT",
99
+ url: "https://files.example.com/reports",
100
+ auth: bearer(secret("files")),
101
+ body: file("dist/report.pdf", {
102
+ segments: ["report.pdf"],
103
+ contentType: "application/pdf",
104
+ }),
105
+ }),
106
+ fail: fail(),
107
+ },
108
+ }).createMachine({
109
+ id: "report",
110
+ context: ({ input }) => input,
111
+ on: { "workspace.lost": ".lost" },
112
+ initial: "cutting",
113
+ states: {
114
+ cutting: {
115
+ invoke: {
116
+ src: "cut",
117
+ input: ({ context }) => ({ path: reportTree(context), branch: "report" }),
118
+ onDone: [{ guard: ({ event }) => isReady(event.output), target: "building" }, { target: "notCut" }],
119
+ },
120
+ },
121
+ building: {
122
+ invoke: { src: "build", input: ({ context }) => ({ worktree: reportTree(context) }), onDone: "uploading" },
123
+ },
124
+ uploading: {
125
+ invoke: { src: "upload", input: ({ context }) => ({ worktree: reportTree(context) }), onDone: "done" },
126
+ },
127
+ done: { type: "final" },
128
+ notCut: { invoke: { src: "fail", input: { reason: "the Worktree was not cut" } } },
129
+ lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
130
+ },
131
+ });
132
+
133
+ export const machine = workspace(body, {
134
+ repos: { app: { url: "https://github.com/you/app.git" } },
135
+ });
136
+ ```
137
+
138
+ **See also**
139
+
140
+ - [Run a command or call a URL with an Effect](../../guides/run-a-command-or-call-a-url.md)
141
+ - [Effects](../../concepts/effects.md)
142
+ - [ADR-0067: An Effect is an actor slot, and runs at most once unless marked idempotent](../decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
@@ -0,0 +1,277 @@
1
+ ---
2
+ title: fromPick
3
+ description: "Make the `input` of the invoke of a state that a pick enters: the params of the pick go to the input of the invoked actor by name."
4
+ ---
5
+
6
+ # `fromPick`
7
+
8
+ Function, in `@jr2/orchestrator/src/pick.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
9
+
10
+ ## Overload 1
11
+
12
+ ```ts
13
+ function fromPick<
14
+ N extends string,
15
+ I extends z.ZodObject,
16
+ C,
17
+ E extends EventObject,
18
+ >(
19
+ def: EventDef<N, I>,
20
+ ): (args: { context: C; event: E; self: AnyActorRef }) => z.infer<I>
21
+ ```
22
+
23
+ Make the `input` of the invoke of a state that a pick enters: the params of the pick go to the
24
+ input of the invoked actor by name. With `fill`, the Machine adds the keys that the Agent must
25
+ not choose. So one expression shows the security boundary: the pick is what the Agent gives, and
26
+ `fill` is what the Machine adds.
27
+
28
+ TypeScript checks the params and the keys of `fill` together against the input type of the
29
+ invoked actor. It finds a missing key or a key of the wrong type, but it accepts an extra key.
30
+
31
+ So `createMachine` refuses:
32
+ - a param that is no key of the input of the Effect, and that nothing else reads: ``machine
33
+ "<id>": pick "<pick>" enters state "<state>" (Effect "<slot>") with fromPick: "<param>" is no
34
+ key of the Effect's input (<keys>), and nothing else reads it — the Agent supplies it and it
35
+ reaches nothing; name an argv slot for it, read it in `fill`, store it with assign, or drop it
36
+ from the def``
37
+ - a key that `fill` sets and that is also a param: ``machine "<id>": pick "<pick>" enters state
38
+ "<state>" (Effect "<slot>"): `fill` sets "<param>", which is also a param of the pick — the
39
+ Machine's value wins and the Agent's is dropped; rename one, or drop it from the def``
40
+ - a `fromPick` in a state that another event enters: `machine "<id>": state "<state>" (Effect
41
+ "<slot>") reads the params of pick "<pick>" but is entered on "<event>" — that event does not
42
+ carry them`
43
+
44
+ The input of an Open argv is one string for each key, so TypeScript checks no key for it. A key
45
+ that the bound argv names and the input does not give stops the Effect when it starts.
46
+
47
+ The state that the pick enters has one of two places:
48
+ - A child state of the Agent's state, as in the first example. The Turn stays open, and the
49
+ pick is outstanding until the Effect ends. Use this shape when the Agent must see the result.
50
+ The Agent reads the Effect's output as the answer only when the route after the Effect stays
51
+ in the Agent's state, as `onDone: "ready"` does. Then the Agent can pick again. A route that
52
+ leaves the Agent's state ends the Turn when the Effect ends, and no Agent reads the output.
53
+ - A sibling state of the Agent's state, as in the second example. The pick leaves the Agent's
54
+ state, so the Turn ends before the Effect runs, and the Agent does not see the output. Use
55
+ this shape for a pick that ends the work of the Agent.
56
+
57
+ **Parameters**
58
+
59
+ - `def` ([`EventDef`](type-eventdef.md)): The pick, as `defineEvent` made it.
60
+
61
+ **Returns**: An `input` mapper for the `invoke` of the state.
62
+
63
+ **Example**
64
+
65
+ ```ts
66
+ import { z } from "zod";
67
+ import { agent, defineEvent, fail, fromPick, http, jr2Setup } from "@jr2/orchestrator";
68
+
69
+ const postNote = defineEvent({
70
+ name: "post_note",
71
+ description: "Post a note to the team channel.",
72
+ input: z.object({ text: z.string() }),
73
+ });
74
+
75
+ const finish = defineEvent({
76
+ name: "finish",
77
+ description: "The note is posted. This ends your work.",
78
+ input: z.object({}),
79
+ });
80
+
81
+ export const machine = jr2Setup({
82
+ types: {} as { context: {}; input: {} },
83
+ events: [postNote, finish],
84
+ actors: {
85
+ writer: agent({
86
+ model: "anthropic/claude-haiku-5-5",
87
+ instructions: "You write one short note for the team.",
88
+ workspace: "none",
89
+ }),
90
+ note: http({
91
+ method: "POST",
92
+ url: "https://hooks.example.com/notes",
93
+ input: z.object({ text: z.string() }),
94
+ request: ({ text }) => ({ json: { text } }),
95
+ }),
96
+ fail: fail(),
97
+ },
98
+ }).createMachine({
99
+ id: "note",
100
+ on: { "agent.fault": ".failed" },
101
+ initial: "writing",
102
+ states: {
103
+ writing: {
104
+ invoke: {
105
+ src: "writer",
106
+ input: {
107
+ prompt: "Write a note that says the release is out, post it, and check the reply.",
108
+ },
109
+ },
110
+ initial: "ready",
111
+ states: {
112
+ ready: { on: { post_note: "posting", finish: "#done" } },
113
+ posting: {
114
+ // The `text` of the pick goes to the input of `note` as it is. The route goes back
115
+ // to `ready`, in `writing`: the writer reads the output and picks again.
116
+ invoke: { src: "note", input: fromPick(postNote), onDone: "ready" },
117
+ },
118
+ },
119
+ },
120
+ done: { id: "done", type: "final" },
121
+ failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
122
+ },
123
+ });
124
+ ```
125
+
126
+ **Example**
127
+
128
+ ```ts
129
+ import { z } from "zod";
130
+ import { agent, defineEvent, fail, fromPick, http, jr2Setup } from "@jr2/orchestrator";
131
+
132
+ const postNote = defineEvent({
133
+ name: "post_note",
134
+ description: "Post the note to the team channel. This ends your work.",
135
+ input: z.object({ text: z.string() }),
136
+ });
137
+
138
+ export const machine = jr2Setup({
139
+ types: {} as { context: {}; input: {} },
140
+ events: [postNote],
141
+ actors: {
142
+ writer: agent({
143
+ model: "anthropic/claude-haiku-5-5",
144
+ instructions: "You write one short note for the team.",
145
+ workspace: "none",
146
+ }),
147
+ note: http({
148
+ method: "POST",
149
+ url: "https://hooks.example.com/notes",
150
+ input: z.object({ text: z.string() }),
151
+ request: ({ text }) => ({ json: { text } }),
152
+ }),
153
+ fail: fail(),
154
+ },
155
+ }).createMachine({
156
+ id: "note",
157
+ on: { "agent.fault": ".failed" },
158
+ initial: "writing",
159
+ states: {
160
+ // The pick leaves this state, so it ends the Turn of the writer.
161
+ writing: {
162
+ invoke: {
163
+ src: "writer",
164
+ input: { prompt: "Write a note that says the release is out, and post it." },
165
+ },
166
+ on: { post_note: "posting" },
167
+ },
168
+ // A sibling of `writing`: the Effect runs after the Turn, and no Agent reads its output.
169
+ posting: {
170
+ invoke: { src: "note", input: fromPick(postNote), onDone: "done" },
171
+ },
172
+ done: { type: "final" },
173
+ failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
174
+ },
175
+ });
176
+ ```
177
+
178
+ **See also**
179
+
180
+ - [Effects](../../concepts/effects.md)
181
+ - [Run a command or call a URL with an Effect](../../guides/run-a-command-or-call-a-url.md)
182
+ - [ADR-0067: An Effect is an actor slot, and runs at most once unless marked idempotent](../decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
183
+
184
+ ## Overload 2
185
+
186
+ ```ts
187
+ function fromPick<
188
+ N extends string,
189
+ I extends z.ZodObject,
190
+ C,
191
+ E extends EventObject,
192
+ R extends object,
193
+ >(
194
+ def: EventDef<N, I>,
195
+ fill: (args: { context: C; params: z.infer<I> }) => R,
196
+ ): (args: { context: C; event: E; self: AnyActorRef }) => z.infer<I> & R
197
+ ```
198
+
199
+ Make the `input` from the params of the pick and the keys that `fill` adds. `fromPick`
200
+ tells the rest, and what `createMachine` refuses.
201
+
202
+ **Parameters**
203
+
204
+ - `def` ([`EventDef`](type-eventdef.md)): The pick, as `defineEvent` made it.
205
+ - `fill`: Gets `{ context, params }` and gives back only the keys that the Machine adds. Do
206
+ not set a key that is also a param.
207
+
208
+ **Returns**: An `input` mapper for the `invoke` of the state.
209
+
210
+ **Example**
211
+
212
+ ```ts
213
+ import { z } from "zod";
214
+ import { agent, bearer, defineEvent, fail, fromPick, http, jr2Setup, secret } from "@jr2/orchestrator";
215
+
216
+ const postComment = defineEvent({
217
+ name: "post_comment",
218
+ description: "Post a comment on the ticket.",
219
+ input: z.object({ body: z.string() }),
220
+ });
221
+
222
+ export const machine = jr2Setup({
223
+ types: {} as { context: { ticket: string }; input: { ticket: string } },
224
+ events: [postComment],
225
+ actors: {
226
+ triager: agent({
227
+ model: "anthropic/claude-haiku-5-5",
228
+ instructions: "You triage tickets.",
229
+ workspace: "none",
230
+ }),
231
+ comment: http({
232
+ method: "POST",
233
+ url: "https://jira.example.com/rest/api/2/issue",
234
+ auth: bearer(secret("jira")),
235
+ input: z.object({ ticket: z.string(), body: z.string() }),
236
+ request: ({ ticket, body }) => ({ path: [ticket, "comment"], json: { body } }),
237
+ }),
238
+ fail: fail(),
239
+ },
240
+ }).createMachine({
241
+ id: "triage",
242
+ context: ({ input }) => input,
243
+ on: { "agent.fault": ".failed" },
244
+ initial: "triaging",
245
+ states: {
246
+ triaging: {
247
+ invoke: {
248
+ src: "triager",
249
+ input: ({ context }) => ({
250
+ prompt: `Read ticket ${context.ticket}, then post one comment on it.`,
251
+ }),
252
+ },
253
+ initial: "ready",
254
+ states: {
255
+ ready: { on: { post_comment: "posting" } },
256
+ posting: {
257
+ invoke: {
258
+ src: "comment",
259
+ // The Agent gives `body`. The Machine gives `ticket`, so the Agent cannot post on
260
+ // another ticket.
261
+ input: fromPick(postComment, ({ context }) => ({ ticket: context.ticket })),
262
+ onDone: "#done",
263
+ },
264
+ },
265
+ },
266
+ },
267
+ done: { id: "done", type: "final" },
268
+ failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
269
+ },
270
+ });
271
+ ```
272
+
273
+ **See also**
274
+
275
+ - [Effects](../../concepts/effects.md)
276
+ - [Run a command or call a URL with an Effect](../../guides/run-a-command-or-call-a-url.md)
277
+ - [ADR-0067: An Effect is an actor slot, and runs at most once unless marked idempotent](../decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
@@ -0,0 +1,259 @@
1
+ ---
2
+ title: http
3
+ description: "Make an `http` Effect: a call to a URL, with Effect secrets that the Agent never reads."
4
+ ---
5
+
6
+ # `http`
7
+
8
+ Function, in `@jr2/orchestrator/src/http-effect.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Effects.
9
+
10
+ ## Overload 1
11
+
12
+ ```ts
13
+ function http<
14
+ S extends z.ZodType | undefined = undefined,
15
+ const U extends HttpDefinition<S>["url"] = string,
16
+ const A extends HttpDefinition<S>["auth"] = undefined,
17
+ const H extends HttpDefinition<S>["headers"] = undefined,
18
+ >(
19
+ def: HttpDefinition<S> & { url: U; auth?: A; headers?: H; body: FileBody<S> },
20
+ ): EffectLogic<HttpFileInput<S>, HttpOutput> & OpenOf<HttpOpenParts<U, A, H>>
21
+ ```
22
+
23
+ Make an `http` Effect: a call to a URL, with Effect secrets that the Agent never reads. Put it
24
+ in `actors`, and invoke it by its key: `actors: { comment: http({ ... }) }`, then `invoke: {
25
+ src: "comment" }`.
26
+
27
+ It runs in the Instance Effector, which `jr2 up` deploys when a Machine has an `http` Effect.
28
+ With `body: file(...)`, it runs in the Sandbox Effector of the Workspace whose body invokes it,
29
+ and under Repo Slots its input names the Worktree in `worktree`. The Effector makes the call. The
30
+ Orchestrator holds no secret.
31
+
32
+ Every outcome is output (`HttpOutput`): `response`, `unreachable`, `refused` or `unknown`. A 4xx
33
+ or 5xx status is output too. jr2 sends the call at most one time, unless you mark it
34
+ `idempotent`. When its state exits while the call runs, jr2 stops waiting for it. The Effector
35
+ can still send it.
36
+
37
+ Each field of [`HttpDefinition`](type-httpdefinition.md) tells what it refuses. `createMachine` also refuses an
38
+ Effect written directly in an `invoke`: `machine "<id>": state "<state>" invokes an Effect
39
+ inline — a Part is a key of actors, so it has a name that the ledger, the report and
40
+ customize() share: actors: { <name>: http(...) }, then invoke: { src: "<name>" }`.
41
+
42
+ **Parameters**
43
+
44
+ - `def`: The definition. Each field tells what it does.
45
+
46
+ - `method`: [`HttpMethod`](type-httpmethod.md)
47
+
48
+ The HTTP method: `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` or `OPTIONS`. It refuses
49
+ another: `http({ method: "<method>" }): the method is one of GET, HEAD, POST, PUT, PATCH,
50
+ DELETE, OPTIONS`.
51
+ - `url`: `string | Text | typeof open`
52
+
53
+ The url: `http://` or `https://`, then a literal host. No input, param or Effect secret can
54
+ change where the call goes. An Effect secret can be only in the path:
55
+ `` text`https://api.telegram.org/bot${secret("tg")}/sendMessage` ``.
56
+
57
+ Or `open`: a packaged Machine that cannot know the host leaves the url Open, and the composer
58
+ binds it one time with `customize(machine, { effects: { <slot>: { url } } })`.
59
+
60
+ It refuses:
61
+ - a scheme or host that is not literal: `` http({ url }): the url is an http:// or https:// url
62
+ whose scheme and host are literal — a secret may sit only in its path, after a "/":
63
+ text`https://api.example.com/bot${secret("tg")}/send` (ADR-0068) ``
64
+ - an Effect secret after `?` or `#`: `` http({ url }): secret("<name>") sits in the url's query
65
+ or fragment — a secret may sit only in its path; send it in `auth` or a header instead:
66
+ headers: { "x-api-key": text`${secret("...")}` } (ADR-0068) ``
67
+ - a host that is not a host: `http({ url }): "<scheme>://<host>" is not a host`
68
+ - a user name or password in the url: ``http({ url }): the url carries userinfo — use `auth` ``
69
+ - `headers` (optional): `Readonly<Record<string, string | Text>>`
70
+
71
+ Headers that are the same for each run. Each name is lowercase. A value is a string, or a
72
+ `text` with an Effect secret.
73
+
74
+ It refuses:
75
+ - a name that is not lowercase, or that frames or routes the request (`host`,
76
+ `content-length`, `transfer-encoding`, `connection`, `upgrade`, `te`, `trailer`,
77
+ `keep-alive`, `proxy-*`): `http({ headers }): "<name>" is not a header an Effect sets — a
78
+ lowercase name that does not frame or route the request (ADR-0068)`
79
+ - an `authorization` header beside `auth`: ``http({ headers }): "authorization" is set by
80
+ `auth` — write one of them``
81
+ - `auth` (optional): `{ readonly bearer: Secret; } | { readonly basic: { user: Text; password: Text; }; } | Text`
82
+
83
+ The `Authorization` header: `bearer(secret("x"))`, `basic(user, password)`, or a `text` that
84
+ is the whole value.
85
+ - `input` (optional): `S`
86
+
87
+ The zod schema of the input of the Effect: what the `input` of the `invoke`, or `fromPick`,
88
+ gives it. jr2 parses the input with it before the call. When it starts, input that does not
89
+ agree with it makes the Effect fail (its `onError` route): `http "<slot>": its input does not
90
+ match the definition's input schema — <path>: <message>`, one `<path>: <message>` for each
91
+ problem, joined by `; `.
92
+ - `request` (optional): `(input: S extends z.ZodType ? z.infer<S> : void) => HttpRequestParts`
93
+
94
+ A function that makes the part of the request that changes for each run, from the input:
95
+ `path` segments, and a `json` or `text` body. It cannot change the host, a header or an
96
+ Effect secret. Do not write it beside `body`.
97
+ - `body`: `FileBody<S>`
98
+
99
+ A Worktree file as the body: `file(path, { segments?, contentType? })`. The Effect then
100
+ runs in the Sandbox Effector of its Workspace. Under a Workspace with Repo Slots, the invoke's
101
+ input names a Worktree that a cut of this run made, in `worktree`; with none, it refuses when
102
+ it starts: ``http "<slot>" reads a Worktree file, under a Workspace with Repo Slots, and its
103
+ input names no `worktree` ``. Do not write `request` beside it: the `segments`
104
+ of `file` are the path. It refuses another body: ``http({ body }): a body is file(path, {
105
+ segments?, contentType? }) — json and text come from `request` ``.
106
+ - `timeout` (optional): [`Duration`](type-duration.md)
107
+
108
+ How long jr2 waits for the answer: a number and a unit, such as `"30s"` or `"2m"`. Default
109
+ `"30s"`. With no answer in that time, the output is `unknown`. It refuses a value that is not
110
+ a positive duration: `http: timeout "<timeout>" is not a positive duration (like "30s",
111
+ "2m")`.
112
+ - `maxBody` (optional): `number`
113
+
114
+ The largest number of bytes of a text response body that the output keeps. Default 65536.
115
+ When jr2 cuts the body, `truncated` is `true`. It refuses a value that is not a positive whole
116
+ number: `http({ maxBody }): a positive number of bytes`.
117
+ - `idempotent` (optional): `boolean`
118
+
119
+ `true` when it is safe to send the call two times: it has its own idempotency key, or it only
120
+ reads. Default `false`. After an Orchestrator restart, jr2 cannot always tell if the call went
121
+ out. Then it sends an idempotent call again, and gives any other call the output `unknown`.
122
+
123
+ **Returns**: An Effect, for `actors`.
124
+
125
+ **Example**
126
+
127
+ ```ts
128
+ import { z } from "zod";
129
+ import { bearer, http, jr2Setup, secret } from "@jr2/orchestrator";
130
+
131
+ const comment = http({
132
+ method: "POST",
133
+ url: "https://jira.example.com/rest/api/2/issue",
134
+ auth: bearer(secret("jira")),
135
+ input: z.object({ key: z.string(), body: z.string() }),
136
+ request: ({ key, body }) => ({ path: [key, "comment"], json: { body } }),
137
+ });
138
+
139
+ export const machine = jr2Setup({
140
+ types: {} as { context: { key: string }; input: { key: string } },
141
+ actors: { comment },
142
+ }).createMachine({
143
+ id: "comment",
144
+ context: ({ input }) => input,
145
+ initial: "commenting",
146
+ states: {
147
+ commenting: {
148
+ invoke: {
149
+ src: "comment",
150
+ input: ({ context }) => ({ key: context.key, body: "The build passed." }),
151
+ onDone: "done",
152
+ },
153
+ },
154
+ done: { type: "final" },
155
+ },
156
+ });
157
+ ```
158
+
159
+ **See also**
160
+
161
+ - [Effects](../../concepts/effects.md)
162
+ - [Run a command or call a URL with an Effect](../../guides/run-a-command-or-call-a-url.md)
163
+ - [Secrets and trust](../../concepts/secrets-and-trust.md)
164
+ - [ADR-0068: An Effector holds an Effect's secrets and signs its wire](../decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md)
165
+ - [ADR-0067: An Effect is an actor slot, and runs at most once unless marked idempotent](../decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md)
166
+
167
+ ## Overload 2
168
+
169
+ ```ts
170
+ function http<
171
+ S extends z.ZodType | undefined = undefined,
172
+ const U extends HttpDefinition<S>["url"] = string,
173
+ const A extends HttpDefinition<S>["auth"] = undefined,
174
+ const H extends HttpDefinition<S>["headers"] = undefined,
175
+ >(
176
+ def: HttpDefinition<S> & { url: U; auth?: A; headers?: H },
177
+ ): EffectLogic<HttpInput<S>, HttpOutput> & OpenOf<HttpOpenParts<U, A, H>>
178
+ ```
179
+
180
+ **Parameters**
181
+
182
+ - `def`
183
+
184
+ - `method`: [`HttpMethod`](type-httpmethod.md)
185
+
186
+ The HTTP method: `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` or `OPTIONS`. It refuses
187
+ another: `http({ method: "<method>" }): the method is one of GET, HEAD, POST, PUT, PATCH,
188
+ DELETE, OPTIONS`.
189
+ - `url`: `string | Text | typeof open`
190
+
191
+ The url: `http://` or `https://`, then a literal host. No input, param or Effect secret can
192
+ change where the call goes. An Effect secret can be only in the path:
193
+ `` text`https://api.telegram.org/bot${secret("tg")}/sendMessage` ``.
194
+
195
+ Or `open`: a packaged Machine that cannot know the host leaves the url Open, and the composer
196
+ binds it one time with `customize(machine, { effects: { <slot>: { url } } })`.
197
+
198
+ It refuses:
199
+ - a scheme or host that is not literal: `` http({ url }): the url is an http:// or https:// url
200
+ whose scheme and host are literal — a secret may sit only in its path, after a "/":
201
+ text`https://api.example.com/bot${secret("tg")}/send` (ADR-0068) ``
202
+ - an Effect secret after `?` or `#`: `` http({ url }): secret("<name>") sits in the url's query
203
+ or fragment — a secret may sit only in its path; send it in `auth` or a header instead:
204
+ headers: { "x-api-key": text`${secret("...")}` } (ADR-0068) ``
205
+ - a host that is not a host: `http({ url }): "<scheme>://<host>" is not a host`
206
+ - a user name or password in the url: ``http({ url }): the url carries userinfo — use `auth` ``
207
+ - `headers` (optional): `Readonly<Record<string, string | Text>>`
208
+
209
+ Headers that are the same for each run. Each name is lowercase. A value is a string, or a
210
+ `text` with an Effect secret.
211
+
212
+ It refuses:
213
+ - a name that is not lowercase, or that frames or routes the request (`host`,
214
+ `content-length`, `transfer-encoding`, `connection`, `upgrade`, `te`, `trailer`,
215
+ `keep-alive`, `proxy-*`): `http({ headers }): "<name>" is not a header an Effect sets — a
216
+ lowercase name that does not frame or route the request (ADR-0068)`
217
+ - an `authorization` header beside `auth`: ``http({ headers }): "authorization" is set by
218
+ `auth` — write one of them``
219
+ - `auth` (optional): `{ readonly bearer: Secret; } | { readonly basic: { user: Text; password: Text; }; } | Text`
220
+
221
+ The `Authorization` header: `bearer(secret("x"))`, `basic(user, password)`, or a `text` that
222
+ is the whole value.
223
+ - `input` (optional): `S`
224
+
225
+ The zod schema of the input of the Effect: what the `input` of the `invoke`, or `fromPick`,
226
+ gives it. jr2 parses the input with it before the call. When it starts, input that does not
227
+ agree with it makes the Effect fail (its `onError` route): `http "<slot>": its input does not
228
+ match the definition's input schema — <path>: <message>`, one `<path>: <message>` for each
229
+ problem, joined by `; `.
230
+ - `request` (optional): `(input: S extends z.ZodType ? z.infer<S> : void) => HttpRequestParts`
231
+
232
+ A function that makes the part of the request that changes for each run, from the input:
233
+ `path` segments, and a `json` or `text` body. It cannot change the host, a header or an
234
+ Effect secret. Do not write it beside `body`.
235
+ - `body` (optional): `FileBody<S>`
236
+
237
+ A Worktree file as the body: `file(path, { segments?, contentType? })`. The Effect then
238
+ runs in the Sandbox Effector of its Workspace. Under a Workspace with Repo Slots, the invoke's
239
+ input names a Worktree that a cut of this run made, in `worktree`; with none, it refuses when
240
+ it starts: ``http "<slot>" reads a Worktree file, under a Workspace with Repo Slots, and its
241
+ input names no `worktree` ``. Do not write `request` beside it: the `segments`
242
+ of `file` are the path. It refuses another body: ``http({ body }): a body is file(path, {
243
+ segments?, contentType? }) — json and text come from `request` ``.
244
+ - `timeout` (optional): [`Duration`](type-duration.md)
245
+
246
+ How long jr2 waits for the answer: a number and a unit, such as `"30s"` or `"2m"`. Default
247
+ `"30s"`. With no answer in that time, the output is `unknown`. It refuses a value that is not
248
+ a positive duration: `http: timeout "<timeout>" is not a positive duration (like "30s",
249
+ "2m")`.
250
+ - `maxBody` (optional): `number`
251
+
252
+ The largest number of bytes of a text response body that the output keeps. Default 65536.
253
+ When jr2 cuts the body, `truncated` is `true`. It refuses a value that is not a positive whole
254
+ number: `http({ maxBody }): a positive number of bytes`.
255
+ - `idempotent` (optional): `boolean`
256
+
257
+ `true` when it is safe to send the call two times: it has its own idempotency key, or it only
258
+ reads. Default `false`. After an Orchestrator restart, jr2 cannot always tell if the call went
259
+ out. Then it sends an idempotent call again, and gives any other call the output `unknown`.