@intentic/sandbox-contract 1.247.0 → 1.249.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 +18 -15
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/chores.js.map +1 -1
- package/dist/chores/digest.d.ts.map +1 -1
- package/dist/chores/digest.js.map +1 -1
- package/dist/chores/extension-update.d.ts.map +1 -1
- package/dist/chores/extension-update.js.map +1 -1
- package/dist/chores/fix-deps.d.ts.map +1 -1
- package/dist/chores/fix-deps.js.map +1 -1
- package/dist/chores/index.d.ts +2 -2
- package/dist/chores/index.d.ts.map +1 -1
- package/dist/chores/index.js +1 -1
- package/dist/chores/index.js.map +1 -1
- package/dist/chores/probes.d.ts.map +1 -1
- package/dist/chores/probes.js.map +1 -1
- package/dist/chores/prompt.d.ts.map +1 -1
- package/dist/chores/prompt.js.map +1 -1
- package/dist/chores/stack.d.ts.map +1 -1
- package/dist/chores/stack.js.map +1 -1
- package/dist/chores/verdict.d.ts +7 -1
- package/dist/chores/verdict.d.ts.map +1 -1
- package/dist/chores/verdict.js +8 -0
- package/dist/chores/verdict.js.map +1 -1
- package/dist/contracts/accounts.contract.d.ts.map +1 -1
- package/dist/contracts/accounts.contract.js.map +1 -1
- package/dist/contracts/activity.contract.d.ts +1 -0
- package/dist/contracts/activity.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.d.ts +13 -205
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +2 -1
- package/dist/contracts/agent.contract.js.map +1 -1
- package/dist/contracts/agents.contract.d.ts +228 -54
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +11 -2
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/automations.contract.d.ts +35 -17
- package/dist/contracts/automations.contract.d.ts.map +1 -1
- package/dist/contracts/automations.contract.js +10 -1
- package/dist/contracts/automations.contract.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts +0 -12
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/capabilities.contract.js +1 -1
- package/dist/contracts/capabilities.contract.js.map +1 -1
- package/dist/contracts/chores.contract.d.ts.map +1 -1
- package/dist/contracts/chores.contract.js.map +1 -1
- package/dist/contracts/ci.contract.d.ts +9 -0
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.js.map +1 -1
- package/dist/contracts/exit.contract.d.ts.map +1 -1
- package/dist/contracts/exit.contract.js +1 -1
- package/dist/contracts/exit.contract.js.map +1 -1
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/git.contract.d.ts +45 -6
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +9 -9
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/host.contract.d.ts +2 -0
- package/dist/contracts/host.contract.d.ts.map +1 -1
- package/dist/contracts/host.contract.js.map +1 -1
- package/dist/contracts/intentic.contract.js +1 -1
- package/dist/contracts/intentic.contract.js.map +1 -1
- package/dist/contracts/logs.contract.d.ts.map +1 -1
- package/dist/contracts/logs.contract.js.map +1 -1
- package/dist/contracts/loops.contract.d.ts.map +1 -1
- package/dist/contracts/loops.contract.js.map +1 -1
- package/dist/contracts/personas.contract.d.ts +39 -4
- package/dist/contracts/personas.contract.d.ts.map +1 -1
- package/dist/contracts/personas.contract.js +10 -1
- package/dist/contracts/personas.contract.js.map +1 -1
- package/dist/contracts/providers.contract.d.ts.map +1 -1
- package/dist/contracts/providers.contract.js.map +1 -1
- package/dist/contracts/runner.contract.d.ts +6 -80
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.js +2 -2
- package/dist/contracts/runner.contract.js.map +1 -1
- package/dist/contracts/safety.contract.d.ts.map +1 -1
- package/dist/contracts/safety.contract.js +1 -1
- package/dist/contracts/safety.contract.js.map +1 -1
- package/dist/contracts/secrets.contract.d.ts.map +1 -1
- package/dist/contracts/secrets.contract.js.map +1 -1
- package/dist/contracts/sessions.contract.d.ts +2 -41
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/sessions.contract.js +1 -1
- package/dist/contracts/sessions.contract.js.map +1 -1
- package/dist/contracts/settings.contract.d.ts +10 -10
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.js.map +1 -1
- package/dist/contracts/share.contract.d.ts.map +1 -1
- package/dist/contracts/share.contract.js.map +1 -1
- package/dist/contracts/skills.contract.d.ts.map +1 -1
- package/dist/contracts/skills.contract.js.map +1 -1
- package/dist/contracts/system.contract.d.ts +49 -73
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +12 -2
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/contracts/usage.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.js.map +1 -1
- package/dist/contracts/vpn.contract.d.ts.map +1 -1
- package/dist/contracts/vpn.contract.js +1 -1
- package/dist/contracts/vpn.contract.js.map +1 -1
- package/dist/contracts/webext.contract.d.ts.map +1 -1
- package/dist/contracts/webext.contract.js.map +1 -1
- package/dist/contracts/workflows.contract.d.ts +7 -6
- package/dist/contracts/workflows.contract.d.ts.map +1 -1
- package/dist/contracts/workflows.contract.js +12 -3
- package/dist/contracts/workflows.contract.js.map +1 -1
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/contracts/workspace.contract.js.map +1 -1
- package/dist/events/agent-events.d.ts +1237 -0
- package/dist/events/agent-events.d.ts.map +1 -0
- package/dist/events/agent-events.js +226 -0
- package/dist/events/agent-events.js.map +1 -0
- package/dist/events/cards.d.ts +404 -0
- package/dist/events/cards.d.ts.map +1 -0
- package/dist/events/cards.js +179 -0
- package/dist/events/cards.js.map +1 -0
- package/dist/events/resume.d.ts +23 -0
- package/dist/events/resume.d.ts.map +1 -0
- package/dist/events/resume.js +31 -0
- package/dist/events/resume.js.map +1 -0
- package/dist/events/system-events.d.ts +615 -0
- package/dist/events/system-events.d.ts.map +1 -0
- package/dist/events/system-events.js +64 -0
- package/dist/events/system-events.js.map +1 -0
- package/dist/events/transcript.d.ts +1755 -0
- package/dist/events/transcript.d.ts.map +1 -0
- package/dist/events/transcript.js +205 -0
- package/dist/events/transcript.js.map +1 -0
- package/dist/ids/conversation-ids.d.ts +8 -0
- package/dist/ids/conversation-ids.d.ts.map +1 -0
- package/dist/{conversation-ids.js → ids/conversation-ids.js} +13 -0
- package/dist/ids/conversation-ids.js.map +1 -0
- package/dist/ids/hostnames.d.ts.map +1 -0
- package/dist/ids/hostnames.js.map +1 -0
- package/dist/ids/session-names.d.ts.map +1 -0
- package/dist/ids/session-names.js.map +1 -0
- package/dist/ids/share-paths.d.ts.map +1 -0
- package/dist/ids/share-paths.js.map +1 -0
- package/dist/{tunnel-ids.d.ts → ids/tunnel-ids.d.ts} +1 -0
- package/dist/ids/tunnel-ids.d.ts.map +1 -0
- package/dist/{tunnel-ids.js → ids/tunnel-ids.js} +1 -0
- package/dist/ids/tunnel-ids.js.map +1 -0
- package/dist/index.d.ts +464 -447
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -47
- package/dist/index.js.map +1 -1
- package/dist/{agent-catalog.d.ts → models/agent-catalog.d.ts} +2 -2
- package/dist/models/agent-catalog.d.ts.map +1 -0
- package/dist/models/agent-catalog.js.map +1 -0
- package/dist/models/agent-runtimes.d.ts.map +1 -0
- package/dist/models/agent-runtimes.js.map +1 -0
- package/dist/{fast-tier.d.ts → models/fast-tier.d.ts} +1 -1
- package/dist/models/fast-tier.d.ts.map +1 -0
- package/dist/models/fast-tier.js.map +1 -0
- package/dist/models/model-order.d.ts.map +1 -0
- package/dist/models/model-order.js.map +1 -0
- package/dist/{model-pins.d.ts → models/model-pins.d.ts} +2 -4
- package/dist/models/model-pins.d.ts.map +1 -0
- package/dist/models/model-pins.js +22 -0
- package/dist/models/model-pins.js.map +1 -0
- package/dist/{model-roles.d.ts → models/model-roles.d.ts} +25 -30
- package/dist/models/model-roles.d.ts.map +1 -0
- package/dist/{model-roles.js → models/model-roles.js} +30 -27
- package/dist/models/model-roles.js.map +1 -0
- package/dist/{plan-pools.d.ts → models/plan-pools.d.ts} +1 -1
- package/dist/models/plan-pools.d.ts.map +1 -0
- package/dist/models/plan-pools.js.map +1 -0
- package/dist/models/prompt-complexity.d.ts.map +1 -0
- package/dist/models/prompt-complexity.js.map +1 -0
- package/dist/models/provider-specs.d.ts.map +1 -0
- package/dist/models/provider-specs.js.map +1 -0
- package/dist/policy/approvals-execution.d.ts.map +1 -0
- package/dist/policy/approvals-execution.js.map +1 -0
- package/dist/{batch-runs.d.ts → policy/batch-runs.d.ts} +5 -1
- package/dist/policy/batch-runs.d.ts.map +1 -0
- package/dist/{batch-runs.js → policy/batch-runs.js} +10 -7
- package/dist/policy/batch-runs.js.map +1 -0
- package/dist/policy/capability-env.d.ts.map +1 -0
- package/dist/policy/capability-env.js.map +1 -0
- package/dist/policy/capability-secrets.d.ts.map +1 -0
- package/dist/policy/capability-secrets.js.map +1 -0
- package/dist/{card-status.d.ts → policy/card-status.d.ts} +2 -2
- package/dist/policy/card-status.d.ts.map +1 -0
- package/dist/{card-status.js → policy/card-status.js} +1 -5
- package/dist/policy/card-status.js.map +1 -0
- package/dist/{command-classes.d.ts → policy/command-classes.d.ts} +6 -2
- package/dist/policy/command-classes.d.ts.map +1 -0
- package/dist/{command-classes.js → policy/command-classes.js} +48 -11
- package/dist/policy/command-classes.js.map +1 -0
- package/dist/{command-run.d.ts → policy/command-run.d.ts} +1 -1
- package/dist/policy/command-run.d.ts.map +1 -0
- package/dist/policy/command-run.js.map +1 -0
- package/dist/policy/control-scopes.d.ts +16 -0
- package/dist/policy/control-scopes.d.ts.map +1 -0
- package/dist/policy/control-scopes.js +26 -0
- package/dist/policy/control-scopes.js.map +1 -0
- package/dist/policy/credential-material.d.ts.map +1 -0
- package/dist/policy/credential-material.js.map +1 -0
- package/dist/policy/needs-action.d.ts.map +1 -0
- package/dist/policy/needs-action.js.map +1 -0
- package/dist/policy/output-fields.d.ts.map +1 -0
- package/dist/policy/output-fields.js.map +1 -0
- package/dist/policy/overlay-lint.d.ts.map +1 -0
- package/dist/policy/overlay-lint.js.map +1 -0
- package/dist/policy/owner-ticket.d.ts.map +1 -0
- package/dist/{owner-ticket.js → policy/owner-ticket.js} +1 -1
- package/dist/policy/owner-ticket.js.map +1 -0
- package/dist/{safety-policy.d.ts → policy/safety-policy.d.ts} +6 -5
- package/dist/policy/safety-policy.d.ts.map +1 -0
- package/dist/{safety-policy.js → policy/safety-policy.js} +12 -12
- package/dist/policy/safety-policy.js.map +1 -0
- package/dist/policy/search-globs.d.ts.map +1 -0
- package/dist/policy/search-globs.js.map +1 -0
- package/dist/protocol/container-requirements.d.ts +20 -0
- package/dist/protocol/container-requirements.d.ts.map +1 -0
- package/dist/protocol/container-requirements.js +23 -0
- package/dist/protocol/container-requirements.js.map +1 -0
- package/dist/{host-protocol.d.ts → protocol/host-protocol.d.ts} +1 -0
- package/dist/protocol/host-protocol.d.ts.map +1 -0
- package/dist/{host-protocol.js → protocol/host-protocol.js} +1 -0
- package/dist/protocol/host-protocol.js.map +1 -0
- package/dist/protocol/ingress-contract.d.ts.map +1 -0
- package/dist/{ingress-contract.js → protocol/ingress-contract.js} +1 -1
- package/dist/protocol/ingress-contract.js.map +1 -0
- package/dist/protocol/ingress-protocol.d.ts.map +1 -0
- package/dist/protocol/ingress-protocol.js.map +1 -0
- package/dist/protocol/listener-protocol.d.ts.map +1 -0
- package/dist/{listener-protocol.js → protocol/listener-protocol.js} +1 -1
- package/dist/protocol/listener-protocol.js.map +1 -0
- package/dist/{peer-dial.d.ts → protocol/peer-dial.d.ts} +4 -1
- package/dist/protocol/peer-dial.d.ts.map +1 -0
- package/dist/{peer-dial.js → protocol/peer-dial.js} +51 -10
- package/dist/protocol/peer-dial.js.map +1 -0
- package/dist/protocol/peer-mcp-server.d.ts.map +1 -0
- package/dist/protocol/peer-mcp-server.js.map +1 -0
- package/dist/protocol/request-id.d.ts.map +1 -0
- package/dist/protocol/request-id.js.map +1 -0
- package/dist/protocol/routes.d.ts.map +1 -0
- package/dist/protocol/routes.js.map +1 -0
- package/dist/{runner-protocol.d.ts → protocol/runner-protocol.d.ts} +1 -0
- package/dist/protocol/runner-protocol.d.ts.map +1 -0
- package/dist/{runner-protocol.js → protocol/runner-protocol.js} +2 -1
- package/dist/protocol/runner-protocol.js.map +1 -0
- package/dist/protocol/sse.d.ts.map +1 -0
- package/dist/protocol/sse.js.map +1 -0
- package/dist/{terminal-protocol.d.ts → protocol/terminal-protocol.d.ts} +1 -3
- package/dist/protocol/terminal-protocol.d.ts.map +1 -0
- package/dist/protocol/terminal-protocol.js.map +1 -0
- package/dist/protocol/webext-links.d.ts.map +1 -0
- package/dist/protocol/webext-links.js.map +1 -0
- package/dist/{webext-protocol.d.ts → protocol/webext-protocol.d.ts} +1 -0
- package/dist/protocol/webext-protocol.d.ts.map +1 -0
- package/dist/{webext-protocol.js → protocol/webext-protocol.js} +1 -0
- package/dist/protocol/webext-protocol.js.map +1 -0
- package/dist/schemas/activity.d.ts +2 -0
- package/dist/schemas/activity.d.ts.map +1 -1
- package/dist/schemas/activity.js +4 -0
- package/dist/schemas/activity.js.map +1 -1
- package/dist/schemas/agent.d.ts +17 -4
- package/dist/schemas/agent.d.ts.map +1 -1
- package/dist/schemas/agent.js +21 -4
- package/dist/schemas/agent.js.map +1 -1
- package/dist/schemas/agents.d.ts +17 -4
- package/dist/schemas/agents.d.ts.map +1 -1
- package/dist/schemas/agents.js +15 -4
- package/dist/schemas/agents.js.map +1 -1
- package/dist/schemas/approvals.d.ts.map +1 -1
- package/dist/schemas/approvals.js.map +1 -1
- package/dist/schemas/automations.d.ts +54 -28
- package/dist/schemas/automations.d.ts.map +1 -1
- package/dist/schemas/automations.js +26 -8
- package/dist/schemas/automations.js.map +1 -1
- package/dist/schemas/capabilities.d.ts +0 -8
- package/dist/schemas/capabilities.d.ts.map +1 -1
- package/dist/schemas/capabilities.js +0 -4
- package/dist/schemas/capabilities.js.map +1 -1
- package/dist/schemas/ci.d.ts +10 -0
- package/dist/schemas/ci.d.ts.map +1 -1
- package/dist/schemas/ci.js +9 -1
- package/dist/schemas/ci.js.map +1 -1
- package/dist/schemas/codebase-health.d.ts.map +1 -1
- package/dist/schemas/codebase-health.js.map +1 -1
- package/dist/schemas/devices.d.ts +90 -0
- package/dist/schemas/devices.d.ts.map +1 -1
- package/dist/schemas/devices.js +10 -1
- package/dist/schemas/devices.js.map +1 -1
- package/dist/schemas/engines.d.ts.map +1 -1
- package/dist/schemas/engines.js.map +1 -1
- package/dist/schemas/environment.d.ts.map +1 -1
- package/dist/schemas/environment.js.map +1 -1
- package/dist/schemas/exit.d.ts.map +1 -1
- package/dist/schemas/exit.js.map +1 -1
- package/dist/schemas/extension-updates.d.ts.map +1 -1
- package/dist/schemas/extension-updates.js.map +1 -1
- package/dist/schemas/git-history.d.ts.map +1 -1
- package/dist/schemas/git-history.js.map +1 -1
- package/dist/schemas/git.d.ts +80 -16
- package/dist/schemas/git.d.ts.map +1 -1
- package/dist/schemas/git.js +37 -25
- package/dist/schemas/git.js.map +1 -1
- package/dist/schemas/history.d.ts.map +1 -1
- package/dist/schemas/history.js.map +1 -1
- package/dist/schemas/hosts.d.ts.map +1 -1
- package/dist/schemas/hosts.js.map +1 -1
- package/dist/schemas/inventory.d.ts.map +1 -1
- package/dist/schemas/inventory.js.map +1 -1
- package/dist/schemas/issues.d.ts +0 -1
- package/dist/schemas/issues.d.ts.map +1 -1
- package/dist/schemas/issues.js +0 -1
- package/dist/schemas/issues.js.map +1 -1
- package/dist/schemas/logs.d.ts.map +1 -1
- package/dist/schemas/logs.js.map +1 -1
- package/dist/schemas/loops.d.ts.map +1 -1
- package/dist/schemas/loops.js +1 -1
- package/dist/schemas/loops.js.map +1 -1
- package/dist/schemas/maintenance.d.ts.map +1 -1
- package/dist/schemas/maintenance.js.map +1 -1
- package/dist/schemas/marketplace.d.ts +0 -4
- package/dist/schemas/marketplace.d.ts.map +1 -1
- package/dist/schemas/panels.d.ts.map +1 -1
- package/dist/schemas/panels.js.map +1 -1
- package/dist/schemas/personas.d.ts +49 -4
- package/dist/schemas/personas.d.ts.map +1 -1
- package/dist/schemas/personas.js +32 -5
- package/dist/schemas/personas.js.map +1 -1
- package/dist/schemas/plan-limits.d.ts +2 -4
- package/dist/schemas/plan-limits.d.ts.map +1 -1
- package/dist/schemas/plan-limits.js +5 -8
- package/dist/schemas/plan-limits.js.map +1 -1
- package/dist/schemas/ports.d.ts.map +1 -1
- package/dist/schemas/ports.js.map +1 -1
- package/dist/schemas/provider-oauth.d.ts.map +1 -1
- package/dist/schemas/provider-oauth.js.map +1 -1
- package/dist/schemas/provider-subscriptions.d.ts +1 -1
- package/dist/schemas/provider-subscriptions.d.ts.map +1 -1
- package/dist/schemas/provider-subscriptions.js +1 -1
- package/dist/schemas/provider-subscriptions.js.map +1 -1
- package/dist/schemas/public.d.ts.map +1 -1
- package/dist/schemas/public.js.map +1 -1
- package/dist/schemas/push.d.ts.map +1 -1
- package/dist/schemas/push.js.map +1 -1
- package/dist/schemas/secrets.d.ts.map +1 -1
- package/dist/schemas/secrets.js.map +1 -1
- package/dist/schemas/settings.d.ts +7 -5
- package/dist/schemas/settings.d.ts.map +1 -1
- package/dist/schemas/settings.js +18 -8
- package/dist/schemas/settings.js.map +1 -1
- package/dist/schemas/share.d.ts.map +1 -1
- package/dist/schemas/share.js.map +1 -1
- package/dist/schemas/shared.d.ts +4 -0
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/shared.js +3 -0
- package/dist/schemas/shared.js.map +1 -1
- package/dist/schemas/system.d.ts +6 -0
- package/dist/schemas/system.d.ts.map +1 -1
- package/dist/schemas/system.js +10 -0
- package/dist/schemas/system.js.map +1 -1
- package/dist/schemas/terminal.d.ts.map +1 -1
- package/dist/schemas/terminal.js.map +1 -1
- package/dist/schemas/usage.d.ts.map +1 -1
- package/dist/schemas/usage.js.map +1 -1
- package/dist/schemas/vpn.d.ts.map +1 -1
- package/dist/schemas/vpn.js.map +1 -1
- package/dist/schemas/webext.d.ts.map +1 -1
- package/dist/schemas/webext.js.map +1 -1
- package/dist/schemas/workflows.d.ts +66 -9
- package/dist/schemas/workflows.d.ts.map +1 -1
- package/dist/schemas/workflows.js +6 -5
- package/dist/schemas/workflows.js.map +1 -1
- package/dist/schemas/workspace-repos.d.ts.map +1 -1
- package/dist/schemas/workspace-repos.js.map +1 -1
- package/dist/schemas/workspace-search.d.ts.map +1 -1
- package/dist/schemas/workspace-search.js.map +1 -1
- package/dist/schemas/workspace-setup.d.ts.map +1 -1
- package/dist/schemas/workspace-setup.js.map +1 -1
- package/dist/schemas/workspace-tree.d.ts.map +1 -1
- package/dist/schemas/workspace-tree.js.map +1 -1
- package/dist/state/arrival.d.ts.map +1 -0
- package/dist/{arrival.js → state/arrival.js} +1 -1
- package/dist/state/arrival.js.map +1 -0
- package/dist/state/contract-lock.d.ts.map +1 -0
- package/dist/{contract-lock.js → state/contract-lock.js} +1 -1
- package/dist/state/contract-lock.js.map +1 -0
- package/dist/{definition.d.ts → state/definition.d.ts} +21 -17
- package/dist/state/definition.d.ts.map +1 -0
- package/dist/{definition.js → state/definition.js} +4 -4
- package/dist/state/definition.js.map +1 -0
- package/dist/state/history-state.d.ts.map +1 -0
- package/dist/{history-state.js → state/history-state.js} +1 -0
- package/dist/state/history-state.js.map +1 -0
- package/dist/state/runtime-state.d.ts.map +1 -0
- package/dist/state/runtime-state.js.map +1 -0
- package/dist/state/starter.d.ts.map +1 -0
- package/dist/state/starter.js.map +1 -0
- package/dist/state/state-portability.d.ts.map +1 -0
- package/dist/state/state-portability.js.map +1 -0
- package/dist/state/versions.d.ts.map +1 -0
- package/dist/state/versions.js.map +1 -0
- package/dist/{workspace-state.d.ts → state/workspace-state.d.ts} +8 -5
- package/dist/state/workspace-state.d.ts.map +1 -0
- package/dist/{workspace-state.js → state/workspace-state.js} +25 -1
- package/dist/state/workspace-state.js.map +1 -0
- package/dist/{documents.d.ts → text/documents.d.ts} +1 -1
- package/dist/text/documents.d.ts.map +1 -0
- package/dist/{documents.js → text/documents.js} +1 -1
- package/dist/text/documents.js.map +1 -0
- package/dist/text/embed.d.ts.map +1 -0
- package/dist/text/embed.js.map +1 -0
- package/dist/text/mentions.d.ts.map +1 -0
- package/dist/text/mentions.js.map +1 -0
- package/dist/text/model-answer.d.ts +3 -0
- package/dist/text/model-answer.d.ts.map +1 -0
- package/dist/text/model-answer.js +3 -0
- package/dist/text/model-answer.js.map +1 -0
- package/dist/text/path-refs.d.ts.map +1 -0
- package/dist/text/path-refs.js.map +1 -0
- package/dist/{shell-regions.d.ts → text/shell-regions.d.ts} +1 -1
- package/dist/text/shell-regions.d.ts.map +1 -0
- package/dist/text/shell-regions.js.map +1 -0
- package/dist/text/title.d.ts.map +1 -0
- package/dist/text/title.js.map +1 -0
- package/dist/{transcript-fold.d.ts → text/transcript-fold.d.ts} +2 -1
- package/dist/text/transcript-fold.d.ts.map +1 -0
- package/dist/{transcript-fold.js → text/transcript-fold.js} +2 -16
- package/dist/text/transcript-fold.js.map +1 -0
- package/dist/text/whisper.d.ts +3 -0
- package/dist/text/whisper.d.ts.map +1 -0
- package/dist/text/whisper.js +11 -0
- package/dist/text/whisper.js.map +1 -0
- package/dist/{workflow-faults.d.ts → text/workflow-faults.d.ts} +1 -1
- package/dist/text/workflow-faults.d.ts.map +1 -0
- package/dist/{workflow-faults.js → text/workflow-faults.js} +1 -1
- package/dist/text/workflow-faults.js.map +1 -0
- package/package.json +70 -70
- package/src/chores/chores.test.ts +4 -10
- package/src/chores/chores.ts +148 -392
- package/src/chores/digest.ts +8 -28
- package/src/chores/extension-update.ts +3 -8
- package/src/chores/fix-deps.ts +4 -18
- package/src/chores/index.ts +2 -2
- package/src/chores/probes.test.ts +7 -43
- package/src/chores/probes.ts +62 -167
- package/src/chores/prompt.ts +10 -34
- package/src/chores/stack.test.ts +6 -45
- package/src/chores/stack.ts +27 -118
- package/src/chores/verdict.test.ts +101 -80
- package/src/chores/verdict.ts +54 -99
- package/src/contracts/accounts.contract.ts +4 -19
- package/src/contracts/agent.contract.ts +7 -22
- package/src/contracts/agents.contract.ts +25 -71
- package/src/contracts/automations.contract.ts +14 -30
- package/src/contracts/capabilities.contract.ts +8 -35
- package/src/contracts/chores.contract.ts +4 -15
- package/src/contracts/endpoints.contract.ts +5 -22
- package/src/contracts/exit.contract.ts +7 -30
- package/src/contracts/extensions.contract.ts +8 -30
- package/src/contracts/git.contract.ts +25 -49
- package/src/contracts/host.contract.ts +9 -44
- package/src/contracts/intentic.contract.ts +1 -1
- package/src/contracts/logs.contract.ts +3 -13
- package/src/contracts/loops.contract.ts +9 -40
- package/src/contracts/personas.contract.ts +22 -30
- package/src/contracts/providers.contract.ts +4 -17
- package/src/contracts/runner.contract.ts +12 -39
- package/src/contracts/safety.contract.ts +5 -14
- package/src/contracts/secrets.contract.ts +4 -22
- package/src/contracts/sessions.contract.ts +1 -1
- package/src/contracts/settings.contract.ts +4 -10
- package/src/contracts/share.contract.ts +3 -9
- package/src/contracts/skills.contract.ts +4 -15
- package/src/contracts/system.contract.ts +26 -52
- package/src/contracts/usage.contract.ts +7 -21
- package/src/contracts/vpn.contract.ts +9 -16
- package/src/contracts/webext.contract.ts +9 -25
- package/src/contracts/workflows.contract.ts +34 -58
- package/src/contracts/workspace.contract.ts +19 -50
- package/src/events/agent-events.ts +345 -0
- package/src/events/cards.ts +286 -0
- package/src/{events.test.ts → events/resume.test.ts} +4 -19
- package/src/events/resume.ts +60 -0
- package/src/events/system-events.ts +139 -0
- package/src/events/transcript.ts +320 -0
- package/src/{conversation-ids.test.ts → ids/conversation-ids.test.ts} +25 -13
- package/src/ids/conversation-ids.ts +178 -0
- package/src/ids/hostnames.ts +129 -0
- package/src/ids/session-names.ts +29 -0
- package/src/ids/share-paths.ts +43 -0
- package/src/{tunnel-ids.test.ts → ids/tunnel-ids.test.ts} +1 -14
- package/src/ids/tunnel-ids.ts +29 -0
- package/src/index.ts +71 -88
- package/src/{agent-catalog.test.ts → models/agent-catalog.test.ts} +19 -93
- package/src/models/agent-catalog.ts +174 -0
- package/src/models/agent-runtimes.ts +201 -0
- package/src/models/capability-ledger.test.ts +84 -0
- package/src/{fast-tier.test.ts → models/fast-tier.test.ts} +7 -18
- package/src/models/fast-tier.ts +36 -0
- package/src/{model-order.test.ts → models/model-order.test.ts} +19 -40
- package/src/models/model-order.ts +163 -0
- package/src/models/model-pins.test.ts +87 -0
- package/src/models/model-pins.ts +57 -0
- package/src/models/model-roles.test.ts +38 -0
- package/src/models/model-roles.ts +180 -0
- package/src/{plan-pools.test.ts → models/plan-pools.test.ts} +6 -11
- package/src/models/plan-pools.ts +65 -0
- package/src/{prompt-complexity.test.ts → models/prompt-complexity.test.ts} +8 -60
- package/src/models/prompt-complexity.ts +215 -0
- package/src/{provider-specs.test.ts → models/provider-specs.test.ts} +18 -47
- package/src/models/provider-specs.ts +272 -0
- package/src/policy/approvals-execution.ts +58 -0
- package/src/{batch-runs.test.ts → policy/batch-runs.test.ts} +4 -20
- package/src/policy/batch-runs.ts +137 -0
- package/src/policy/capability-secrets.ts +5 -0
- package/src/{card-status.ts → policy/card-status.ts} +11 -26
- package/src/{command-classes.test.ts → policy/command-classes.test.ts} +11 -118
- package/src/policy/command-classes.ts +395 -0
- package/src/policy/command-run.ts +65 -0
- package/src/policy/control-scopes.ts +38 -0
- package/src/{credential-material.test.ts → policy/credential-material.test.ts} +4 -26
- package/src/policy/credential-material.ts +91 -0
- package/src/policy/needs-action.ts +5 -0
- package/src/policy/output-fields.ts +86 -0
- package/src/policy/overlay-lint.ts +100 -0
- package/src/{owner-ticket.test.ts → policy/owner-ticket.test.ts} +1 -1
- package/src/{owner-ticket.ts → policy/owner-ticket.ts} +9 -31
- package/src/policy/safety-policy.test.ts +84 -0
- package/src/policy/safety-policy.ts +142 -0
- package/src/policy/search-globs.ts +60 -0
- package/src/protocol/container-requirements.test.ts +72 -0
- package/src/protocol/container-requirements.ts +58 -0
- package/src/protocol/host-protocol.ts +29 -0
- package/src/protocol/ingress-contract.ts +103 -0
- package/src/{ingress-protocol.test.ts → protocol/ingress-protocol.test.ts} +25 -90
- package/src/protocol/ingress-protocol.ts +441 -0
- package/src/protocol/listener-protocol.ts +75 -0
- package/src/{peer-dial.test.ts → protocol/peer-dial.test.ts} +52 -1
- package/src/protocol/peer-dial.ts +207 -0
- package/src/{peer-mcp-server.ts → protocol/peer-mcp-server.ts} +16 -41
- package/src/protocol/request-id.ts +5 -0
- package/src/{routes.test.ts → protocol/routes.test.ts} +14 -22
- package/src/protocol/routes.ts +159 -0
- package/src/protocol/runner-protocol.ts +197 -0
- package/src/protocol/terminal-protocol.ts +13 -0
- package/src/protocol/webext-links.ts +50 -0
- package/src/protocol/webext-protocol.ts +24 -0
- package/src/schemas/activity.ts +22 -30
- package/src/schemas/agent.ts +130 -238
- package/src/schemas/agents.ts +165 -483
- package/src/schemas/approvals.ts +23 -71
- package/src/schemas/automations.ts +145 -249
- package/src/schemas/capabilities.ts +127 -414
- package/src/schemas/ci.ts +56 -108
- package/src/schemas/codebase-health.ts +7 -11
- package/src/schemas/devices.ts +98 -321
- package/src/schemas/engines.ts +16 -44
- package/src/schemas/environment.ts +41 -91
- package/src/schemas/exit.ts +24 -81
- package/src/schemas/extension-updates.ts +42 -87
- package/src/schemas/git-history.ts +30 -84
- package/src/schemas/git.ts +141 -256
- package/src/schemas/history.ts +14 -40
- package/src/schemas/hosts.ts +9 -15
- package/src/schemas/inventory.ts +8 -10
- package/src/schemas/issues.ts +66 -134
- package/src/schemas/logs.ts +15 -34
- package/src/schemas/loops.ts +46 -163
- package/src/schemas/maintenance.ts +47 -172
- package/src/schemas/panels.ts +20 -45
- package/src/schemas/personas.ts +85 -168
- package/src/schemas/plan-limits.ts +58 -197
- package/src/schemas/ports.ts +14 -32
- package/src/schemas/provider-oauth.ts +23 -76
- package/src/schemas/provider-subscriptions.ts +4 -13
- package/src/schemas/public.ts +4 -15
- package/src/schemas/push.ts +8 -36
- package/src/schemas/secrets.ts +20 -64
- package/src/schemas/settings.ts +177 -597
- package/src/schemas/share.ts +14 -32
- package/src/schemas/shared.ts +14 -13
- package/src/schemas/system.ts +46 -78
- package/src/schemas/terminal.ts +41 -120
- package/src/schemas/usage.ts +44 -233
- package/src/schemas/version-seam.test.ts +9 -26
- package/src/schemas/vpn.ts +27 -64
- package/src/schemas/webext.ts +22 -53
- package/src/schemas/workflows.ts +57 -183
- package/src/schemas/workspace-repos.ts +12 -24
- package/src/schemas/workspace-search.ts +17 -35
- package/src/schemas/workspace-setup.ts +4 -11
- package/src/schemas/workspace-tree.ts +32 -91
- package/src/state/arrival.ts +109 -0
- package/src/state/contract-lock.test.ts +17 -0
- package/src/state/contract-lock.ts +49 -0
- package/src/state/definition.ts +143 -0
- package/src/state/history-state.ts +103 -0
- package/src/{runtime-state.test.ts → state/runtime-state.test.ts} +3 -10
- package/src/state/runtime-state.ts +62 -0
- package/src/state/starter.ts +5 -0
- package/src/state/state-portability.ts +27 -0
- package/src/state/versions.ts +26 -0
- package/src/{workspace-state.test.ts → state/workspace-state.test.ts} +65 -173
- package/src/state/workspace-state.ts +669 -0
- package/src/{documents.test.ts → text/documents.test.ts} +1 -1
- package/src/text/documents.ts +42 -0
- package/src/text/embed.ts +132 -0
- package/src/text/mentions.ts +21 -0
- package/src/text/model-answer.ts +9 -0
- package/src/text/path-refs.ts +39 -0
- package/src/text/shell-regions.ts +224 -0
- package/src/{title.test.ts → text/title.test.ts} +13 -32
- package/src/text/title.ts +202 -0
- package/src/{transcript-fold.test.ts → text/transcript-fold.test.ts} +5 -83
- package/src/{transcript-fold.ts → text/transcript-fold.ts} +65 -170
- package/src/text/whisper.test.ts +19 -0
- package/src/text/whisper.ts +17 -0
- package/src/{workflow-faults.test.ts → text/workflow-faults.test.ts} +6 -24
- package/src/{workflow-faults.ts → text/workflow-faults.ts} +20 -60
- package/dist/agent-catalog.d.ts.map +0 -1
- package/dist/agent-catalog.js.map +0 -1
- package/dist/agent-runtimes.d.ts.map +0 -1
- package/dist/agent-runtimes.js.map +0 -1
- package/dist/approvals-execution.d.ts.map +0 -1
- package/dist/approvals-execution.js.map +0 -1
- package/dist/arrival.d.ts.map +0 -1
- package/dist/arrival.js.map +0 -1
- package/dist/batch-runs.d.ts.map +0 -1
- package/dist/batch-runs.js.map +0 -1
- package/dist/capability-env.d.ts.map +0 -1
- package/dist/capability-env.js.map +0 -1
- package/dist/capability-secrets.d.ts.map +0 -1
- package/dist/capability-secrets.js.map +0 -1
- package/dist/card-status.d.ts.map +0 -1
- package/dist/card-status.js.map +0 -1
- package/dist/command-classes.d.ts.map +0 -1
- package/dist/command-classes.js.map +0 -1
- package/dist/command-run.d.ts.map +0 -1
- package/dist/command-run.js.map +0 -1
- package/dist/contract-lock.d.ts.map +0 -1
- package/dist/contract-lock.js.map +0 -1
- package/dist/conversation-ids.d.ts +0 -4
- package/dist/conversation-ids.d.ts.map +0 -1
- package/dist/conversation-ids.js.map +0 -1
- package/dist/credential-material.d.ts.map +0 -1
- package/dist/credential-material.js.map +0 -1
- package/dist/definition.d.ts.map +0 -1
- package/dist/definition.js.map +0 -1
- package/dist/documents.d.ts.map +0 -1
- package/dist/documents.js.map +0 -1
- package/dist/embed.d.ts.map +0 -1
- package/dist/embed.js.map +0 -1
- package/dist/events.d.ts +0 -4336
- package/dist/events.d.ts.map +0 -1
- package/dist/events.js +0 -725
- package/dist/events.js.map +0 -1
- package/dist/fast-tier.d.ts.map +0 -1
- package/dist/fast-tier.js.map +0 -1
- package/dist/history-state.d.ts.map +0 -1
- package/dist/history-state.js.map +0 -1
- package/dist/host-protocol.d.ts.map +0 -1
- package/dist/host-protocol.js.map +0 -1
- package/dist/hostnames.d.ts.map +0 -1
- package/dist/hostnames.js.map +0 -1
- package/dist/ingress-contract.d.ts.map +0 -1
- package/dist/ingress-contract.js.map +0 -1
- package/dist/ingress-protocol.d.ts.map +0 -1
- package/dist/ingress-protocol.js.map +0 -1
- package/dist/listener-protocol.d.ts.map +0 -1
- package/dist/listener-protocol.js.map +0 -1
- package/dist/mentions.d.ts.map +0 -1
- package/dist/mentions.js.map +0 -1
- package/dist/model-order.d.ts.map +0 -1
- package/dist/model-order.js.map +0 -1
- package/dist/model-pins.d.ts.map +0 -1
- package/dist/model-pins.js +0 -45
- package/dist/model-pins.js.map +0 -1
- package/dist/model-roles.d.ts.map +0 -1
- package/dist/model-roles.js.map +0 -1
- package/dist/needs-action.d.ts.map +0 -1
- package/dist/needs-action.js.map +0 -1
- package/dist/output-fields.d.ts.map +0 -1
- package/dist/output-fields.js.map +0 -1
- package/dist/overlay-lint.d.ts.map +0 -1
- package/dist/overlay-lint.js.map +0 -1
- package/dist/owner-ticket.d.ts.map +0 -1
- package/dist/owner-ticket.js.map +0 -1
- package/dist/path-refs.d.ts.map +0 -1
- package/dist/path-refs.js.map +0 -1
- package/dist/peer-dial.d.ts.map +0 -1
- package/dist/peer-dial.js.map +0 -1
- package/dist/peer-mcp-server.d.ts.map +0 -1
- package/dist/peer-mcp-server.js.map +0 -1
- package/dist/plan-pools.d.ts.map +0 -1
- package/dist/plan-pools.js.map +0 -1
- package/dist/prompt-complexity.d.ts.map +0 -1
- package/dist/prompt-complexity.js.map +0 -1
- package/dist/provider-specs.d.ts.map +0 -1
- package/dist/provider-specs.js.map +0 -1
- package/dist/request-id.d.ts.map +0 -1
- package/dist/request-id.js.map +0 -1
- package/dist/routes.d.ts.map +0 -1
- package/dist/routes.js.map +0 -1
- package/dist/runner-protocol.d.ts.map +0 -1
- package/dist/runner-protocol.js.map +0 -1
- package/dist/runtime-state.d.ts.map +0 -1
- package/dist/runtime-state.js.map +0 -1
- package/dist/safety-policy.d.ts.map +0 -1
- package/dist/safety-policy.js.map +0 -1
- package/dist/schemas/context.d.ts +0 -30
- package/dist/schemas/context.d.ts.map +0 -1
- package/dist/schemas/context.js +0 -34
- package/dist/schemas/context.js.map +0 -1
- package/dist/search-globs.d.ts.map +0 -1
- package/dist/search-globs.js.map +0 -1
- package/dist/session-names.d.ts.map +0 -1
- package/dist/session-names.js.map +0 -1
- package/dist/share-paths.d.ts.map +0 -1
- package/dist/share-paths.js.map +0 -1
- package/dist/shell-regions.d.ts.map +0 -1
- package/dist/shell-regions.js.map +0 -1
- package/dist/sse.d.ts.map +0 -1
- package/dist/sse.js.map +0 -1
- package/dist/starter.d.ts.map +0 -1
- package/dist/starter.js.map +0 -1
- package/dist/state-portability.d.ts.map +0 -1
- package/dist/state-portability.js.map +0 -1
- package/dist/terminal-protocol.d.ts.map +0 -1
- package/dist/terminal-protocol.js.map +0 -1
- package/dist/title.d.ts.map +0 -1
- package/dist/title.js.map +0 -1
- package/dist/transcript-fold.d.ts.map +0 -1
- package/dist/transcript-fold.js.map +0 -1
- package/dist/tunnel-ids.d.ts.map +0 -1
- package/dist/tunnel-ids.js.map +0 -1
- package/dist/versions.d.ts.map +0 -1
- package/dist/versions.js.map +0 -1
- package/dist/webext-links.d.ts.map +0 -1
- package/dist/webext-links.js.map +0 -1
- package/dist/webext-protocol.d.ts.map +0 -1
- package/dist/webext-protocol.js.map +0 -1
- package/dist/workflow-faults.d.ts.map +0 -1
- package/dist/workflow-faults.js.map +0 -1
- package/dist/workspace-state.d.ts.map +0 -1
- package/dist/workspace-state.js.map +0 -1
- package/src/agent-catalog.ts +0 -316
- package/src/agent-runtimes.ts +0 -419
- package/src/approvals-execution.ts +0 -96
- package/src/arrival.ts +0 -160
- package/src/batch-runs.ts +0 -188
- package/src/capability-ledger.test.ts +0 -140
- package/src/capability-secrets.ts +0 -20
- package/src/command-classes.ts +0 -617
- package/src/command-run.ts +0 -78
- package/src/contract-lock.test.ts +0 -23
- package/src/contract-lock.ts +0 -66
- package/src/conversation-ids.ts +0 -207
- package/src/credential-material.ts +0 -181
- package/src/definition.ts +0 -207
- package/src/documents.ts +0 -67
- package/src/embed.ts +0 -164
- package/src/events.ts +0 -1870
- package/src/fast-tier.ts +0 -72
- package/src/history-state.ts +0 -174
- package/src/host-protocol.ts +0 -36
- package/src/hostnames.ts +0 -180
- package/src/ingress-contract.ts +0 -157
- package/src/ingress-protocol.ts +0 -625
- package/src/listener-protocol.ts +0 -96
- package/src/mentions.ts +0 -25
- package/src/model-order.ts +0 -262
- package/src/model-pins.test.ts +0 -202
- package/src/model-pins.ts +0 -183
- package/src/model-roles.ts +0 -224
- package/src/needs-action.ts +0 -14
- package/src/output-fields.ts +0 -111
- package/src/overlay-lint.ts +0 -116
- package/src/path-refs.ts +0 -59
- package/src/peer-dial.ts +0 -163
- package/src/plan-pools.ts +0 -92
- package/src/prompt-complexity.ts +0 -334
- package/src/provider-specs.ts +0 -432
- package/src/request-id.ts +0 -41
- package/src/routes.ts +0 -219
- package/src/runner-protocol.ts +0 -239
- package/src/runtime-state.ts +0 -140
- package/src/safety-policy.test.ts +0 -88
- package/src/safety-policy.ts +0 -258
- package/src/schemas/context.ts +0 -87
- package/src/search-globs.ts +0 -76
- package/src/session-names.ts +0 -44
- package/src/share-paths.ts +0 -68
- package/src/shell-regions.ts +0 -289
- package/src/starter.ts +0 -13
- package/src/state-portability.ts +0 -56
- package/src/terminal-protocol.ts +0 -16
- package/src/title.ts +0 -267
- package/src/tunnel-ids.ts +0 -57
- package/src/versions.ts +0 -48
- package/src/webext-links.ts +0 -90
- package/src/webext-protocol.ts +0 -27
- package/src/workspace-state.ts +0 -1096
- /package/dist/{hostnames.d.ts → ids/hostnames.d.ts} +0 -0
- /package/dist/{hostnames.js → ids/hostnames.js} +0 -0
- /package/dist/{session-names.d.ts → ids/session-names.d.ts} +0 -0
- /package/dist/{session-names.js → ids/session-names.js} +0 -0
- /package/dist/{share-paths.d.ts → ids/share-paths.d.ts} +0 -0
- /package/dist/{share-paths.js → ids/share-paths.js} +0 -0
- /package/dist/{agent-catalog.js → models/agent-catalog.js} +0 -0
- /package/dist/{agent-runtimes.d.ts → models/agent-runtimes.d.ts} +0 -0
- /package/dist/{agent-runtimes.js → models/agent-runtimes.js} +0 -0
- /package/dist/{fast-tier.js → models/fast-tier.js} +0 -0
- /package/dist/{model-order.d.ts → models/model-order.d.ts} +0 -0
- /package/dist/{model-order.js → models/model-order.js} +0 -0
- /package/dist/{plan-pools.js → models/plan-pools.js} +0 -0
- /package/dist/{prompt-complexity.d.ts → models/prompt-complexity.d.ts} +0 -0
- /package/dist/{prompt-complexity.js → models/prompt-complexity.js} +0 -0
- /package/dist/{provider-specs.d.ts → models/provider-specs.d.ts} +0 -0
- /package/dist/{provider-specs.js → models/provider-specs.js} +0 -0
- /package/dist/{approvals-execution.d.ts → policy/approvals-execution.d.ts} +0 -0
- /package/dist/{approvals-execution.js → policy/approvals-execution.js} +0 -0
- /package/dist/{capability-env.d.ts → policy/capability-env.d.ts} +0 -0
- /package/dist/{capability-env.js → policy/capability-env.js} +0 -0
- /package/dist/{capability-secrets.d.ts → policy/capability-secrets.d.ts} +0 -0
- /package/dist/{capability-secrets.js → policy/capability-secrets.js} +0 -0
- /package/dist/{command-run.js → policy/command-run.js} +0 -0
- /package/dist/{credential-material.d.ts → policy/credential-material.d.ts} +0 -0
- /package/dist/{credential-material.js → policy/credential-material.js} +0 -0
- /package/dist/{needs-action.d.ts → policy/needs-action.d.ts} +0 -0
- /package/dist/{needs-action.js → policy/needs-action.js} +0 -0
- /package/dist/{output-fields.d.ts → policy/output-fields.d.ts} +0 -0
- /package/dist/{output-fields.js → policy/output-fields.js} +0 -0
- /package/dist/{overlay-lint.d.ts → policy/overlay-lint.d.ts} +0 -0
- /package/dist/{overlay-lint.js → policy/overlay-lint.js} +0 -0
- /package/dist/{owner-ticket.d.ts → policy/owner-ticket.d.ts} +0 -0
- /package/dist/{search-globs.d.ts → policy/search-globs.d.ts} +0 -0
- /package/dist/{search-globs.js → policy/search-globs.js} +0 -0
- /package/dist/{ingress-contract.d.ts → protocol/ingress-contract.d.ts} +0 -0
- /package/dist/{ingress-protocol.d.ts → protocol/ingress-protocol.d.ts} +0 -0
- /package/dist/{ingress-protocol.js → protocol/ingress-protocol.js} +0 -0
- /package/dist/{listener-protocol.d.ts → protocol/listener-protocol.d.ts} +0 -0
- /package/dist/{peer-mcp-server.d.ts → protocol/peer-mcp-server.d.ts} +0 -0
- /package/dist/{peer-mcp-server.js → protocol/peer-mcp-server.js} +0 -0
- /package/dist/{request-id.d.ts → protocol/request-id.d.ts} +0 -0
- /package/dist/{request-id.js → protocol/request-id.js} +0 -0
- /package/dist/{routes.d.ts → protocol/routes.d.ts} +0 -0
- /package/dist/{routes.js → protocol/routes.js} +0 -0
- /package/dist/{sse.d.ts → protocol/sse.d.ts} +0 -0
- /package/dist/{sse.js → protocol/sse.js} +0 -0
- /package/dist/{terminal-protocol.js → protocol/terminal-protocol.js} +0 -0
- /package/dist/{webext-links.d.ts → protocol/webext-links.d.ts} +0 -0
- /package/dist/{webext-links.js → protocol/webext-links.js} +0 -0
- /package/dist/{arrival.d.ts → state/arrival.d.ts} +0 -0
- /package/dist/{contract-lock.d.ts → state/contract-lock.d.ts} +0 -0
- /package/dist/{history-state.d.ts → state/history-state.d.ts} +0 -0
- /package/dist/{runtime-state.d.ts → state/runtime-state.d.ts} +0 -0
- /package/dist/{runtime-state.js → state/runtime-state.js} +0 -0
- /package/dist/{starter.d.ts → state/starter.d.ts} +0 -0
- /package/dist/{starter.js → state/starter.js} +0 -0
- /package/dist/{state-portability.d.ts → state/state-portability.d.ts} +0 -0
- /package/dist/{state-portability.js → state/state-portability.js} +0 -0
- /package/dist/{versions.d.ts → state/versions.d.ts} +0 -0
- /package/dist/{versions.js → state/versions.js} +0 -0
- /package/dist/{embed.d.ts → text/embed.d.ts} +0 -0
- /package/dist/{embed.js → text/embed.js} +0 -0
- /package/dist/{mentions.d.ts → text/mentions.d.ts} +0 -0
- /package/dist/{mentions.js → text/mentions.js} +0 -0
- /package/dist/{path-refs.d.ts → text/path-refs.d.ts} +0 -0
- /package/dist/{path-refs.js → text/path-refs.js} +0 -0
- /package/dist/{shell-regions.js → text/shell-regions.js} +0 -0
- /package/dist/{title.d.ts → text/title.d.ts} +0 -0
- /package/dist/{title.js → text/title.js} +0 -0
- /package/src/{hostnames.test.ts → ids/hostnames.test.ts} +0 -0
- /package/src/{share-paths.test.ts → ids/share-paths.test.ts} +0 -0
- /package/src/{capability-env.ts → policy/capability-env.ts} +0 -0
- /package/src/{overlay-lint.test.ts → policy/overlay-lint.test.ts} +0 -0
- /package/src/{search-globs.test.ts → policy/search-globs.test.ts} +0 -0
- /package/src/{ingress-contract.test.ts → protocol/ingress-contract.test.ts} +0 -0
- /package/src/{peer-mcp-server.test.ts → protocol/peer-mcp-server.test.ts} +0 -0
- /package/src/{sse.ts → protocol/sse.ts} +0 -0
- /package/src/{versions.test.ts → state/versions.test.ts} +0 -0
- /package/src/{embed.test.ts → text/embed.test.ts} +0 -0
- /package/src/{mentions.test.ts → text/mentions.test.ts} +0 -0
- /package/src/{path-refs.test.ts → text/path-refs.test.ts} +0 -0
package/src/fast-tier.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { compareCheapestFirst, isCheaperRung } from "./model-order.js";
|
|
2
|
-
import { parsePinned } from "./model-pins.js";
|
|
3
|
-
import type { AgentProvider } from "./schemas/agent.js";
|
|
4
|
-
|
|
5
|
-
/* WHICH MODEL A DOWNGRADED TURN ACTUALLY RUNS ON, the second half of automatic tier selection.
|
|
6
|
-
* prompt-complexity.ts decides a turn COULD be cheaper; this decides whether there is anything cheaper to put
|
|
7
|
-
* it on, and names it.
|
|
8
|
-
*
|
|
9
|
-
* THERE IS NO "STANDARD TIER" SETTING, and its absence is the design rather than an omission. The standard tier
|
|
10
|
-
* is whatever the user already picked for this conversation. So this mechanism can only ever route DOWN, from a
|
|
11
|
-
* model somebody chose to a cheaper rung of the same catalog, which means the worst case of a wrong answer is
|
|
12
|
-
* one turn's quality on a model the user can see and correct, never a bill they did not ask for. Every
|
|
13
|
-
* ambiguous case in this file therefore resolves to `undefined`, which the caller reads as "run what they
|
|
14
|
-
* asked for".
|
|
15
|
-
*
|
|
16
|
-
* THE PROVIDER IS NEVER CROSSED, and this is the constraint the rest of the app imposes rather than one this
|
|
17
|
-
* file would have chosen. A conversation's provider session is resumed only while the selection still matches
|
|
18
|
-
* the runtime and account that minted it (turnRequest.ts `resumes`, which compares provider, account and
|
|
19
|
-
* harness, and pointedly NOT model). A model swap inside one provider is free, and the session carries on. A
|
|
20
|
-
* provider swap RETIRES the session and cuts a new segment, which throws away the very context that made the
|
|
21
|
-
* follow-up cheap to answer. So a cross-provider pin here is dropped rather than honoured: saving a fraction of
|
|
22
|
-
* a cent by starting the conversation over is not a saving.
|
|
23
|
-
*
|
|
24
|
-
* THE ORDER IS A LADDER, for the reason model-pins.ts is one, but a shorter one: the caller spends the head
|
|
25
|
-
* and falls back to the user's own pick, rather than walking rungs. A downgrade that cannot be started is not
|
|
26
|
-
* worth a second attempt when the honest answer (their model) is sitting right there. */
|
|
27
|
-
|
|
28
|
-
export interface FastTierInput {
|
|
29
|
-
// The provider this turn is on. Both the pick and every candidate belong to it; see above.
|
|
30
|
-
readonly provider: AgentProvider;
|
|
31
|
-
// The model the user picked, i.e. the standard tier and the ceiling. Empty when the composer has not
|
|
32
|
-
// resolved one yet, which resolves to no downgrade: there is nothing to be cheaper THAN.
|
|
33
|
-
readonly model: string;
|
|
34
|
-
// That provider's catalog as the caller can see it. Empty is a real state (a catalog that has not loaded),
|
|
35
|
-
// and it resolves to no downgrade rather than to a guess.
|
|
36
|
-
readonly models: readonly string[];
|
|
37
|
-
// settings.autoFastModels: an ordered list of `${provider}:${modelId}` keys (modelPinKey), or empty for
|
|
38
|
-
// Auto. Entries naming another provider are dropped, not honoured.
|
|
39
|
-
readonly pinned: readonly string[];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* THE CHEAPER MODEL TO RUN THIS TURN ON, or undefined for "there isn't one, use their pick".
|
|
43
|
-
*
|
|
44
|
-
* A PIN IS TAKEN VERBATIM against the catalog, the same call resolveRoleModels makes and for the same reason:
|
|
45
|
-
* the model picker offers a custom-id escape hatch for a model the static catalog has not caught up with, and
|
|
46
|
-
* second-guessing the id here would run a different model than the settings row names. It is still checked for
|
|
47
|
-
* being CHEAPER, because that is not a fact about the catalog, it is a fact about the id, and a pin that is not
|
|
48
|
-
* cheaper than the pick is not a downgrade at all.
|
|
49
|
-
*
|
|
50
|
-
* AUTO IS THE CHEAPEST ROW THE PROVIDER PUBLISHES, read through the same cheap-end order the quick model uses,
|
|
51
|
-
* so the two features cannot disagree about which rung is the cheap one. Derived, never stored: connect an
|
|
52
|
-
* account tomorrow and the answer improves by itself, exactly as a one-shot role's empty list does.
|
|
53
|
-
*
|
|
54
|
-
* NOTHING CHEAPER THAN THE PICK ⇒ UNDEFINED, and that is the common case worth being exact about rather than
|
|
55
|
-
* the edge case: a user already working on the cheap rung has nowhere to be sent, and a user on a model whose
|
|
56
|
-
* family this build does not recognize is not going to be downgraded on a guess (isCheaperRung). */
|
|
57
|
-
export const fastTierModel = (input: FastTierInput): string | undefined => {
|
|
58
|
-
if (input.model === "") {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
|
-
const pinned = input.pinned
|
|
62
|
-
.flatMap((key) => {
|
|
63
|
-
const choice = parsePinned(key);
|
|
64
|
-
return choice === undefined || choice.provider !== input.provider ? [] : [choice.model];
|
|
65
|
-
})
|
|
66
|
-
.find((model) => isCheaperRung(model, input.model));
|
|
67
|
-
if (pinned !== undefined) {
|
|
68
|
-
return pinned;
|
|
69
|
-
}
|
|
70
|
-
const cheapest = input.models.toSorted(compareCheapestFirst)[0];
|
|
71
|
-
return cheapest !== undefined && isCheaperRung(cheapest, input.model) ? cheapest : undefined;
|
|
72
|
-
};
|
package/src/history-state.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import type { StateFile } from "./state-portability.js";
|
|
2
|
-
|
|
3
|
-
/* WHAT LIVES ON /history, the second half of the daemon's state, and the half nothing declared until an
|
|
4
|
-
* export had to reason about it.
|
|
5
|
-
*
|
|
6
|
-
* `WORKSPACE_STATE_FILES` covers `<workspace>/.intentic/`, which is where the manifests live. It is not where
|
|
7
|
-
* the machinery lives. Every repo's REAL git dir is here (a repo's in-tree `.git` is a pointer file, see
|
|
8
|
-
* git/repo-git-dirs.ts for the invariant that forces it), and so are the fleet registry, the turn journal, the
|
|
9
|
-
* ledgers, the checkpoint scopes and the isolated agents' checkouts. A "workspace export" that took `/work`
|
|
10
|
-
* alone would carry a tree of repos with dangling gitdir pointers, every git command in the restored sandbox
|
|
11
|
-
* answering `fatal: not a git repository`, and an empty agent board.
|
|
12
|
-
*
|
|
13
|
-
* The two tables stay separate rather than becoming one keyed by volume, because they answer different
|
|
14
|
-
* questions. A `.intentic` entry also declares which browser QUERY it makes stale, since the file watcher
|
|
15
|
-
* reports it; nothing here is watched at all (that is the point of the volume), so an `invalidates` field on
|
|
16
|
-
* these entries would be a column of empty arrays. What they share is the portability class, and that is
|
|
17
|
-
* imported rather than duplicated.
|
|
18
|
-
*
|
|
19
|
-
* `history-state-coverage.test.ts` fails when a daemon store builds a `/history` path this list doesn't carry, in both
|
|
20
|
-
* directions, the same shape-recognizing guard that covers the workspace table.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
// Paths are historyRoot-relative, forward-slash, matched by PREFIX; a directory entry keeps its trailing slash
|
|
24
|
-
// so it cannot prefix-match a sibling file. See stateFileFor for how nesting resolves.
|
|
25
|
-
export const HISTORY_STATE_FILES: readonly StateFile[] = [
|
|
26
|
-
/* ---- the machinery a restored workspace is inert without ---- */
|
|
27
|
-
|
|
28
|
-
/* THE ONE THAT MAKES A BUNDLE A WORKSPACE. Every repo's real git dir, including the /work root's own
|
|
29
|
-
* ("root"), keyed by URI-encoded repo id. Carrying the working tree without this hands the target files
|
|
30
|
-
* whose `.git` points at a path that does not exist there, which is not a degraded repo but a broken one,
|
|
31
|
-
* and it takes the Changes review, the diff, land and every agent branch with it. The agent BRANCHES live
|
|
32
|
-
* in here too, which is what lets the checkouts below be left out. */
|
|
33
|
-
{ path: "gits/", portability: "carry" },
|
|
34
|
-
// The checkpoint timeline (one bare repo per scope, snapshots on refs/snapshots/head). Restoring it is what
|
|
35
|
-
// makes "restore to before that turn" still reach back past the move.
|
|
36
|
-
{ path: "scopes/", portability: "carry" },
|
|
37
|
-
// The fleet: every conversation card, its branch, its session ids, its standing.
|
|
38
|
-
{ path: "agents.json", portability: "carry" },
|
|
39
|
-
{ path: "turns/", portability: "carry" },
|
|
40
|
-
/* THE ARMED CONDITION WATCHES, one file per watch, put back at boot (agent/watchers.ts `restoreWatchers`).
|
|
41
|
-
*
|
|
42
|
-
* Carried for the reason loops.json is: an arrangement the agent entered into on the user's behalf and
|
|
43
|
-
* that is still outstanding travels with the conversation that is waiting on it, or a restored sandbox
|
|
44
|
-
* shows a card parked on a condition nothing will ever check. It can be carried safely because the journal
|
|
45
|
-
* holds no credential, only the NAMES of the environment its check ran with (agent/watch-journal.ts); the
|
|
46
|
-
* values are re-derived on the target from whatever capabilities it actually has, so a watch landing
|
|
47
|
-
* somewhere without them fails its check honestly and ends in a wake that says so, rather than arriving
|
|
48
|
-
* with a working copy of a token the bundle was never supposed to carry. A watch whose isolated checkout
|
|
49
|
-
* did not travel (those are `derived`) is dropped by the restore rather than re-armed against a tree that
|
|
50
|
-
* is not there. */
|
|
51
|
-
{ path: "watches/", portability: "carry" },
|
|
52
|
-
{ path: "transcripts/", portability: "carry" },
|
|
53
|
-
// What each message can be put back to, a workspace checkpoint, or an isolated conversation's own commits.
|
|
54
|
-
// Carried WITH the transcripts and the scopes above, because it is the join between them: without it a
|
|
55
|
-
// restored conversation reads back whole and offers no way back into it, even though both the messages and
|
|
56
|
-
// the states they name travelled.
|
|
57
|
-
{ path: "turn-anchors.json", portability: "carry" },
|
|
58
|
-
/* WHICH CONVERSATIONS ARE PUBLISHED AS PAGES ANYONE WITH THE LINK CAN READ.
|
|
59
|
-
*
|
|
60
|
-
* Carried, and it is the entry with the most to say for itself: the PAGES live in the workspace's outbox
|
|
61
|
-
* (`public/`), so they travel with `/work` whatever this says. Leaving the index behind would restore a
|
|
62
|
-
* sandbox that is still serving somebody's conversation on the internet with nothing in the app that knows
|
|
63
|
-
* it, no row, no link, and no way to stop sharing short of deleting files by hand. The index is what makes
|
|
64
|
-
* a published page withdrawable, so it goes wherever the pages go. */
|
|
65
|
-
{ path: "shares.json", portability: "carry" },
|
|
66
|
-
{ path: "activity.jsonl", portability: "carry" },
|
|
67
|
-
{ path: "usage.jsonl", portability: "carry" },
|
|
68
|
-
{ path: "account-usage.json", portability: "carry" },
|
|
69
|
-
{ path: "provider-refusals.json", portability: "carry" },
|
|
70
|
-
/* Which MODELS this sandbox's credentials were refused (usage/model-refusals.ts), the per-model half of the
|
|
71
|
-
* entry above and carried for the same reason: a bundle is this owner's sandbox on another machine, signing
|
|
72
|
-
* the same subscriptions back in, so a plan that does not cover a model there does not cover it here
|
|
73
|
-
* either, and the picker should arrive already clean. Cheap to be wrong about in the one case it can be
|
|
74
|
-
* (the target signs in a bigger plan): every entry is forgotten a day after it was written. */
|
|
75
|
-
{ path: "model-refusals.json", portability: "carry" },
|
|
76
|
-
// Explicit first-time dependency setup requests. Carrying the worklist preserves the owner's decision when
|
|
77
|
-
// an export interrupts the queue before its terminal starts; fulfilled entries remove themselves.
|
|
78
|
-
{ path: "dependency-requests.json", portability: "carry" },
|
|
79
|
-
// The deploy engine's own ledgers, a run's events and the check results the Pipelines view reads back.
|
|
80
|
-
{ path: "apply-events.ndjson", portability: "carry" },
|
|
81
|
-
{ path: "check-events/", portability: "carry" },
|
|
82
|
-
|
|
83
|
-
/* ---- regenerated by the target ---- */
|
|
84
|
-
|
|
85
|
-
/* THE DELIBERATE OMISSION, and the difference between a bundle of gigabytes and one of hundreds.
|
|
86
|
-
*
|
|
87
|
-
* A conversation's worktree is a full checkout of the monorepo per agent (plus its overlay upper dir), and
|
|
88
|
-
* there can be a hundred of them. None of it is unique: the branch it holds is in `gits/` above, and the
|
|
89
|
-
* registry entry naming it travels in agents.json, so an imported conversation arrives in exactly the
|
|
90
|
-
* shape the system already has a name for. `attached()` reports its checkout as absent, the board renders
|
|
91
|
-
* it, and the next turn's `ensure()` re-creates it from the recorded composition, which is the same path an
|
|
92
|
-
* archived agent takes when it runs again. The boot sweep's `git worktree prune` clears the stale admin
|
|
93
|
-
* entries the restored git dirs still carry. */
|
|
94
|
-
{
|
|
95
|
-
path: "worktrees/",
|
|
96
|
-
portability: "derived",
|
|
97
|
-
note: "Each conversation re-attaches its checkout from its branch on its next turn.",
|
|
98
|
-
},
|
|
99
|
-
/* The phrase index over what every conversation said, which both search boxes read (sessions/search-index.ts).
|
|
100
|
-
* Derived in the strict sense: every row in it was extracted from `transcripts/`, which travels, so a
|
|
101
|
-
* restored sandbox rebuilds it on its first boot rather than carrying tens of megabytes of index that its
|
|
102
|
-
* own backfill would produce anyway. Until that pass finishes the searches answer from what is indexed so
|
|
103
|
-
* far and say so, which is the behaviour they already have on any first run. */
|
|
104
|
-
{ path: "said-index/", portability: "derived", note: "Rebuilt from the carried transcripts by the first boot's backfill." },
|
|
105
|
-
{ path: "overlays/", portability: "derived" },
|
|
106
|
-
{ path: "logs/", portability: "derived" },
|
|
107
|
-
{ path: "trash/", portability: "derived" },
|
|
108
|
-
{ path: ".isolation-probe", portability: "derived" },
|
|
109
|
-
/* The finished bundles themselves. `derived` is doing real work here rather than describing leftovers: an
|
|
110
|
-
* export that carried the export directory would pack every previous bundle into the new one, and the next
|
|
111
|
-
* export would pack THAT, each one a multiple of the last. Living on this volume is the other half of the
|
|
112
|
-
* same guard; under `/work` the file would also be watched, indexed by iq, and snapshotted into history. */
|
|
113
|
-
{ path: "exports/", portability: "derived" },
|
|
114
|
-
/* The other end of the same volume: a bundle being taken IN, spooled here while its owner reads the plan
|
|
115
|
-
* it produced. `derived` for the export directory's reason and one more — this is somebody else's bundle,
|
|
116
|
-
* mid-review, and packing a half-reviewed arrival into an export would carry a sandbox that was never
|
|
117
|
-
* this one. The pipeline deletes each spool on apply or abandon, and boot sweeps whatever a crash left
|
|
118
|
-
* (portability/bundle-arrival.ts). */
|
|
119
|
-
{ path: "arrivals/", portability: "derived" },
|
|
120
|
-
|
|
121
|
-
/* ---- credentials ---- */
|
|
122
|
-
|
|
123
|
-
// The ssh alias dir ~/.ssh/intentic-hosts symlinks to: per-host config, private keys and passphrases for
|
|
124
|
-
// every host capability and git remote the sandbox reaches.
|
|
125
|
-
{
|
|
126
|
-
path: "ssh-hosts/",
|
|
127
|
-
portability: "secret",
|
|
128
|
-
note: "Re-add each ssh host on the Capabilities view, its key does not travel.",
|
|
129
|
-
},
|
|
130
|
-
// The cli-proxy's config, which holds the routed subscriptions' provider tokens.
|
|
131
|
-
{
|
|
132
|
-
path: "translator/",
|
|
133
|
-
portability: "secret",
|
|
134
|
-
note: "Sign the routed AI subscriptions in again on the Agent tab.",
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
/* ---- identity: what binds this sandbox to its owner, its browsers and its host ---- */
|
|
138
|
-
|
|
139
|
-
/* Signs every browser session cookie. Carrying it would let a bundle's holder mint sessions against the
|
|
140
|
-
* target, an export becomes a credential, and the target minting its own costs exactly one sign-in. */
|
|
141
|
-
{ path: "session-secret", portability: "identity", note: "Sign in again, the target signs its own sessions." },
|
|
142
|
-
{
|
|
143
|
-
path: "browser-access-disabled",
|
|
144
|
-
portability: "identity",
|
|
145
|
-
note: "Account-deletion retirement belongs to the source sandbox; the imported copy starts with fresh browser access.",
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
path: "push.json",
|
|
149
|
-
portability: "identity",
|
|
150
|
-
note: "Re-enable notifications in the browsers you use, a push subscription is bound to the sandbox that minted it.",
|
|
151
|
-
},
|
|
152
|
-
{ path: "sync-enrollments.json", portability: "identity", note: "Re-pair desktop sync from the Sync tab." },
|
|
153
|
-
{ path: "sync-pair-consumed.json", portability: "identity" },
|
|
154
|
-
{ path: "host-enrollments.json", portability: "identity" },
|
|
155
|
-
/* A connected BROWSER's enrollment (webext/webext-peer.ts). Identity for the hosts file's reason and one
|
|
156
|
-
* more of its own: the token admits a socket into somebody's signed-in browser, and that browser was paired
|
|
157
|
-
* with THIS sandbox — carried into another one it would either be dead weight or, worse, a second sandbox
|
|
158
|
-
* holding a live key to a browser its owner never connected it to. Re-pairing is a code and one click. */
|
|
159
|
-
{ path: "webext-enrollments.json", portability: "identity", note: "Pair your browser again from its card: the extension is still installed." },
|
|
160
|
-
// The browser door's burn list: every peer door keeps one (peers/peer-store.ts), and a browser pairing
|
|
161
|
-
// redeemed here must not read as fresh in a sandbox this file travelled to. Identity, hosts' reason.
|
|
162
|
-
{ path: "webext-pair-consumed.json", portability: "identity" },
|
|
163
|
-
// The burn list for setup-time device pairings. Identity, like sync's beside it, and for a sharper reason:
|
|
164
|
-
// carrying it into another sandbox would mark that sandbox's own fresh pairing as already spent.
|
|
165
|
-
{ path: "host-pair-consumed.json", portability: "identity" },
|
|
166
|
-
// A runner's enrollment names THIS sandbox as its parent (runners/runner-peer.ts): in another sandbox the
|
|
167
|
-
// digest would admit a socket whose runner still dials the old parent. Identity, both files, hosts' reasons.
|
|
168
|
-
{ path: "runner-enrollments.json", portability: "identity" },
|
|
169
|
-
{ path: "runner-pair-consumed.json", portability: "identity" },
|
|
170
|
-
// The runner-SIDE half: who this container belongs to and the token its reconnects present
|
|
171
|
-
// (runners/runner-identity.ts). Carried into another box it would dial the parent as this runner.
|
|
172
|
-
{ path: "runner-identity.json", portability: "identity" },
|
|
173
|
-
{ path: "local-cert/", portability: "identity" },
|
|
174
|
-
];
|
package/src/host-protocol.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
/* The handshake on /system/hosts/connect, the ONE message that is not oRPC.
|
|
4
|
-
*
|
|
5
|
-
* Everything a connected device is asked lives in `hostContract` (contracts/host.contract.ts), spoken over
|
|
6
|
-
* this socket by oRPC's websocket adapter: the machine hosts the server, the daemon holds the client. But a
|
|
7
|
-
* socket has to prove whose it is before it can be given a typed client, and that proof cannot itself be an
|
|
8
|
-
* oRPC call, the daemon has nothing to call yet, and would be attaching a link to a stranger.
|
|
9
|
-
*
|
|
10
|
-
* So the machine's first act is this frame, in plain JSON. The daemon verifies the token, learns which
|
|
11
|
-
* capability the socket belongs to, and only then attaches the link; from that message on, every byte on the
|
|
12
|
-
* wire is oRPC. Anything arriving before the link exists is either this frame or a closed socket. */
|
|
13
|
-
|
|
14
|
-
// The MCP protocol revision the machine's tool server implements. Shared because the daemon answers the
|
|
15
|
-
// handshake ITSELF when the machine is asleep (the daemon's peer bridge), two spellings of this would mean an
|
|
16
|
-
// offline machine negotiating a different protocol than the same machine awake.
|
|
17
|
-
export const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
18
|
-
|
|
19
|
-
export const HostHelloSchema = z.object({
|
|
20
|
-
type: z.literal("hello"),
|
|
21
|
-
/* The machine's enrollment token, in the FIRST FRAME, never in the URL. A WebSocket has no headers to put
|
|
22
|
-
* it in, and the obvious `?token=` would write a durable key to somebody's laptop into Cloudflare's edge
|
|
23
|
-
* logs, the connector's logs and every proxy in between (the reasoning that moved the browser's upgrades
|
|
24
|
-
* onto one-shot tickets, auth/ws-tickets.ts). A frame is body, not URL, so it is logged nowhere. Until this
|
|
25
|
-
* arrives the socket is anonymous and short-lived: the daemon closes it in seconds if it never does. */
|
|
26
|
-
token: z.string(),
|
|
27
|
-
// The @intentic/machine build the machine is running, surfaced per machine so an old binary is visible rather
|
|
28
|
-
// than mysteriously missing a tool. What the machine IS (`describe`) is not here: it is pulled over the
|
|
29
|
-
// typed link a moment later, so there is one definition of those facts rather than two.
|
|
30
|
-
version: z.string(),
|
|
31
|
-
});
|
|
32
|
-
export type HostHello = z.infer<typeof HostHelloSchema>;
|
|
33
|
-
|
|
34
|
-
// The URL the machine's agent dials, given the sandbox's public URL. Carries no credential, the token rides
|
|
35
|
-
// the hello frame. One place builds it, so the agent and the daemon route can't disagree about where it lives.
|
|
36
|
-
export const hostConnectUrl = (sandboxUrl: string): string => `${sandboxUrl.replace(/^http/, "ws").replace(/\/$/, "")}/system/hosts/connect`;
|
package/src/hostnames.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
// The single source for the tunnel/preview hostname + ingress scheme, shared by the CLI, platform API, daemon,
|
|
2
|
-
// AND the browser. Pure string builders/parsers with NO node imports (unlike ./tunnel-ids, which needs
|
|
3
|
-
// node:crypto for the digest), so the web bundle can import them and derive identical names. The caller supplies
|
|
4
|
-
// the 12-hex id (sandboxIdFromToken/hostSshIdFromToken in node; WebCrypto in the browser).
|
|
5
|
-
//
|
|
6
|
-
// All four apps MUST agree on these strings: a divergence resolves to NXDOMAIN that resolvers negative-cache for
|
|
7
|
-
// the zone's SOA TTL. This module is that agreement.
|
|
8
|
-
|
|
9
|
-
// The sandbox daemon's subdomain + hostname: `sandbox-<id>` / `sandbox-<id>.<zone>`.
|
|
10
|
-
const SANDBOX_PREFIX = "sandbox-";
|
|
11
|
-
export const sandboxSubdomain = (id: string): string => `${SANDBOX_PREFIX}${id}`;
|
|
12
|
-
export const sandboxHostname = (id: string, zone: string): string => `${sandboxSubdomain(id)}.${zone}`;
|
|
13
|
-
|
|
14
|
-
// The container sshd hostname the desktop-sync (Mutagen) reaches over the sandbox tunnel: `ssh-<id>.<zone>`.
|
|
15
|
-
export const sshHostname = (id: string, zone: string): string => `ssh-${id}.${zone}`;
|
|
16
|
-
|
|
17
|
-
/* The LOOPBACK name: `<id>.local.<zone>`, resolving to 127.0.0.1 under ONE wildcard record for the whole zone.
|
|
18
|
-
*
|
|
19
|
-
* A public DNS name for a private address looks odd until you ask what the alternative is. A browser on the
|
|
20
|
-
* same machine as the sandbox can reach its daemon in microseconds instead of crossing to a Cloudflare edge
|
|
21
|
-
* and back, but only over HTTPS, because Safari refuses http://127.0.0.1 from an HTTPS page as mixed content
|
|
22
|
-
* (WebKit 171934, open since 2017), and HTTPS needs a name a public CA will certify. An IP literal cannot have
|
|
23
|
-
* one; this can. The daemon holds the key and gets the certificate by proving control of the zone over
|
|
24
|
-
* DNS-01 (there is nothing on the public internet for a CA to connect to).
|
|
25
|
-
*
|
|
26
|
-
* IT IS A LABEL DEEPER THAN THE OTHER NAMES, and that is the entire point rather than a naming preference. A
|
|
27
|
-
* DNS wildcard matches ONE label, so `*.<zone>` cannot cover `<id>.local.<zone>` and `*.local.<zone>` covers
|
|
28
|
-
* every sandbox that will ever exist: one record for the platform, not one per sandbox. The shape it replaced,
|
|
29
|
-
* `local-<id>.<zone>`, needed a record each, and a zone has a hard per-record quota (Cloudflare 81045). Every
|
|
30
|
-
* OTHER per-sandbox record went away with the move to the zrok hub, so this was the last thing consuming that
|
|
31
|
-
* quota, and when the zone filled the platform could no longer write the record OR the ACME challenge beside
|
|
32
|
-
* it: the certified shortcut stopped resolving, every browser fell back to the plain-http loopback, and that
|
|
33
|
-
* transport is HTTP/1.1 with six connections per origin (see the editor's streamBudget.ts for what that cost).
|
|
34
|
-
* A quota nothing can exhaust is the fix that keeps working.
|
|
35
|
-
*
|
|
36
|
-
* It discloses nothing: the id is already the leading label of the sandbox's public hostname, and the address
|
|
37
|
-
* it resolves to is every machine's own loopback. */
|
|
38
|
-
export const localHostname = (id: string, zone: string): string => `${id}.${LOCAL_LABEL}.${zone}`;
|
|
39
|
-
|
|
40
|
-
// The label the loopback names live under, so the wildcard has something to be a wildcard OF.
|
|
41
|
-
export const LOCAL_LABEL = "local";
|
|
42
|
-
|
|
43
|
-
// The single record that answers for all of them. Never per-sandbox, never reaped.
|
|
44
|
-
export const localWildcardHostname = (zone: string): string => `*.${LOCAL_LABEL}.${zone}`;
|
|
45
|
-
|
|
46
|
-
// What that record points at, and the reason it is safe to publish: every resolver on earth gets 127.0.0.1.
|
|
47
|
-
export const LOCAL_ADDRESS = "127.0.0.1";
|
|
48
|
-
|
|
49
|
-
// A per-host SSH tunnel's Cloudflare tunnel NAME (its hostname reuses sshHostname with the host-ssh id).
|
|
50
|
-
export const hostSshTunnelName = (id: string): string => `host-ssh-${id}`;
|
|
51
|
-
|
|
52
|
-
// The proxied-CNAME target every tunnel points its DNS record at.
|
|
53
|
-
export const cfargotunnelCname = (tunnelId: string): string => `${tunnelId}.cfargotunnel.com`;
|
|
54
|
-
|
|
55
|
-
// The cloudflared ingress catch-all, must be the LAST rule.
|
|
56
|
-
export const CATCH_ALL = { service: "http_status:404" } as const;
|
|
57
|
-
|
|
58
|
-
// Preview scheme: `preview-<panel>-<sandboxId>.<zone>`, one DNS label (the free Universal SSL `*.<zone>` cert
|
|
59
|
-
// covers exactly one level), where <panel> is `<repo>` or `<repo>--<app>` and <sandboxId> pins the hostname to
|
|
60
|
-
// this sandbox (the shared intentic zone hosts many sandboxes; without the id two users' panels would collide).
|
|
61
|
-
// Port-forward scheme: `port-<slot>-<sandboxId>.<zone>`, the same shape with a `port-` prefix, where <slot>
|
|
62
|
-
// is one of the sandbox's forward slots (portSlotsFromToken in ./tunnel-ids), not the port number itself:
|
|
63
|
-
// slots keep the intentic-provided path's minted routes bounded and warm while dev servers churn ephemeral
|
|
64
|
-
// ports. The slot labels are salted with the connect token rather than being the letters a…h, so a forwarded
|
|
65
|
-
// port's hostname is not derivable from the (public) sandbox id alone, see tunnel-ids for why that matters.
|
|
66
|
-
//
|
|
67
|
-
// Outbox scheme: `public-<slot>-<sandboxId>.<zone>`, the same shape again, serving the workspace's `public/`
|
|
68
|
-
// directory as static files. <slot> is publicSlotFromToken (./tunnel-ids), salted for the same reason the port
|
|
69
|
-
// slots are, and one record per sandbox rather than a pool: there is one outbox, and its link has to stay good
|
|
70
|
-
// for as long as the file does.
|
|
71
|
-
//
|
|
72
|
-
// A *label* is the first-DNS-label prefix before `-<sandboxId>` (`preview-<panel>` / `port-<slot>` /
|
|
73
|
-
// `public-<slot>`), the unit reachability is expressed in, so one rule covers all three.
|
|
74
|
-
export const previewLabel = (panel: string): string => `preview-${panel}`;
|
|
75
|
-
export const portLabel = (slot: string): string => `port-${slot}`;
|
|
76
|
-
export const publicLabel = (slot: string): string => `public-${slot}`;
|
|
77
|
-
|
|
78
|
-
// The hostname a label resolves to. Nothing mints it: the edge parses the sandbox id back out of the name.
|
|
79
|
-
export const labelHostname = (label: string, id: string, zone: string): string => `${label}-${id}.${zone}`;
|
|
80
|
-
export const previewHostname = (panel: string, id: string, zone: string): string => labelHostname(previewLabel(panel), id, zone);
|
|
81
|
-
export const portHostname = (slot: string, id: string, zone: string): string => labelHostname(portLabel(slot), id, zone);
|
|
82
|
-
export const publicHostname = (slot: string, id: string, zone: string): string => labelHostname(publicLabel(slot), id, zone);
|
|
83
|
-
|
|
84
|
-
// A label's public URL, undefined unless the sandbox has both a zone and an id (headless/loopback sandboxes
|
|
85
|
-
// have neither and advertise nothing). One builder, three vocabularies: a panel's preview, a forwarded port's,
|
|
86
|
-
// and the outbox's.
|
|
87
|
-
const labelUrl = (label: string, zone: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
88
|
-
zone !== undefined && zone !== "" && sandboxId !== undefined ? `https://${labelHostname(label, sandboxId, zone)}` : undefined;
|
|
89
|
-
export const previewUrl = (panel: string, zone: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
90
|
-
labelUrl(previewLabel(panel), zone, sandboxId);
|
|
91
|
-
export const portUrl = (slot: string, zone: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
92
|
-
labelUrl(portLabel(slot), zone, sandboxId);
|
|
93
|
-
export const publicUrl = (slot: string, zone: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
94
|
-
labelUrl(publicLabel(slot), zone, sandboxId);
|
|
95
|
-
|
|
96
|
-
// The key after `<prefix>` from a request's Host header. The first DNS label must carry the prefix (the
|
|
97
|
-
// own-Cloudflare wildcard also catches stray subdomains → undefined → the caller's 404) and, when the sandbox
|
|
98
|
-
// has an id, the exact `-<sandboxId>` suffix, a fixed-length match, so keys containing `-` stay unambiguous.
|
|
99
|
-
// Without an id the bare label is the key (loopback tests and provider-deployed workspaces, which front the
|
|
100
|
-
// proxy themselves).
|
|
101
|
-
const keyFromHost = (prefix: string, hostHeader: string | undefined, sandboxId: string | undefined): string | undefined => {
|
|
102
|
-
const label = hostHeader?.split(":")[0]?.split(".")[0] ?? "";
|
|
103
|
-
if (!label.startsWith(prefix)) {
|
|
104
|
-
return undefined;
|
|
105
|
-
}
|
|
106
|
-
const key = label.slice(prefix.length);
|
|
107
|
-
if (sandboxId === undefined) {
|
|
108
|
-
return key === "" ? undefined : key;
|
|
109
|
-
}
|
|
110
|
-
const suffix = `-${sandboxId}`;
|
|
111
|
-
return key.length > suffix.length && key.endsWith(suffix) ? key.slice(0, -suffix.length) : undefined;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export const panelFromHost = (hostHeader: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
115
|
-
keyFromHost("preview-", hostHeader, sandboxId);
|
|
116
|
-
export const portSlotFromHost = (hostHeader: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
117
|
-
keyFromHost("port-", hostHeader, sandboxId);
|
|
118
|
-
export const publicSlotFromHost = (hostHeader: string | undefined, sandboxId: string | undefined): string | undefined =>
|
|
119
|
-
keyFromHost("public-", hostHeader, sandboxId);
|
|
120
|
-
|
|
121
|
-
// The sandbox's identity AS THE USER SEES IT: the leading DNS label of its public URL, minus the `sandbox-`
|
|
122
|
-
// prefix, `https://sandbox-0f310c3c4db4.intentic.dev` → `0f310c3c4db4`, i.e. sandboxIdFromToken's digest read
|
|
123
|
-
// back off the wire by anyone holding only the URL. On the own-Cloudflare path the label is whatever subdomain
|
|
124
|
-
// the owner chose, so that is the id there. undefined until the sandbox has a URL at all.
|
|
125
|
-
export const sandboxIdFromUrl = (url: string | undefined): string | undefined => {
|
|
126
|
-
if (url === undefined || url === "") {
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(url) ? url : `https://${url}`;
|
|
130
|
-
let label: string;
|
|
131
|
-
try {
|
|
132
|
-
label = new URL(withScheme).hostname.split(".")[0] ?? "";
|
|
133
|
-
} catch {
|
|
134
|
-
return undefined;
|
|
135
|
-
}
|
|
136
|
-
if (label === "" || label === SANDBOX_PREFIX) {
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
return label.startsWith(SANDBOX_PREFIX) ? label.slice(SANDBOX_PREFIX.length) : label;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// The LOCAL folder desktop sync mirrors /work into: `~/intentic/<sandbox name>-<sandboxIdFromUrl>`. Both halves
|
|
143
|
-
// are strings the user already has in front of them, the name in the sandbox switcher, the id in the address
|
|
144
|
-
// bar, so the folder on disk and the sandbox it mirrors read as ONE identity: `~/intentic/shop-0f310c3c4db4`
|
|
145
|
-
// belongs to `https://sandbox-0f310c3c4db4.intentic.dev` and nothing else. Keyed on the URL rather than the
|
|
146
|
-
// name alone for the same reason the hostname is: a torn-down sandbox recreated under the same name gets a new
|
|
147
|
-
// id, hence its own fresh folder instead of reusing the dead one's (which cleanup never deletes) and colliding
|
|
148
|
-
// on the two-way sync. Lives here, beside the hostname builders, because that match IS the contract.
|
|
149
|
-
export const syncFolder = (name: string, url: string | undefined): string => {
|
|
150
|
-
const slug =
|
|
151
|
-
name
|
|
152
|
-
.replace(/[^a-zA-Z0-9]+/g, "-")
|
|
153
|
-
.replace(/^-+|-+$/g, "")
|
|
154
|
-
.toLowerCase() || "sandbox";
|
|
155
|
-
const id = sandboxIdFromUrl(url);
|
|
156
|
-
return `~/intentic/${slug}${id === undefined ? "" : `-${id}`}`;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// The Cloudflare zone from a sandbox public URL (https://sandbox-<id>.<zone> → <zone>): the hostname minus its
|
|
160
|
-
// first DNS label. undefined when the URL is unparsable OR the hostname has fewer than three labels (no zone
|
|
161
|
-
// suffix to strip, e.g. a 2-label host would otherwise yield a bare TLD). Accepts scheme-less input too, so it
|
|
162
|
-
// works whether the caller passes `https://…` (daemon/CLI) or a bare host. This is the single reconciled
|
|
163
|
-
// implementation of what used to be the daemon's `zoneFromPublicUrl` and the web's `zoneFromDaemonUrl`.
|
|
164
|
-
export const zoneFromUrl = (url: string | undefined): string | undefined => {
|
|
165
|
-
if (url === undefined || url === "") {
|
|
166
|
-
return undefined;
|
|
167
|
-
}
|
|
168
|
-
const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(url) ? url : `https://${url}`;
|
|
169
|
-
let hostname: string;
|
|
170
|
-
try {
|
|
171
|
-
hostname = new URL(withScheme).hostname;
|
|
172
|
-
} catch {
|
|
173
|
-
return undefined;
|
|
174
|
-
}
|
|
175
|
-
const labels = hostname.split(".");
|
|
176
|
-
if (labels.length < 3) {
|
|
177
|
-
return undefined;
|
|
178
|
-
}
|
|
179
|
-
return labels.slice(1).join(".");
|
|
180
|
-
};
|
package/src/ingress-contract.ts
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { createPrivateKey, createPublicKey, sign as edSign, verify as edVerify } from "node:crypto";
|
|
2
|
-
|
|
3
|
-
/* THE INGRESS CONTRACT: how a sandbox is reached now that the reachability fabric is the platform's OWN edge
|
|
4
|
-
* (the `@intentic/ingress` app on Fly) instead of a zrok hub. Node-only (crypto), like ./tunnel-ids beside it;
|
|
5
|
-
* shared by the platform (mints grants), the ingress (verifies grants, routes hosts), and the daemon (dials
|
|
6
|
-
* the tunnel). The three MUST agree on every string in this file, which is why it exists.
|
|
7
|
-
*
|
|
8
|
-
* WHAT REPLACED WHAT. Under zrok, reachability was STATE: an account minted per sandbox over the hub's admin
|
|
9
|
-
* API, names claimed one by one, shares bound to them, and a reaper collecting what the soft-deletes leaked.
|
|
10
|
-
* Every piece of that state existed to answer one question — "which sandbox may serve this hostname?" — that
|
|
11
|
-
* the hostnames ALREADY answer by construction: every public name a sandbox serves ends in its own 12-hex id
|
|
12
|
-
* (`sandbox-<id>`, `preview-<panel>-<id>`, `port-<slot>-<id>`, `public-<slot>-<id>`; hostnames.ts is the
|
|
13
|
-
* single source). So ownership is a PARSE, not a registry, and the only thing that has to be minted is proof
|
|
14
|
-
* of identity: a grant, signed by the platform, saying "the bearer is sandbox <id>". Provisioning reachability
|
|
15
|
-
* becomes a pure function — no hub round trip, no row to cache a token on, no orphan to reconcile, and
|
|
16
|
-
* revoking it is deleting the sandbox row (the ingress asks the platform on register, below).
|
|
17
|
-
*
|
|
18
|
-
* THE FLOW. The daemon dials ONE outbound WebSocket to the ingress (INGRESS_TUNNEL_PATH) presenting its grant
|
|
19
|
-
* in INGRESS_GRANT_HEADER. The ingress verifies the signature offline, registers the tunnel under grant.sub,
|
|
20
|
-
* and from then on routes every edge request whose Host's leftmost label ends in `-<that id>` (or is exactly
|
|
21
|
-
* `sandbox-<id>`) down that tunnel. A second tunnel for the same id DISPLACES the first — the new container is
|
|
22
|
-
* by definition the live one, which is what buries the zrok-era stale-share reclaim dance (a recreated box
|
|
23
|
-
* used to fight the hub over names its dead predecessor still held; here the fight cannot exist).
|
|
24
|
-
*
|
|
25
|
-
* THE DATA PLANE over the tunnel is an HTTP/2 cleartext session runs over the WebSocket's binary stream:
|
|
26
|
-
* the ingress side opens an http2 CLIENT session over the duplex (node's http2.connect with createConnection),
|
|
27
|
-
* the daemon side feeds the duplex to an http2 SERVER session, and each edge request becomes one h2 stream
|
|
28
|
-
* with the original :authority preserved, which the daemon's client forwards to its own loopback listener
|
|
29
|
-
* (the Hono app already dispatches previews by Host). WebSocket upgrades ride CONNECT-method streams carrying
|
|
30
|
-
* the raw upgraded bytes. All of it is node core — the mux, flow control and per-stream backpressure are
|
|
31
|
-
* h2's own, not ours to reimplement. The implementation lives in ./ingress-protocol.ts (both halves, one
|
|
32
|
-
* owner); this file pins only what every party must agree on.
|
|
33
|
-
*
|
|
34
|
-
* WHY PER-REQUEST ROUTING IS NOT OPTIONAL: the edge terminates TLS under ONE wildcard certificate, and h2
|
|
35
|
-
* browsers coalesce connections across every hostname a certificate covers — one TCP connection can carry
|
|
36
|
-
* `sandbox-a…` and `preview-x-b…` interleaved. Routing a CONNECTION by its first Host would send one
|
|
37
|
-
* sandbox's requests to another. The unit of routing is the request (h2 stream), never the connection. */
|
|
38
|
-
|
|
39
|
-
// ── The reachability grant ──────────────────────────────────────────────────────────────────────────────
|
|
40
|
-
|
|
41
|
-
/* Version prefix, so a future shape can coexist during a key rotation. Not a negotiation: an ingress that
|
|
42
|
-
* does not know a prefix refuses the tunnel, and the box retries until its operator updates something. */
|
|
43
|
-
const GRANT_PREFIX = "ig1";
|
|
44
|
-
|
|
45
|
-
const base64url = (bytes: Buffer): string => bytes.toString("base64url");
|
|
46
|
-
|
|
47
|
-
// The signed claim. `sub` is the sandbox's 12-hex id (sandboxIdFromToken in ./tunnel-ids); `iat` is seconds.
|
|
48
|
-
// Deliberately no expiry: the grant lives in a container's env for the container's whole life, and the
|
|
49
|
-
// revocation that matters (the sandbox being deleted) is answered by the platform on register, not by time.
|
|
50
|
-
export interface ReachabilityGrant {
|
|
51
|
-
readonly sandboxId: string;
|
|
52
|
-
readonly issuedAt: number;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const SANDBOX_ID = /^[0-9a-f]{12}$/;
|
|
56
|
-
|
|
57
|
-
/* Mint a grant: Ed25519 over the canonical payload bytes. Ed25519 because node signs/verifies it with key
|
|
58
|
-
* objects alone (no hash negotiation, no padding modes), signatures are 64 bytes, and the platform already
|
|
59
|
-
* depends on nothing for it — the private key is config (PEM, PKCS8), the public key rides the ingress env. */
|
|
60
|
-
export const mintReachabilityGrant = (privateKeyPem: string, sandboxId: string, issuedAtMs: number): string => {
|
|
61
|
-
if (!SANDBOX_ID.test(sandboxId)) {
|
|
62
|
-
throw new Error(`a reachability grant names a 12-hex sandbox id, got "${sandboxId}"`);
|
|
63
|
-
}
|
|
64
|
-
const payload = Buffer.from(JSON.stringify({ sub: sandboxId, iat: Math.floor(issuedAtMs / 1000) }), "utf8");
|
|
65
|
-
const signature = edSign(null, payload, createPrivateKey(privateKeyPem));
|
|
66
|
-
return `${GRANT_PREFIX}.${base64url(payload)}.${base64url(signature)}`;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/* Verify a grant against the platform's public key. Every malformed shape answers undefined rather than
|
|
70
|
-
* throwing: this runs on the ingress's unauthenticated door, where a garbage token is weather, not a fault. */
|
|
71
|
-
export const verifyReachabilityGrant = (publicKeyPem: string, token: string): ReachabilityGrant | undefined => {
|
|
72
|
-
const parts = token.split(".");
|
|
73
|
-
if (parts.length !== 3 || parts[0] !== GRANT_PREFIX) {
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
const payload = Buffer.from(parts[1] as string, "base64url");
|
|
78
|
-
const signature = Buffer.from(parts[2] as string, "base64url");
|
|
79
|
-
if (!edVerify(null, payload, createPublicKey(publicKeyPem), signature)) {
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
const parsed = JSON.parse(payload.toString("utf8")) as { sub?: unknown; iat?: unknown };
|
|
83
|
-
if (typeof parsed.sub !== "string" || !SANDBOX_ID.test(parsed.sub) || typeof parsed.iat !== "number") {
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
return { sandboxId: parsed.sub, issuedAt: parsed.iat };
|
|
87
|
-
} catch {
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// ── Host → owner routing ────────────────────────────────────────────────────────────────────────────────
|
|
93
|
-
|
|
94
|
-
/* Which sandbox may serve this Host. The leftmost DNS label either IS `sandbox-<id>` or ends in `-<id>`
|
|
95
|
-
* (preview/port/public labels, hostnames.ts) — a fixed-length tail, so label keys containing `-` stay
|
|
96
|
-
* unambiguous. Anything else (the ingress's own name, the zone apex, a stray subdomain) answers undefined,
|
|
97
|
-
* which the ingress turns into its 404. The loopback name (`<id>.local.<zone>`) never reaches the ingress —
|
|
98
|
-
* it resolves to 127.0.0.1 — and its bare-id label deliberately does not match here. */
|
|
99
|
-
export const hostOwnerId = (host: string): string | undefined => {
|
|
100
|
-
const label = host.split(":")[0]?.split(".")[0] ?? "";
|
|
101
|
-
const match = /-([0-9a-f]{12})$/.exec(label);
|
|
102
|
-
return match === null ? undefined : match[1];
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// ── Wire constants ──────────────────────────────────────────────────────────────────────────────────────
|
|
106
|
-
|
|
107
|
-
/* The tunnel door on the ingress. Versioned in the path so a v2 session shape is a new door, not a flag day:
|
|
108
|
-
* the ingress serves both for as long as old containers exist. Checked BEFORE host routing — the ingress's own
|
|
109
|
-
* hostname carries no sandbox id on purpose. */
|
|
110
|
-
export const INGRESS_TUNNEL_PATH = "/tunnel/v1";
|
|
111
|
-
|
|
112
|
-
// The grant rides a header on the tunnel upgrade (a Node client can set one; this is never a browser).
|
|
113
|
-
export const INGRESS_GRANT_HEADER = "x-intentic-grant";
|
|
114
|
-
|
|
115
|
-
/* The env vocabulary, every lane (connect one-liner, compose file, hosted machine env) hands the same pair
|
|
116
|
-
* down and the DAEMON reads exactly these names — the entrypoint reads neither, and that is the shape of the
|
|
117
|
-
* change: reachability stopped being something a shell script arranges before the daemon starts and became
|
|
118
|
-
* one outbound dial the daemon makes for itself. SANDBOX_PUBLIC_URL is unchanged from the fabric before this
|
|
119
|
-
* one and stays beside them. */
|
|
120
|
-
export const ENV_INGRESS_URL = "INGRESS_URL";
|
|
121
|
-
export const ENV_SANDBOX_GRANT = "SANDBOX_GRANT";
|
|
122
|
-
|
|
123
|
-
// ── The daemon-side surface (pinned for the boot wiring) ────────────────────────────────────────────────
|
|
124
|
-
|
|
125
|
-
/* The daemon-side tunnel behavior this contract requires. Dial, register, forward to the loopback listener,
|
|
126
|
-
* reconnect forever with backoff —
|
|
127
|
-
* the tunnel is the sandbox's reachability, so like the zrok agent's restart loop it never gives up, it only
|
|
128
|
-
* ever waits longer. close() is for shutdown and tests. */
|
|
129
|
-
export interface IngressTunnelOptions {
|
|
130
|
-
// e.g. https://ingress.<zone>. The daemon derives the wss:// door itself (INGRESS_TUNNEL_PATH).
|
|
131
|
-
readonly url: string;
|
|
132
|
-
readonly grant: string;
|
|
133
|
-
// The daemon's own loopback listener; every h2 stream lands there as a plain HTTP/1.1 request or upgrade.
|
|
134
|
-
readonly targetPort: number;
|
|
135
|
-
readonly log: (message: string, error?: unknown) => void;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export interface IngressTunnelHandle {
|
|
139
|
-
readonly close: () => Promise<void>;
|
|
140
|
-
// For /health and the boot log: whether the tunnel currently holds a registered session.
|
|
141
|
-
readonly connected: () => boolean;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export type StartIngressTunnel = (options: IngressTunnelOptions) => IngressTunnelHandle;
|
|
145
|
-
|
|
146
|
-
/* ── What the INGRESS side must also honor (spec, enforced by ingress-protocol tests) ──────────────────────
|
|
147
|
-
*
|
|
148
|
-
* • Register: verify the grant offline; then, when PLATFORM_URL is configured, ask the platform whether the
|
|
149
|
-
* sandbox still exists (GET /api/reachability/<id>, 200/404, answer cached; fail-OPEN on a platform that
|
|
150
|
-
* does not answer — reachability must not depend on the platform being up, that is the whole point of the
|
|
151
|
-
* platform being off the hot path). A 404 refuses the tunnel: that is revocation.
|
|
152
|
-
* • Displacement: a new tunnel for an id closes the old session (code 4001) and takes the registration.
|
|
153
|
-
* • Liveness: WebSocket ping every 15s; a peer silent for 45s is dead and unregistered.
|
|
154
|
-
* • Routing: request host → hostOwnerId → registered tunnel; no tunnel answers 502 with a body naming the
|
|
155
|
-
* sandbox label (the browser's availability flow reads any 5xx as "sandbox unreachable" and drives wake).
|
|
156
|
-
* • The tunnel door itself (INGRESS_TUNNEL_PATH) and anything not carrying a sandbox-id host answer on the
|
|
157
|
-
* ingress directly; they are never routed. */
|