@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.
- package/README.md +20 -2
- package/console/components/app.ts +2 -0
- package/console/components/fleet.ts +14 -1
- package/console/components/machine-pane.ts +41 -2
- package/console/main.ts +13 -1
- package/console/store.ts +102 -6
- package/console/style.css +21 -0
- package/docs/agents-block.md +5 -0
- package/docs/concepts/agents-and-turns.md +478 -0
- package/docs/concepts/architecture.md +243 -0
- package/docs/concepts/charts.md +146 -0
- package/docs/concepts/composition.md +357 -0
- package/docs/concepts/converge.md +257 -0
- package/docs/concepts/durable-runs.md +189 -0
- package/docs/concepts/effects.md +658 -0
- package/docs/concepts/gates.md +208 -0
- package/docs/concepts/machines-and-workflows.md +298 -0
- package/docs/concepts/pools-and-sources.md +230 -0
- package/docs/concepts/secrets-and-trust.md +306 -0
- package/docs/concepts/the-menu.md +381 -0
- package/docs/concepts/workspaces.md +756 -0
- package/docs/get-started/a-model-decides.md +563 -0
- package/docs/get-started/an-agent-in-a-sandbox.md +383 -0
- package/docs/get-started/connect-a-model.md +248 -0
- package/docs/get-started/create-an-instance.md +194 -0
- package/docs/get-started/have-your-assistant-write-a-machine.md +993 -0
- package/docs/get-started/install.md +130 -0
- package/docs/guides/add-tools-to-the-sandbox.md +308 -0
- package/docs/guides/answer-a-gate.md +304 -0
- package/docs/guides/bind-open-parts.md +224 -0
- package/docs/guides/cancel-a-run.md +146 -0
- package/docs/guides/clean-up.md +206 -0
- package/docs/guides/cut-a-worktree.md +560 -0
- package/docs/guides/fix-a-failed-converge.md +361 -0
- package/docs/guides/give-the-cluster-git-credentials.md +222 -0
- package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
- package/docs/guides/let-an-agent-write-a-chart.md +230 -0
- package/docs/guides/look-inside-a-sandbox.md +177 -0
- package/docs/guides/mirror-the-kit-images.md +176 -0
- package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -0
- package/docs/guides/open-the-console.md +91 -0
- package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
- package/docs/guides/push-and-sign-a-branch.md +532 -0
- package/docs/guides/run-a-chart-by-name.md +270 -0
- package/docs/guides/run-a-command-or-call-a-url.md +587 -0
- package/docs/guides/run-one-worker-per-item.md +322 -0
- package/docs/guides/set-an-agents-access-and-dials.md +420 -0
- package/docs/guides/size-a-workspace.md +217 -0
- package/docs/guides/start-a-run-from-a-run.md +237 -0
- package/docs/guides/start-a-run.md +207 -0
- package/docs/guides/upgrade-the-kit-version.md +240 -0
- package/docs/guides/use-a-hosted-provider.md +214 -0
- package/docs/guides/use-a-local-model.md +313 -0
- package/docs/guides/watch-a-run.md +349 -0
- package/docs/guides/write-a-workflow.md +318 -0
- package/docs/index.md +44 -0
- package/docs/llms.txt +237 -0
- package/docs/reference/authoring-surface/agent.md +151 -0
- package/docs/reference/authoring-surface/answer.md +156 -0
- package/docs/reference/authoring-surface/arg.md +82 -0
- package/docs/reference/authoring-surface/basic.md +62 -0
- package/docs/reference/authoring-surface/bearer.md +53 -0
- package/docs/reference/authoring-surface/branchname.md +15 -0
- package/docs/reference/authoring-surface/chartschema.md +23 -0
- package/docs/reference/authoring-surface/chartschemafor.md +48 -0
- package/docs/reference/authoring-surface/command.md +206 -0
- package/docs/reference/authoring-surface/customize.md +64 -0
- package/docs/reference/authoring-surface/defineconfig.md +41 -0
- package/docs/reference/authoring-surface/defineevent.md +114 -0
- package/docs/reference/authoring-surface/dispatch.md +126 -0
- package/docs/reference/authoring-surface/fail.md +96 -0
- package/docs/reference/authoring-surface/file.md +142 -0
- package/docs/reference/authoring-surface/frompick.md +277 -0
- package/docs/reference/authoring-surface/http.md +259 -0
- package/docs/reference/authoring-surface/isfailure.md +58 -0
- package/docs/reference/authoring-surface/isready.md +14 -0
- package/docs/reference/authoring-surface/jr2setup.md +237 -0
- package/docs/reference/authoring-surface/open.md +105 -0
- package/docs/reference/authoring-surface/openbody.md +86 -0
- package/docs/reference/authoring-surface/paramsof.md +143 -0
- package/docs/reference/authoring-surface/pool.md +186 -0
- package/docs/reference/authoring-surface/push.md +130 -0
- package/docs/reference/authoring-surface/readyof.md +21 -0
- package/docs/reference/authoring-surface/secret.md +139 -0
- package/docs/reference/authoring-surface/sentby.md +83 -0
- package/docs/reference/authoring-surface/source.md +51 -0
- package/docs/reference/authoring-surface/text.md +62 -0
- package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
- package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
- package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
- package/docs/reference/authoring-surface/type-agentslots.md +15 -0
- package/docs/reference/authoring-surface/type-answeraction.md +12 -0
- package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
- package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
- package/docs/reference/authoring-surface/type-arg.md +19 -0
- package/docs/reference/authoring-surface/type-argnames.md +12 -0
- package/docs/reference/authoring-surface/type-bindactors.md +14 -0
- package/docs/reference/authoring-surface/type-binding.md +61 -0
- package/docs/reference/authoring-surface/type-bindingof.md +12 -0
- package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
- package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
- package/docs/reference/authoring-surface/type-ceilings.md +41 -0
- package/docs/reference/authoring-surface/type-chainlink.md +19 -0
- package/docs/reference/authoring-surface/type-chartaction.md +46 -0
- package/docs/reference/authoring-surface/type-chartagent.md +28 -0
- package/docs/reference/authoring-surface/type-chartevent.md +20 -0
- package/docs/reference/authoring-surface/type-chartguard.md +20 -0
- package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
- package/docs/reference/authoring-surface/type-chartjson.md +14 -0
- package/docs/reference/authoring-surface/type-chartstate.md +46 -0
- package/docs/reference/authoring-surface/type-charttext.md +40 -0
- package/docs/reference/authoring-surface/type-charttransition.md +22 -0
- package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
- package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
- package/docs/reference/authoring-surface/type-childat.md +12 -0
- package/docs/reference/authoring-surface/type-childslots.md +12 -0
- package/docs/reference/authoring-surface/type-commandenv.md +15 -0
- package/docs/reference/authoring-surface/type-commandinput.md +20 -0
- package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
- package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
- package/docs/reference/authoring-surface/type-customize.md +111 -0
- package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
- package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
- package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
- package/docs/reference/authoring-surface/type-dispatchoutput.md +72 -0
- package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
- package/docs/reference/authoring-surface/type-duration.md +15 -0
- package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
- package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
- package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
- package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
- package/docs/reference/authoring-surface/type-eventdef.md +45 -0
- package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
- package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
- package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
- package/docs/reference/authoring-surface/type-failslot.md +14 -0
- package/docs/reference/authoring-surface/type-failure.md +19 -0
- package/docs/reference/authoring-surface/type-failureinput.md +20 -0
- package/docs/reference/authoring-surface/type-filebody.md +37 -0
- package/docs/reference/authoring-surface/type-framepath.md +14 -0
- package/docs/reference/authoring-surface/type-frominput.md +14 -0
- package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
- package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
- package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
- package/docs/reference/authoring-surface/type-httpinput.md +12 -0
- package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
- package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
- package/docs/reference/authoring-surface/type-httpoutput.md +95 -0
- package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
- package/docs/reference/authoring-surface/type-jr2config.md +126 -0
- package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
- package/docs/reference/authoring-surface/type-lends.md +38 -0
- package/docs/reference/authoring-surface/type-logicat.md +12 -0
- package/docs/reference/authoring-surface/type-markedif.md +12 -0
- package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
- package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
- package/docs/reference/authoring-surface/type-namestart.md +77 -0
- package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
- package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
- package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
- package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
- package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
- package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
- package/docs/reference/authoring-surface/type-opencommandinput.md +22 -0
- package/docs/reference/authoring-surface/type-openeffect.md +12 -0
- package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
- package/docs/reference/authoring-surface/type-openof.md +12 -0
- package/docs/reference/authoring-surface/type-opensecret.md +23 -0
- package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
- package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +26 -0
- package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
- package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
- package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
- package/docs/reference/authoring-surface/type-poolspec.md +60 -0
- package/docs/reference/authoring-surface/type-pushinput.md +34 -0
- package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
- package/docs/reference/authoring-surface/type-pushoutput.md +149 -0
- package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
- package/docs/reference/authoring-surface/type-quantity.md +14 -0
- package/docs/reference/authoring-surface/type-reached.md +12 -0
- package/docs/reference/authoring-surface/type-reposlot.md +70 -0
- package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
- package/docs/reference/authoring-surface/type-sandboxoptions.md +84 -0
- package/docs/reference/authoring-surface/type-secret.md +25 -0
- package/docs/reference/authoring-surface/type-sender.md +19 -0
- package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
- package/docs/reference/authoring-surface/type-size.md +85 -0
- package/docs/reference/authoring-surface/type-slothandles.md +24 -0
- package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
- package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
- package/docs/reference/authoring-surface/type-syncstate.md +12 -0
- package/docs/reference/authoring-surface/type-text.md +19 -0
- package/docs/reference/authoring-surface/type-textpart.md +24 -0
- package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
- package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
- package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
- package/docs/reference/authoring-surface/type-unknown.md +21 -0
- package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
- package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
- package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
- package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
- package/docs/reference/authoring-surface/type-workspaced.md +115 -0
- package/docs/reference/authoring-surface/type-workspacehandles.md +22 -0
- package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
- package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
- package/docs/reference/authoring-surface/type-workspaceoptions.md +27 -0
- package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
- package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
- package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
- package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
- package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
- package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
- package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
- package/docs/reference/authoring-surface/workspace.md +287 -0
- package/docs/reference/authoring-surface/worktree.md +71 -0
- package/docs/reference/authoring-surface.md +217 -0
- package/docs/reference/cli.md +433 -0
- package/docs/reference/config.md +765 -0
- package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
- package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
- package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
- package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
- package/docs/reference/decisions/0006-agent-control-surface.md +50 -0
- package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
- package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
- package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
- package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
- package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
- package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
- package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +175 -0
- package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
- package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +271 -0
- package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
- package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -0
- package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
- package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +287 -0
- package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
- package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +101 -0
- package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
- package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +175 -0
- package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -0
- package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
- package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
- package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +245 -0
- package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -0
- package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
- package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
- package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +193 -0
- package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
- package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +126 -0
- package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
- package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
- package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
- package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
- package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
- package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
- package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
- package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
- package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
- package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
- package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
- package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
- package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
- package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
- package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
- package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
- package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +238 -0
- package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
- package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -0
- package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
- package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
- package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
- package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
- package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +108 -0
- package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -0
- package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
- package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
- package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +239 -0
- package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -0
- package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
- package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
- 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
- package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
- package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -0
- package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
- package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +334 -0
- package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
- package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
- package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
- package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
- package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
- package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
- package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
- package/docs/reference/decisions.md +86 -0
- package/docs/reference/glossary.md +687 -0
- package/docs/reference/http-api.md +1386 -0
- package/docs/reference/machines.md +189 -0
- package/docs/reference/mechanism-events.md +72 -0
- package/docs/why.md +207 -0
- package/package.json +5 -3
- package/src/actor.ts +694 -106
- package/src/agent.ts +114 -38
- package/src/ambient.ts +3 -4
- package/src/assembly-checks.ts +189 -7
- package/src/cause.ts +234 -0
- package/src/chart.ts +345 -46
- package/src/charts.ts +43 -8
- package/src/config.ts +440 -178
- package/src/custodian.lua +17 -5
- package/src/custodian.ts +325 -99
- package/src/customize.ts +199 -49
- package/src/dispatch-effect.ts +945 -0
- package/src/door-compat.ts +217 -0
- package/src/durability.ts +11 -4
- package/src/effect-checks.ts +50 -3
- package/src/effect.ts +641 -128
- package/src/effector-wire.ts +165 -13
- package/src/fail.ts +222 -0
- package/src/harness-client.ts +587 -50
- package/src/harness-env.ts +33 -0
- package/src/held-secrets.ts +125 -16
- package/src/holds.ts +3 -0
- package/src/http-effect.ts +556 -58
- package/src/http.ts +480 -30
- package/src/index.ts +74 -82
- package/src/instance.ts +68 -8
- package/src/internal.ts +85 -0
- package/src/kube-client.ts +6 -3
- package/src/machine-doc.ts +24 -7
- package/src/mechanism-routes.ts +168 -0
- package/src/model-keys.generated.ts +53 -0
- package/src/model-keys.ts +42 -58
- package/src/names.ts +19 -6
- package/src/notices.ts +483 -41
- package/src/open-body.ts +242 -40
- package/src/open-effect.ts +81 -8
- package/src/open.ts +90 -6
- package/src/parts.ts +213 -30
- package/src/party.ts +101 -2
- package/src/pick.ts +497 -11
- package/src/pool.ts +282 -50
- package/src/registration.ts +133 -12
- package/src/repo-identity.ts +7 -3
- package/src/repos.ts +22 -3
- package/src/run-host.ts +665 -45
- package/src/run-output.ts +38 -0
- package/src/sandbox-effect.ts +457 -71
- package/src/sandbox-kube.ts +66 -17
- package/src/secret-placement.ts +59 -17
- package/src/server.ts +3 -0
- package/src/setup.ts +325 -62
- package/src/size.ts +121 -9
- package/src/snapshot-store.ts +54 -10
- package/src/stub-harness.ts +44 -16
- package/src/timers.ts +14 -1
- package/src/tokens.ts +107 -32
- package/src/vocabulary.ts +88 -14
- package/src/wire.ts +100 -26
- package/src/workspace.ts +771 -238
- package/src/worktree.ts +249 -0
package/src/config.ts
CHANGED
|
@@ -34,34 +34,96 @@ import { assertSize, type Size } from "./size.ts";
|
|
|
34
34
|
// credential against an arbitrary host. A bound url is code the Instance typechecked and deployed
|
|
35
35
|
// — admitted without a match, cloned anonymously.
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
// One credentials entry. An entry may carry neither `token` nor `sshKey`: it then admits its
|
|
38
|
+
// prefix through the fence and the clone is anonymous.
|
|
39
|
+
/** One entry of `git.credentials`: the credential that the cluster uses for the Repos whose
|
|
40
|
+
* identity starts with `match`. An entry with neither `token` nor `sshKey` admits its Repos
|
|
41
|
+
* through the fence, and they clone with no credential. */
|
|
39
42
|
export type GitCredential = {
|
|
40
|
-
/**
|
|
43
|
+
/** The Repos this entry is for: a prefix of a Repo's identity, such as `github.com/ourorg/`, or
|
|
44
|
+
* `*` for every Repo. The identity of a Repo is its host and path with no scheme, user or `.git`.
|
|
45
|
+
* When more than one entry matches, the longest `match` wins; on a tie, the first entry in the
|
|
46
|
+
* list wins. */
|
|
41
47
|
match: string;
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
// The cache agent spends the clone Secret; the Orchestrator never holds it (ADR-0068).
|
|
49
|
+
/** For an `https://` url: the name of the env var that holds a token, read from the shell or
|
|
50
|
+
* `.env` when `jr2 up` runs. `jr2 up` writes the value into a Secret (`jr2-git-<hash>`) that only
|
|
51
|
+
* the Repo cache agent reads. The Agent never sees it. */
|
|
44
52
|
token?: string;
|
|
45
|
-
/**
|
|
53
|
+
/** For an ssh url: the name of a Secret that you create. It holds a deploy key under the Flux
|
|
54
|
+
* key names `identity`, `identity.pub` and `known_hosts`. */
|
|
46
55
|
sshKey?: string;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
// The credential a `push()` spends (ADR-0051, ADR-0067). A token goes Basic through a credential
|
|
57
|
+
// helper only.
|
|
58
|
+
/** The credential that a `push()` Effect uses, when it is not the clone credential. Write
|
|
59
|
+
* `{ sshKey }` or `{ token }`. Default: the clone credential pushes. An entry with no credential
|
|
60
|
+
* admits a clone and never a push. When the push finds no usable credential, it is refused, for
|
|
61
|
+
* example: `no git.credentials entry matches "<identity>" — a push spends the entry its url
|
|
62
|
+
* matches`, or `git.credentials entry "<match>" holds no credential a push over <scheme> can
|
|
63
|
+
* spend`. */
|
|
64
|
+
push?:
|
|
65
|
+
| {
|
|
66
|
+
/** For an ssh url: the name of a Secret that you create, with the same keys as the
|
|
67
|
+
* entry's `sshKey`. */
|
|
68
|
+
sshKey: string;
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
/** For an `https://` url: the name of the env var that holds the push token, read as for
|
|
72
|
+
* the entry's `token`. */
|
|
73
|
+
token: string;
|
|
74
|
+
};
|
|
75
|
+
// Explicit (ADR-0067): an auth key is never reused as a signing key.
|
|
76
|
+
/** The key that a `push({ sign: true })` signs with, and the committer it signs as:
|
|
77
|
+
* `{ sshKey, name, email }` or `{ gpgKey, name, email }`. `sshKey` names a Secret with
|
|
78
|
+
* `identity`. `gpgKey` names a Secret with `private.asc` and no passphrase. jr2 never signs with
|
|
79
|
+
* the clone or push key, so name the signing key here. The email must belong to the forge account
|
|
80
|
+
* that holds the key, or the forge shows the signature as unverified. A signed push without it is
|
|
81
|
+
* refused: `signed, and git.credentials entry "<match>" holds no sign field`. */
|
|
82
|
+
sign?:
|
|
83
|
+
| {
|
|
84
|
+
/** The name of a Secret that you create, which holds the ssh signing key under `identity`. */
|
|
85
|
+
sshKey: string;
|
|
86
|
+
/** The committer's name on the signed commit. */
|
|
87
|
+
name: string;
|
|
88
|
+
/** The committer's email. It must belong to the forge account that holds the key. */
|
|
89
|
+
email: string;
|
|
90
|
+
}
|
|
91
|
+
| {
|
|
92
|
+
/** The name of a Secret that you create, which holds the GPG signing key under
|
|
93
|
+
* `private.asc`, with no passphrase. */
|
|
94
|
+
gpgKey: string;
|
|
95
|
+
/** The committer's name on the signed commit. */
|
|
96
|
+
name: string;
|
|
97
|
+
/** The committer's email. It must belong to the forge account that holds the key. */
|
|
98
|
+
email: string;
|
|
99
|
+
};
|
|
100
|
+
// The squashed commit is new, and without `sign` no signer names its committer (ADR-0067).
|
|
101
|
+
/** Who commits an unsigned `push({ squash: true })`: `{ name, email }`. The squashed commit is
|
|
102
|
+
* new, so it needs a committer. Its date comes from the Effector's clock, and its author stays
|
|
103
|
+
* the Agent. A signed push is committed by the signer, so it does not read this field. A squashed
|
|
104
|
+
* push with neither field is refused: `squashed without sign, and git.credentials entry "<match>"
|
|
105
|
+
* holds neither sign nor committer`. */
|
|
106
|
+
committer?: {
|
|
107
|
+
/** The committer's name on the squashed commit. */
|
|
108
|
+
name: string;
|
|
109
|
+
/** The committer's email on the squashed commit. */
|
|
110
|
+
email: string;
|
|
111
|
+
};
|
|
61
112
|
};
|
|
62
113
|
|
|
114
|
+
/** How the cluster authenticates to Repos. */
|
|
63
115
|
export type GitConfig = {
|
|
64
|
-
/**
|
|
116
|
+
/** The credential entries, matched by prefix on the Repo identity. The longest `match` wins; on a
|
|
117
|
+
* tie, the first entry in the list wins.
|
|
118
|
+
*
|
|
119
|
+
* The list is also a fence. A per-run url, which comes from the run input, must match an entry,
|
|
120
|
+
* or the Sandbox refuses it when it attaches the Repo:
|
|
121
|
+
* `Sandbox "<name>" refuses the per-run repo <url> for slot "<slot>": no git.credentials entry matches "<identity>"`.
|
|
122
|
+
* Thus a run cannot spend this cluster's credentials against any host. A url that a Machine
|
|
123
|
+
* binds needs no entry. When no entry matches it, it clones with no credential.
|
|
124
|
+
*
|
|
125
|
+
* Each entry is checked when the config loads:
|
|
126
|
+
* `<file> at git.credentials[<i>]<path>: <problem>`, followed by the shape of an entry. */
|
|
65
127
|
credentials?: readonly GitCredential[];
|
|
66
128
|
};
|
|
67
129
|
|
|
@@ -110,21 +172,41 @@ export function isSshUrl(url: string): boolean {
|
|
|
110
172
|
}
|
|
111
173
|
}
|
|
112
174
|
|
|
113
|
-
|
|
114
|
-
|
|
175
|
+
// An env var on the Harness container, in the CR's (corev1.EnvVar) shape — `value` or a
|
|
176
|
+
// `valueFrom` secret/configmap reference, passed through to the operator verbatim.
|
|
177
|
+
/** One env var of the Harness container, in the Kubernetes `EnvVar` shape. The Agent can read it,
|
|
178
|
+
* so it must not hold a model key: put a model key in `secrets`. */
|
|
115
179
|
export type HarnessEnvVar = {
|
|
180
|
+
/** The env var's name. A known model key name, such as `ANTHROPIC_API_KEY`, is refused:
|
|
181
|
+
* `harness.env[<i>] sets <NAME>, a model key the Agent could read and take out of the pod — hold it instead`. */
|
|
116
182
|
name: string;
|
|
183
|
+
/** The value, usually read from `process.env`. `jr2 up` writes it into a Secret of the Instance.
|
|
184
|
+
* Write `value` or `valueFrom`. */
|
|
117
185
|
value?: string;
|
|
186
|
+
/** Or a Kubernetes `valueFrom` reference, such as `{ secretKeyRef: { name, key } }`, given to the
|
|
187
|
+
* pod as it is. A reference to a Secret of the kit is refused:
|
|
188
|
+
* `harness.env[<i>] (<NAME>) reads Secret "<name>", which is the kit's and never the Harness's`. */
|
|
118
189
|
valueFrom?: Record<string, unknown>;
|
|
119
190
|
};
|
|
120
191
|
|
|
121
|
-
|
|
122
|
-
|
|
192
|
+
// A whole-Secret/ConfigMap env injection (corev1.EnvFromSource) for the Harness container.
|
|
193
|
+
/** A Secret or a ConfigMap whose keys all become env vars of the Harness container, in the
|
|
194
|
+
* Kubernetes `EnvFromSource` shape. Write `secretRef` or `configMapRef`. The Agent can read every
|
|
195
|
+
* key, so `jr2 up` refuses one that holds a known model key:
|
|
196
|
+
* `harness.envFrom[<i>] loads <where>, which carries <KEY> — a model key the Agent could read`. */
|
|
123
197
|
export type HarnessEnvFromSource = {
|
|
124
|
-
/**
|
|
198
|
+
/** Text put before each key's name, as Kubernetes does. Default: none. */
|
|
125
199
|
prefix?: string;
|
|
126
|
-
|
|
127
|
-
|
|
200
|
+
/** A Secret that you manage, by name: `{ name }`. `jr2 up` checks that it exists. */
|
|
201
|
+
secretRef?: {
|
|
202
|
+
/** The name of the Secret. */
|
|
203
|
+
name: string;
|
|
204
|
+
};
|
|
205
|
+
/** A ConfigMap that you manage, by name: `{ name }`. */
|
|
206
|
+
configMapRef?: {
|
|
207
|
+
/** The name of the ConfigMap. */
|
|
208
|
+
name: string;
|
|
209
|
+
};
|
|
128
210
|
};
|
|
129
211
|
|
|
130
212
|
/** This kit's version — npm version == published image tag, one release train (ADR-0019). */
|
|
@@ -134,235 +216,415 @@ export const KIT_VERSION = (
|
|
|
134
216
|
}
|
|
135
217
|
).version;
|
|
136
218
|
|
|
137
|
-
|
|
138
|
-
|
|
219
|
+
// Token limits for one model — the Harness's provider-registration options, keyed per model
|
|
220
|
+
// because limits are properties of the MODEL, not the endpoint (agents pick models per definition,
|
|
221
|
+
// ADR-0018).
|
|
222
|
+
/** The token limits of one model of a custom provider. */
|
|
139
223
|
export type HarnessProviderModel = {
|
|
140
|
-
/** The model's context window, in tokens (vLLM: `max_model_len`).
|
|
224
|
+
/** The model's context window, in tokens (vLLM: `max_model_len`). Default: the provider's
|
|
225
|
+
* `contextWindow`. */
|
|
141
226
|
contextWindow?: number;
|
|
142
|
-
/** The
|
|
227
|
+
/** The most output tokens in one completion. Default: the provider's `maxTokens`. */
|
|
143
228
|
maxTokens?: number;
|
|
144
229
|
};
|
|
145
230
|
|
|
146
|
-
/**
|
|
147
|
-
* `
|
|
148
|
-
*
|
|
231
|
+
/** The wire protocols the Harness speaks for a custom provider (`harness.provider.api`, ADR-0018) —
|
|
232
|
+
* `CUSTOM_APIS` in `@jr2/harness`, whose test holds the two lists equal. `jr2 up` refuses any other
|
|
233
|
+
* value before it starts anything, as the Harness would refuse it at boot. */
|
|
234
|
+
export const CUSTOM_PROVIDER_APIS: readonly string[] = ["openai-completions"];
|
|
235
|
+
|
|
236
|
+
// A custom model provider (ADR-0018) — what the stock Harness registers with pi's
|
|
237
|
+
// `registerProvider(id, { api, baseUrl, … })` (ADR-0027). The vLLM/Ollama path: an
|
|
238
|
+
// OpenAI-compatible endpoint under an instance-chosen provider id.
|
|
239
|
+
/** A custom model provider: an endpoint that is not in the model catalog, such as vLLM or Ollama,
|
|
240
|
+
* under a provider id that you choose. An Agent names one of its models as `<id>/<model>`. */
|
|
149
241
|
export type HarnessProvider = {
|
|
150
|
-
/** The provider id model
|
|
242
|
+
/** The provider id that model names start with: `vllm` in `vllm/Qwen/Qwen3-32B`. It must not
|
|
243
|
+
* also be a key of `harness.catalog`:
|
|
244
|
+
* `harness.catalog.<id>: "<id>" is also harness.provider.id — a custom provider owns its own baseUrl`. */
|
|
151
245
|
id: string;
|
|
152
|
-
/** The wire protocol
|
|
246
|
+
/** The wire protocol. The only value is `"openai-completions"`, which most OpenAI-compatible
|
|
247
|
+
* endpoints speak, such as vLLM and Ollama. `jr2 up` refuses any other value before it builds or
|
|
248
|
+
* applies anything:
|
|
249
|
+
* `refusing: harness.provider.api is "<api>" — the Harness speaks: openai-completions (ADR-0018)`. */
|
|
153
250
|
api: string;
|
|
154
|
-
|
|
155
|
-
|
|
251
|
+
// Deployment-varying → resolve from env (`.env`), never hardcode (ADR-0019).
|
|
252
|
+
/** The endpoint's URL. The pods must reach it: `localhost` never works, and a LAN address works
|
|
253
|
+
* on kind. It changes between deployments, so read it from `process.env` (`.env`). `jr2 up`
|
|
254
|
+
* checks from inside the cluster that the endpoint answers. */
|
|
156
255
|
baseUrl: string;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
*
|
|
161
|
-
*
|
|
256
|
+
// A held secret (ADR-0059). Genuinely optional: an unauthenticated endpoint needs none (the
|
|
257
|
+
// Harness sends the wire library's placeholder, which vLLM/Ollama ignore).
|
|
258
|
+
/** The API key, when the endpoint needs one. Read it from `process.env`. It is a Held secret,
|
|
259
|
+
* `JR2_PROVIDER_API_KEY`: `jr2 up` gives the value to the Custodian only, bound to the host of
|
|
260
|
+
* `baseUrl`, and the Harness process holds only its secret Stand-in. Thus `baseUrl` must be
|
|
261
|
+
* `https://` when you set it:
|
|
262
|
+
* `harness.provider.apiKey is set, and harness.provider.baseUrl is not https://`. Default: none,
|
|
263
|
+
* for an endpoint that needs no key. */
|
|
162
264
|
apiKey?: string;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
265
|
+
// Limits resolve per-model → provider-level → 0, and a CUSTOM provider id has no catalog entry —
|
|
266
|
+
// unset limits resolve to 0, which leaves auto-compaction no context budget to reason about. The
|
|
267
|
+
// wire request sends no limit for a 0 `maxTokens`: pi-ai omits it when the context window is
|
|
268
|
+
// known, and the Harness removes the 1 that pi-ai would send when neither is (`unlimitedPayload`).
|
|
269
|
+
/** The context window, in tokens, of each model of this provider that `models` does not set.
|
|
270
|
+
* Set it here or in `models`: a limit that nothing sets is 0, and then Compaction has no context
|
|
271
|
+
* budget. */
|
|
167
272
|
contextWindow?: number;
|
|
273
|
+
/** The most output tokens in one completion, for each model of this provider that `models` does
|
|
274
|
+
* not set. Default: no limit is sent. */
|
|
168
275
|
maxTokens?: number;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
276
|
+
// Committable model properties, not deployment-varying: whichever model an Agent definition names
|
|
277
|
+
// resolves its own entry.
|
|
278
|
+
/** Token limits for each model, keyed by the model id after the provider prefix: the key for
|
|
279
|
+
* `vllm/Qwen/Qwen3-32B` is `"Qwen/Qwen3-32B"`. A limit set here wins over the provider's. */
|
|
172
280
|
models?: Record<string, HarnessProviderModel>;
|
|
173
281
|
};
|
|
174
282
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
283
|
+
// Where one of pi's catalog providers sends its calls (ADR-0059) — reach, not a model choice
|
|
284
|
+
// (ADR-0018). The catalog keeps every model fact (limits, cost, thinking levels).
|
|
285
|
+
/** Where the calls of one catalog provider go: a gateway that serves that provider's own API, such
|
|
286
|
+
* as LiteLLM. Only the endpoint changes. The catalog keeps every fact about the models. */
|
|
178
287
|
export type CatalogReach = {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
* `https://litellm.corp.example/v1` for `openai
|
|
288
|
+
// Replaces `model.baseUrl` for every model of this provider.
|
|
289
|
+
/** The whole base URL that the provider's API adds its paths to: `https://litellm.corp.example`
|
|
290
|
+
* for `anthropic`, which adds `/v1/messages`; `https://litellm.corp.example/v1` for `openai`. It
|
|
291
|
+
* must be `https://`: `harness.catalog.<id>.baseUrl must be an https:// URL`. It changes between
|
|
292
|
+
* deployments, so read it from `process.env` (`.env`). */
|
|
182
293
|
baseUrl: string;
|
|
183
294
|
};
|
|
184
295
|
|
|
296
|
+
// One secret of the Instance (ADR-0059's entry shape, ADR-0068's list). Its placement is READ,
|
|
297
|
+
// never declared, and naming is placement: a pod gets the secrets something in it names. Both is
|
|
298
|
+
// both, and `jr2 up` reports it per pod. `hosts`, `headers` and `paths` are the binding, never the
|
|
299
|
+
// placement.
|
|
185
300
|
/**
|
|
186
|
-
* One secret of the Instance
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
301
|
+
* One secret of the Instance. You do not say where it goes: it goes where something names it.
|
|
302
|
+
*
|
|
303
|
+
* - It is a Held secret in each Harness pod that names it. A pod names it when its `workspace()`
|
|
304
|
+
* lists it under `secrets`, or when it is the model key of a provider that an Agent there uses. The Harness
|
|
305
|
+
* process then holds only its Stand-in, a secret value that starts `jr2-held-<name>.`, and the
|
|
306
|
+
* pod's Custodian puts the value into requests toward `hosts` only. The Agent's programs get the
|
|
307
|
+
* Stand-in, in their env under this name, only when the `workspace()` lists it under `secrets`.
|
|
308
|
+
* - It is an Effect secret where an Effect names it with `secret("name")`: a file in that
|
|
309
|
+
* Effect's Effector.
|
|
310
|
+
*
|
|
311
|
+
* One secret can be both. Its `hosts`, `headers` and `paths` are its binding, never its placement:
|
|
312
|
+
* they say where the value may go, not which pod gets it. `jr2 up` warns about an entry that nothing names:
|
|
313
|
+
* `secrets[<i>] (<NAME>) is named by nothing; goes nowhere`.
|
|
194
314
|
*/
|
|
195
315
|
export type SecretEntry = {
|
|
196
|
-
/** As a Held secret, the
|
|
197
|
-
*
|
|
316
|
+
/** As a Held secret, the name of its Stand-in: the file the Harness reads it from, the env var
|
|
317
|
+
* that the engine reads a model key from, and the env var of the Agent's programs when the
|
|
318
|
+
* `workspace()` lists it under `secrets`. As an Effect secret, the name that `secret("<name>")` names, and the name of the
|
|
319
|
+
* Effector's file. For a Held secret, it must match `[A-Z_][A-Z0-9_]*`:
|
|
320
|
+
* `secrets[<i>].name "<name>" is not an env var name ([A-Z_][A-Z0-9_]*)`. It must not start with
|
|
321
|
+
* `JR2_` and must not be a proxy or trust variable of the kit:
|
|
322
|
+
* `secrets[<i>].name <NAME> is the kit's — JR2_ names and the proxy and trust variables belong to the mechanism`.
|
|
323
|
+
* One name, one entry: `secrets[<i>].name <NAME> is held twice`. */
|
|
198
324
|
name: string;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
325
|
+
// `jr2 up` writes it into the Secret of each placement that names it —
|
|
326
|
+
// `jr2-held-secrets-<pod>` (that pod's Custodian's), `jr2-instance-effector` — and nowhere else.
|
|
327
|
+
/** The value, usually read from `process.env` (`.env`). `jr2 up` writes it only into the Secrets
|
|
328
|
+
* of the containers that hold it. Write exactly one of `value` and `valueFrom`:
|
|
329
|
+
* `secrets[<i>] needs exactly one of value or valueFrom`. A `.env` variable that is not set reads
|
|
330
|
+
* as no value, and an empty one is refused: `secrets[<i>].value is empty — set <NAME> in .env`. */
|
|
202
331
|
value?: string;
|
|
203
|
-
/** Or a key of a Secret you manage (Sealed Secrets, External Secrets)
|
|
204
|
-
*
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
332
|
+
/** Or a key of a Secret that you manage (Sealed Secrets, External Secrets):
|
|
333
|
+
* `{ secretKeyRef: { name, key } }`. `jr2 up` checks that the Secret and the key exist. Each
|
|
334
|
+
* container that holds the secret mounts that one key as a file, and no other container does. */
|
|
335
|
+
valueFrom?: {
|
|
336
|
+
/** The Secret and the key in it that hold the value. */
|
|
337
|
+
secretKeyRef: {
|
|
338
|
+
/** The name of the Secret. */
|
|
339
|
+
name: string;
|
|
340
|
+
/** The key in the Secret that holds the value. */
|
|
341
|
+
key: string;
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
// A known model-key name is a key of `MODEL_KEYS` (model-keys.ts), which holds its default host.
|
|
345
|
+
/** Where the value may go as a Held secret. Each entry is `host`, `host:port`, or an `https://`
|
|
346
|
+
* URL, of which only the host and port count. Write exact DNS names or IP addresses, with no
|
|
347
|
+
* wildcards. The port default is 443. A known model key, such as `ANTHROPIC_API_KEY`, may leave
|
|
348
|
+
* it out: it then goes to the one host that its provider calls. Any other Held secret must name
|
|
349
|
+
* its hosts: `secrets[<i>].hosts is absent, and <NAME> has no single default host`. */
|
|
211
350
|
hosts?: readonly string[];
|
|
212
|
-
/**
|
|
213
|
-
* `["authorization", "x-api-key", "x-goog-api-key", "api-key"]`.
|
|
351
|
+
/** The request headers in which the Custodian puts the value in place of the Stand-in,
|
|
352
|
+
* lowercase. Default: `["authorization", "x-api-key", "x-goog-api-key", "api-key"]`. A header
|
|
353
|
+
* that frames or routes the request is refused:
|
|
354
|
+
* `secrets[<i>].headers[<j>] "<header>" cannot carry a held secret`. */
|
|
214
355
|
headers?: readonly string[];
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
*
|
|
356
|
+
// A key minted through the Custodian is a key the Agent can take away.
|
|
357
|
+
/** The path prefixes to which the value may be sent, such as `/v1/messages`. Each starts with
|
|
358
|
+
* `/`. Default: every path. Narrow it for a gateway key that can reach admin routes, such as a
|
|
359
|
+
* LiteLLM key that can make new keys. The Agent could take away a key made that way. */
|
|
218
360
|
paths?: readonly string[];
|
|
219
361
|
};
|
|
220
362
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
363
|
+
// The agent-runtime section (ADR-0018): what the stock Harness image consumes alongside the Agent
|
|
364
|
+
// definition each Turn hands it (ADR-0049). Moved out of `sandbox` deliberately — `sandbox` is pod
|
|
365
|
+
// transport (it still CARRIES this env to the Harness container), but model concerns are Harness
|
|
366
|
+
// semantics.
|
|
367
|
+
//
|
|
368
|
+
// It declares what this instance can REACH — endpoints, credentials, trust — and never WHICH
|
|
369
|
+
// model to use (ADR-0018). This config holds no instance-wide `model` default and no Agent
|
|
370
|
+
// roster: an Agent is an actor slot on ONE Machine, whose definition rides the Turn (ADR-0049).
|
|
371
|
+
// One definition value may still be carried by several Machines, so the variation that matters is
|
|
372
|
+
// per-definition and per-invocation, which one global default serves not at all.
|
|
373
|
+
/** What the Harness can reach: the model endpoints, their credentials, and the CAs it trusts. It
|
|
374
|
+
* never says which model an Agent uses: each Agent's definition names its model. */
|
|
231
375
|
export type HarnessConfig = {
|
|
232
|
-
|
|
233
|
-
|
|
376
|
+
// Preflighted from inside the cluster by `jr2 up` (ADR-0019); its `apiKey` is held (ADR-0059).
|
|
377
|
+
/** A custom model provider, such as a vLLM or Ollama endpoint. See {@link HarnessProvider}.
|
|
378
|
+
* Default: none; the Agents use catalog providers only. */
|
|
234
379
|
provider?: HarnessProvider;
|
|
235
|
-
|
|
236
|
-
|
|
380
|
+
// A gateway that serves the provider's own API (ADR-0059).
|
|
381
|
+
/** Catalog providers whose calls go to another endpoint, such as a gateway, keyed by the catalog
|
|
382
|
+
* provider id: `anthropic`, `openai`, and so on. See {@link CatalogReach}. A key that is not a
|
|
383
|
+
* catalog provider with a known model key is refused:
|
|
384
|
+
* `harness.catalog.<id>: "<id>" is not a pi catalog provider jr2 knows a key for`. Default:
|
|
385
|
+
* each provider's own endpoint. */
|
|
237
386
|
catalog?: Readonly<Record<string, CatalogReach>>;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
387
|
+
// Values read from `process.env`/`.env` are materialized into the instance-owned Secret by
|
|
388
|
+
// `jr2 up`. A known model key here is refused (ADR-0059).
|
|
389
|
+
/** Env vars for the Harness container. The Agent can read every one of them, so do not put a
|
|
390
|
+
* credential here. A known model key is refused here. Put it in the top-level `secrets` list.
|
|
391
|
+
* The Harness process gets each one, except a name that loads code from a path, such as
|
|
392
|
+
* `NODE_OPTIONS` or `LD_PRELOAD`, and `HOME`, which is its own; the Agent's programs get each
|
|
393
|
+
* one. A name that starts with `JR2_` is jr2's own, and is refused. A credential file that the
|
|
394
|
+
* Harness process reads, such as `AWS_CONFIG_FILE`, is refused in a folder that the Agent's code
|
|
395
|
+
* writes (`/work`, `/tmp`, `/home/jr2`), and gives a warning anywhere else.
|
|
396
|
+
* See {@link HarnessEnvVar}. */
|
|
241
397
|
env?: readonly HarnessEnvVar[];
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
398
|
+
// `jr2 up` preflights that each referenced Secret exists (ADR-0019), and refuses one that
|
|
399
|
+
// carries a known model key (ADR-0059).
|
|
400
|
+
/** Secrets and ConfigMaps that you manage, whose keys all become env vars of the Harness
|
|
401
|
+
* process and of the Agent's programs, as `env` does. In the container's spec each key has the
|
|
402
|
+
* prefix `JR2_ENVFROM_`, so that the Harness can tell jr2's names from the image's; the Harness
|
|
403
|
+
* removes it. A key that starts with `JR2_` is refused: `jr2 up` refuses it, and the Harness does
|
|
404
|
+
* not start with one. See {@link HarnessEnvFromSource}. */
|
|
245
405
|
envFrom?: readonly HarnessEnvFromSource[];
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
*
|
|
250
|
-
*
|
|
406
|
+
// Only `jr2 up` reads it (host-side): it materializes the `jr2-ca` ConfigMap and runs the
|
|
407
|
+
// provider preflight with the same trust (ADR-0020, ADR-0059).
|
|
408
|
+
/** A path to a PEM CA bundle, relative to the Instance folder. An example is the CA of an
|
|
409
|
+
* internal endpoint in front of a LAN vLLM. Commit the file: CA certificates are public. `jr2 up`
|
|
410
|
+
* puts it in the `jr2-ca` ConfigMap and uses it when it checks the provider. The Harness
|
|
411
|
+
* container trusts it, and so does the Custodian when it verifies a host that a Held secret is
|
|
412
|
+
* bound to. */
|
|
251
413
|
caBundle?: string;
|
|
252
414
|
};
|
|
253
415
|
|
|
254
|
-
|
|
255
|
-
|
|
416
|
+
// One pod-spec toleration, verbatim (ADR-0052): `nodeSelector` and `tolerations` are the raw
|
|
417
|
+
// Kubernetes shapes, the stance `HarnessEnvVar` takes for `EnvVar`.
|
|
418
|
+
/** One toleration of a Sandbox pod, in the Kubernetes `Toleration` shape: a node taint that the
|
|
419
|
+
* pod tolerates. */
|
|
256
420
|
export type Toleration = {
|
|
421
|
+
/** The taint key. Leave it out, with `operator: "Exists"`, to tolerate every taint. */
|
|
257
422
|
key?: string;
|
|
423
|
+
/** `"Equal"` matches a taint whose value is `value`; `"Exists"` matches any value. Default:
|
|
424
|
+
* `"Equal"`. */
|
|
258
425
|
operator?: "Exists" | "Equal";
|
|
426
|
+
/** The taint value, for `operator: "Equal"`. */
|
|
259
427
|
value?: string;
|
|
428
|
+
/** The taint effect to tolerate: `"NoSchedule"`, `"PreferNoSchedule"` or `"NoExecute"`. Default:
|
|
429
|
+
* every effect. */
|
|
260
430
|
effect?: "NoSchedule" | "PreferNoSchedule" | "NoExecute";
|
|
431
|
+
/** For `"NoExecute"`: how many seconds the pod stays on the node after the taint is added.
|
|
432
|
+
* Default: the pod stays. */
|
|
261
433
|
tolerationSeconds?: number;
|
|
262
434
|
};
|
|
263
435
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
*
|
|
271
|
-
|
|
436
|
+
// Where an Instance's Sandboxes may land (ADR-0052). Both keys ride the Sandbox pod verbatim, the
|
|
437
|
+
// Repo cache agent's DaemonSet takes the same two so a cache is only ever where a Sandbox can reach
|
|
438
|
+
// it, and `jr2 up` reads the same predicate off the nodes to report the set. A Machine says nothing
|
|
439
|
+
// about placement: a node label is a deployment fact (ADR-0050). These two are the default class;
|
|
440
|
+
// a per-Machine `classes` map is the deferred extension.
|
|
441
|
+
/** Which nodes are Sandbox nodes: the nodes on which this Instance's Sandboxes may run. Absent, a
|
|
442
|
+
* Sandbox runs wherever an ordinary pod runs: on a node that is not cordoned and has no taint. No
|
|
443
|
+
* jr2 label is ever needed. The Repo cache agent runs on the same nodes, and `jr2 up` reports the
|
|
444
|
+
* set and warns when it is empty. */
|
|
272
445
|
export type SandboxPlacement = {
|
|
273
|
-
/**
|
|
446
|
+
/** The pod's `nodeSelector`: a Sandbox node must have every one of these labels. Default: none. */
|
|
274
447
|
nodeSelector?: Readonly<Record<string, string>>;
|
|
275
|
-
|
|
276
|
-
|
|
448
|
+
// No `tolerationSeconds` is added.
|
|
449
|
+
/** The pod's `tolerations`, as you write them. Default: none. jr2 adds no `tolerationSeconds`.
|
|
450
|
+
* Thus a tolerated `NoExecute` taint keeps a Sandbox on its node while its Lease is renewed. */
|
|
277
451
|
tolerations?: readonly Toleration[];
|
|
278
452
|
};
|
|
279
453
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
* that states none.
|
|
283
|
-
|
|
454
|
+
// The Instance's Sandbox defaults (ADR-0052, ADR-0060).
|
|
455
|
+
/** The Instance's Sandbox defaults: the Sandbox nodes (see {@link SandboxPlacement}), and the Size
|
|
456
|
+
* of a Workspace that states none. The config load refuses a `sandbox` that is not an object:
|
|
457
|
+
* `<file> at sandbox: expected an object — { nodeSelector?, tolerations?, resources? }`. A key that
|
|
458
|
+
* this type does not have fails the typecheck that `jr2 up` runs. */
|
|
284
459
|
export type SandboxConfig = SandboxPlacement & {
|
|
460
|
+
// NEVER an override of a Size a Machine states: a Size is a fact of the Machine, and its one
|
|
461
|
+
// override path is `customize(machine, { resources })` (ADR-0060).
|
|
285
462
|
/**
|
|
286
|
-
* The
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
463
|
+
* The Size of a Workspace that states no Size at all: `{ limits: { memory, cpu } }` and nothing
|
|
464
|
+
* else. The kit default fills a field that it leaves out. It never changes a Size that a Machine
|
|
465
|
+
* states: to change that, use `customize(machine, { resources })`. Default: the kit default,
|
|
466
|
+
* memory `2Gi` and cpu `1`. jr2 reserves the whole Size and enforces the cpu limit. See
|
|
467
|
+
* {@link Size} for the refusals, such as
|
|
468
|
+
* `<file> at sandbox.resources.requests is not accepted`.
|
|
291
469
|
*/
|
|
292
470
|
resources?: Size;
|
|
293
471
|
};
|
|
294
472
|
|
|
473
|
+
// The PriorityClasses jr2's pods run under (ADR-0060). Absent, `jr2 up` creates two,
|
|
474
|
+
// cluster-scoped, beside the CRDs.
|
|
295
475
|
/**
|
|
296
|
-
* The PriorityClasses jr2's pods run under
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
476
|
+
* The PriorityClasses that jr2's pods run under. Absent, `jr2 up` creates two: `jr2-control`
|
|
477
|
+
* (value 100000, `PreemptLowerPriority`) and `jr2-sandbox` (value 1000, `preemptionPolicy: Never`).
|
|
478
|
+
* Thus an ordinary pod cannot preempt a live Workspace, and a Sandbox that waits for a node evicts
|
|
479
|
+
* no pod. A cluster with its own scheme names its existing classes here, and `jr2 up` then creates
|
|
480
|
+
* none for that key. The config load refuses any other key:
|
|
481
|
+
* `<file> at priorityClasses<path>: <problem> — { control?, sandbox? }, each the name of an existing PriorityClass`.
|
|
302
482
|
*/
|
|
303
483
|
export type PriorityClasses = {
|
|
304
|
-
/** An existing PriorityClass for the Orchestrator, the operator and the Repo cache agent.
|
|
484
|
+
/** An existing PriorityClass for the Orchestrator, the operator and the Repo cache agent.
|
|
485
|
+
* Default: `jr2-control`, which `jr2 up` creates. */
|
|
305
486
|
control?: string;
|
|
306
|
-
/** An existing PriorityClass for Sandboxes and the Instance Harness.
|
|
487
|
+
/** An existing PriorityClass for the Sandboxes and the Instance Harness. Default: `jr2-sandbox`,
|
|
488
|
+
* which `jr2 up` creates. */
|
|
307
489
|
sandbox?: string;
|
|
308
490
|
};
|
|
309
491
|
|
|
492
|
+
/**
|
|
493
|
+
* The shape of `jr2.config.ts`: the deployment facts of an Instance, which a Machine cannot carry.
|
|
494
|
+
* It holds the Instance's name, its secrets, how the cluster authenticates to Repos, what the
|
|
495
|
+
* Harness can reach, where Sandboxes run, and where images go. It names no Repo, no model and no
|
|
496
|
+
* Sandbox Image: a Machine names those itself.
|
|
497
|
+
*
|
|
498
|
+
* Every field is optional, and an Instance can run with no `jr2.config.ts`. Write the file as
|
|
499
|
+
* `export default defineConfig({ … })`. When the config loads, a file with no default export is
|
|
500
|
+
* refused: `` <file> has no default export (use `export default defineConfig({…})`) ``. The load also
|
|
501
|
+
* checks the shape of `git.credentials`, `secrets`, `harness.catalog` and `priorityClasses`. It
|
|
502
|
+
* checks that `sandbox` is an object, and checks its `resources`. Each refusal names the field.
|
|
503
|
+
* `jr2 up` checks the rest.
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```ts
|
|
507
|
+
* import { defineConfig, type JR2Config } from "@jr2/orchestrator";
|
|
508
|
+
*
|
|
509
|
+
* const harness: JR2Config["harness"] = {
|
|
510
|
+
* provider: {
|
|
511
|
+
* id: "vllm",
|
|
512
|
+
* api: "openai-completions",
|
|
513
|
+
* baseUrl: process.env.VLLM_URL ?? "",
|
|
514
|
+
* models: { "Qwen/Qwen3.6-35B-A3B": { contextWindow: 131072, maxTokens: 16384 } },
|
|
515
|
+
* },
|
|
516
|
+
* };
|
|
517
|
+
*
|
|
518
|
+
* export default defineConfig({ name: "my-instance", harness });
|
|
519
|
+
* ```
|
|
520
|
+
*
|
|
521
|
+
* @see docs/reference/config.md
|
|
522
|
+
* @see docs/get-started/connect-a-model.md
|
|
523
|
+
* @see docs/concepts/secrets-and-trust.md
|
|
524
|
+
* @see docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md
|
|
525
|
+
*/
|
|
310
526
|
export type JR2Config = {
|
|
311
|
-
|
|
312
|
-
|
|
527
|
+
// The instance's identity (ADR-0019).
|
|
528
|
+
/** The Instance's name. Its Kubernetes namespace is this name (`-n` overrides it), and
|
|
529
|
+
* `jr2 up` labels every object that it owns with it. Default: the name of the Instance folder. */
|
|
313
530
|
name?: string;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
* where
|
|
318
|
-
*
|
|
531
|
+
// One list for both sides (ADR-0068). Naming is the placement; `hosts` is a Held secret's
|
|
532
|
+
// binding, never its placement: an entry nothing names goes nowhere.
|
|
533
|
+
/** Every secret of the Instance, in one list. A secret goes where something names it. A Held
|
|
534
|
+
* secret goes where a `workspace()` lists it under `secrets` or an Agent's provider reads it. An
|
|
535
|
+
* Effect secret goes where an Effect names it with `secret("name")`. Its `hosts` is a Held
|
|
536
|
+
* secret's binding, never its placement: an entry that nothing names goes nowhere. A model API
|
|
537
|
+
* key goes here, never in `harness.env`. See {@link SecretEntry}. Each entry is checked when the
|
|
538
|
+
* config loads: `<file> at secrets[<i>]<path>: <problem>`, followed by the shape of an entry. */
|
|
319
539
|
secrets?: readonly SecretEntry[];
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
540
|
+
// NOT a list of Repos (ADR-0051): a Machine names those itself, through its `workspace()`'s Repo
|
|
541
|
+
// Slots, and whether the instance has a data plane at all is read off the registered Machines.
|
|
542
|
+
/** How the cluster authenticates to Repos, and the fence that a per-run url must pass. It is not
|
|
543
|
+
* a list of Repos: a Machine names its Repos in the Repo Slots of its `workspace()`. See
|
|
544
|
+
* {@link GitConfig}. */
|
|
323
545
|
git?: GitConfig;
|
|
324
|
-
/**
|
|
546
|
+
/** What the Harness can reach: a custom model provider, gateways for catalog providers, env
|
|
547
|
+
* vars, and CAs. See {@link HarnessConfig}. */
|
|
325
548
|
harness?: HarnessConfig;
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
* ordinary pod
|
|
549
|
+
// See `SandboxPlacement` (ADR-0052) and `SandboxConfig` (ADR-0060).
|
|
550
|
+
/** Which nodes are Sandbox nodes, and the Size of a Workspace that states none. Default: a
|
|
551
|
+
* Sandbox runs wherever an ordinary pod runs, at the kit's Size. See {@link SandboxConfig}. */
|
|
329
552
|
sandbox?: SandboxConfig;
|
|
330
|
-
|
|
331
|
-
|
|
553
|
+
// See `PriorityClasses` (ADR-0060).
|
|
554
|
+
/** Existing PriorityClasses to use in place of the two that `jr2 up` creates. See
|
|
555
|
+
* {@link PriorityClasses}. */
|
|
332
556
|
priorityClasses?: PriorityClasses;
|
|
333
|
-
|
|
334
|
-
|
|
557
|
+
// Deployment-varying — resolve from env (ADR-0019).
|
|
558
|
+
/** The image registry prefix to which `jr2 up` pushes the images that it builds, such as
|
|
559
|
+
* `registry.example.com/team`. It changes between deployments, so read it from `process.env`
|
|
560
|
+
* (`.env`). Default: none; `jr2 up` loads the images into the kind cluster. On a cluster that is
|
|
561
|
+
* not kind, `jr2 up` then refuses:
|
|
562
|
+
* `` context <context> is not a kind cluster and no `registry` is configured ``. */
|
|
335
563
|
registry?: string;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
*
|
|
344
|
-
*
|
|
564
|
+
// Deployment-varying — resolve from env. Seeding that mirror is a deliberate, instance-less act
|
|
565
|
+
// (`jr2 kit push`), never a side effect of `jr2 up` (ADR-0044).
|
|
566
|
+
//
|
|
567
|
+
// Separate from `registry` on purpose: `registry` addresses images THIS converge builds,
|
|
568
|
+
// `kitRegistry` addresses artifacts the kit already published. One key for both would make every
|
|
569
|
+
// private-registry user mirror the Kit images they could have pulled from the home.
|
|
570
|
+
/** The registry from which this cluster pulls the published Kit images: a mirror for a cluster
|
|
571
|
+
* that is self-hosted, air-gapped, or mirror-only. Default: none; the cluster pulls from the
|
|
572
|
+
* canonical home, `ghcr.io/snapwich/jr2-harness:<version>` and the others. Set, the cluster pulls
|
|
573
|
+
* the same tags from `<kitRegistry>/jr2-harness:<version>`. Fill the mirror with
|
|
574
|
+
* `jr2 kit push <registry>`; `jr2 up` never pushes to it. Read it from `process.env` (`.env`). */
|
|
345
575
|
kitRegistry?: string;
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
576
|
+
// Deployment-varying — resolve from env (ADR-0045). Present → ABSOLUTE: derivation is skipped
|
|
577
|
+
// (still intersected, so an unpublished platform is a named error, never a silent build).
|
|
578
|
+
//
|
|
579
|
+
// The escape hatch for the two cases derivation cannot see: a pool that autoscales from zero (no
|
|
580
|
+
// nodes to read yet), and a polluted set (an amd64 GPU pool beside arm64 workers, where the
|
|
581
|
+
// derived pair would cost a needless qemu cross-build). Not additive or subtractive.
|
|
582
|
+
/** The platforms for which `jr2 up` builds its images, as docker platform strings, such as
|
|
583
|
+
* `["linux/arm64"]`. Default: the platforms of the cluster's schedulable nodes that the kit
|
|
584
|
+
* releases images for. `jr2 up` reports a node platform that it skips.
|
|
351
585
|
*
|
|
352
|
-
*
|
|
353
|
-
* nodes
|
|
354
|
-
*
|
|
586
|
+
* Set it when the nodes cannot tell. One case is a node group that scales up from zero. Another
|
|
587
|
+
* is a set of nodes that need no image, such as an amd64 GPU group beside arm64 nodes. When you
|
|
588
|
+
* set it, it replaces the default. It adds to nothing and removes from nothing. The kit releases
|
|
589
|
+
* images for `linux/amd64` and `linux/arm64` only, so `jr2 up` refuses any other:
|
|
590
|
+
* `` `platforms` names <platforms> — the kit releases images for linux/amd64, linux/arm64 and nothing else ``. */
|
|
355
591
|
platforms?: readonly string[];
|
|
356
|
-
|
|
592
|
+
// Kit development territory (ADR-0019).
|
|
593
|
+
/** Settings of the operator layer, for kit development. */
|
|
357
594
|
operator?: {
|
|
358
|
-
/** `false
|
|
595
|
+
/** `false`: `jr2 up` does not converge the operator, and you run its controller yourself.
|
|
596
|
+
* Default: `true`. */
|
|
359
597
|
manage?: boolean;
|
|
360
598
|
};
|
|
361
599
|
};
|
|
362
600
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
601
|
+
// Identity passthrough that checks a config object against `JR2Config` where it is written —
|
|
602
|
+
// excess keys included, at every depth, which is why the parameter is the type and not a generic
|
|
603
|
+
// bound by it.
|
|
604
|
+
/**
|
|
605
|
+
* Declare the config of an Instance: the default export of `jr2.config.ts`. It gives back the
|
|
606
|
+
* object that you pass. Its only work is to check that object against {@link JR2Config} where you
|
|
607
|
+
* write it, at every depth, a misspelled key included. `jr2 up` typechecks the file before it
|
|
608
|
+
* converges.
|
|
609
|
+
*
|
|
610
|
+
* @param c - The Instance's config. See {@link JR2Config} for every field.
|
|
611
|
+
* @returns The same object.
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* ```ts
|
|
615
|
+
* import { defineConfig } from "@jr2/orchestrator";
|
|
616
|
+
*
|
|
617
|
+
* export default defineConfig({
|
|
618
|
+
* name: "my-instance",
|
|
619
|
+
* secrets: [{ name: "ANTHROPIC_API_KEY", value: process.env.ANTHROPIC_API_KEY }],
|
|
620
|
+
* git: { credentials: [{ match: "github.com/you/", token: "GITHUB_TOKEN" }] },
|
|
621
|
+
* });
|
|
622
|
+
* ```
|
|
623
|
+
*
|
|
624
|
+
* @see docs/reference/config.md
|
|
625
|
+
* @see docs/get-started/create-an-instance.md
|
|
626
|
+
* @see docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md
|
|
627
|
+
*/
|
|
366
628
|
export function defineConfig(c: JR2Config): JR2Config {
|
|
367
629
|
return c;
|
|
368
630
|
}
|