@intentic/sandbox-contract 1.231.0 → 1.233.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 +13 -2
- package/dist/agent-catalog.d.ts +2 -1
- package/dist/agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog.js +1 -1
- package/dist/agent-catalog.js.map +1 -1
- package/dist/chores/chores.d.ts +1 -1
- package/dist/chores/chores.d.ts.map +1 -1
- package/dist/chores/probes.d.ts +1 -1
- package/dist/chores/probes.d.ts.map +1 -1
- package/dist/chores/stack.d.ts.map +1 -1
- package/dist/chores/stack.js +2 -1
- package/dist/chores/stack.js.map +1 -1
- package/dist/chores/verdict.d.ts +1 -1
- package/dist/chores/verdict.d.ts.map +1 -1
- package/dist/command-classes.d.ts +14 -0
- package/dist/command-classes.d.ts.map +1 -0
- package/dist/command-classes.js +168 -0
- package/dist/command-classes.js.map +1 -0
- package/dist/contracts/activity.contract.js +1 -1
- package/dist/contracts/activity.contract.js.map +1 -1
- package/dist/contracts/agent.contract.d.ts +51 -2
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +13 -1
- package/dist/contracts/agent.contract.js.map +1 -1
- package/dist/contracts/agents.contract.d.ts +24 -0
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +5 -1
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/automations.contract.js +2 -1
- package/dist/contracts/automations.contract.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts +63 -0
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/capabilities.contract.js +3 -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 +2 -1
- package/dist/contracts/chores.contract.js.map +1 -1
- package/dist/contracts/ci.contract.js +2 -1
- package/dist/contracts/ci.contract.js.map +1 -1
- package/dist/contracts/claude.contract.js +2 -1
- package/dist/contracts/claude.contract.js.map +1 -1
- package/dist/contracts/cursor.contract.js +2 -1
- package/dist/contracts/cursor.contract.js.map +1 -1
- package/dist/contracts/drafts.contract.d.ts.map +1 -1
- package/dist/contracts/drafts.contract.js +2 -1
- package/dist/contracts/drafts.contract.js.map +1 -1
- package/dist/contracts/endpoints.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.js +2 -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 +2 -1
- package/dist/contracts/exit.contract.js.map +1 -1
- package/dist/contracts/extensions.contract.d.ts +42 -0
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js +4 -1
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +4 -1
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/grok.contract.d.ts.map +1 -1
- package/dist/contracts/grok.contract.js +2 -1
- package/dist/contracts/grok.contract.js.map +1 -1
- package/dist/contracts/history.contract.d.ts.map +1 -1
- package/dist/contracts/history.contract.js +2 -1
- package/dist/contracts/history.contract.js.map +1 -1
- package/dist/contracts/host.contract.d.ts +11 -0
- package/dist/contracts/host.contract.d.ts.map +1 -1
- package/dist/contracts/host.contract.js +4 -1
- package/dist/contracts/host.contract.js.map +1 -1
- package/dist/contracts/intentic.contract.d.ts.map +1 -1
- package/dist/contracts/intentic.contract.js +2 -1
- package/dist/contracts/intentic.contract.js.map +1 -1
- package/dist/contracts/inventory.contract.js +1 -1
- package/dist/contracts/inventory.contract.js.map +1 -1
- package/dist/contracts/logs.contract.d.ts.map +1 -1
- package/dist/contracts/logs.contract.js +1 -1
- package/dist/contracts/logs.contract.js.map +1 -1
- package/dist/contracts/loops.contract.js +2 -1
- package/dist/contracts/loops.contract.js.map +1 -1
- package/dist/contracts/panels.contract.d.ts.map +1 -1
- package/dist/contracts/panels.contract.js +2 -1
- package/dist/contracts/panels.contract.js.map +1 -1
- package/dist/contracts/personas.contract.js +2 -1
- package/dist/contracts/personas.contract.js.map +1 -1
- package/dist/contracts/ports.contract.d.ts.map +1 -1
- package/dist/contracts/ports.contract.js +2 -1
- package/dist/contracts/ports.contract.js.map +1 -1
- package/dist/contracts/prepush.contract.d.ts.map +1 -1
- package/dist/contracts/prepush.contract.js +2 -1
- package/dist/contracts/prepush.contract.js.map +1 -1
- package/dist/contracts/providers.contract.d.ts.map +1 -1
- package/dist/contracts/providers.contract.js +2 -1
- package/dist/contracts/providers.contract.js.map +1 -1
- package/dist/contracts/public.contract.d.ts.map +1 -1
- package/dist/contracts/public.contract.js +2 -1
- package/dist/contracts/public.contract.js.map +1 -1
- package/dist/contracts/push.contract.d.ts.map +1 -1
- package/dist/contracts/push.contract.js +2 -1
- package/dist/contracts/push.contract.js.map +1 -1
- package/dist/contracts/runner.contract.d.ts +151 -43
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.js +14 -1
- package/dist/contracts/runner.contract.js.map +1 -1
- package/dist/contracts/secrets.contract.d.ts.map +1 -1
- package/dist/contracts/secrets.contract.js +2 -1
- package/dist/contracts/secrets.contract.js.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 +20 -0
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.js +3 -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 +2 -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 +2 -1
- package/dist/contracts/skills.contract.js.map +1 -1
- package/dist/contracts/system.contract.d.ts +35 -16
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +6 -1
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/contracts/translator.contract.d.ts.map +1 -1
- package/dist/contracts/translator.contract.js +4 -1
- package/dist/contracts/translator.contract.js.map +1 -1
- package/dist/contracts/usage.contract.js +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 +2 -1
- package/dist/contracts/vpn.contract.js.map +1 -1
- package/dist/contracts/webext.contract.d.ts +45 -0
- package/dist/contracts/webext.contract.d.ts.map +1 -0
- package/dist/contracts/webext.contract.js +12 -0
- package/dist/contracts/webext.contract.js.map +1 -0
- package/dist/contracts/workflows.contract.js +2 -1
- package/dist/contracts/workflows.contract.js.map +1 -1
- package/dist/contracts/workspace.contract.d.ts +2 -2
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/contracts/workspace.contract.js +7 -1
- package/dist/contracts/workspace.contract.js.map +1 -1
- package/dist/definition-action.d.ts +7 -0
- package/dist/definition-action.d.ts.map +1 -0
- package/dist/definition-action.js +3 -0
- package/dist/definition-action.js.map +1 -0
- package/dist/definition.d.ts +1064 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +93 -0
- package/dist/definition.js.map +1 -0
- package/dist/events.d.ts +109 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +30 -1
- package/dist/events.js.map +1 -1
- package/dist/fast-tier.d.ts +1 -1
- package/dist/fast-tier.d.ts.map +1 -1
- package/dist/history-state.d.ts.map +1 -1
- package/dist/history-state.js +1 -0
- package/dist/history-state.js.map +1 -1
- package/dist/index.d.ts +371 -103
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -1
- package/dist/index.js.map +1 -1
- package/dist/listener-protocol.js +1 -1
- package/dist/listener-protocol.js.map +1 -1
- package/dist/quick-model.d.ts +1 -1
- package/dist/quick-model.d.ts.map +1 -1
- package/dist/runner-protocol.d.ts +18 -0
- package/dist/runner-protocol.d.ts.map +1 -1
- package/dist/runner-protocol.js +8 -4
- package/dist/runner-protocol.js.map +1 -1
- package/dist/schemas/activity.d.ts +112 -0
- package/dist/schemas/activity.d.ts.map +1 -0
- package/dist/schemas/activity.js +70 -0
- package/dist/schemas/activity.js.map +1 -0
- package/dist/schemas/agent.d.ts +189 -0
- package/dist/schemas/agent.d.ts.map +1 -0
- package/dist/schemas/agent.js +170 -0
- package/dist/schemas/agent.js.map +1 -0
- package/dist/schemas/agents.d.ts +690 -0
- package/dist/schemas/agents.d.ts.map +1 -0
- package/dist/schemas/agents.js +314 -0
- package/dist/schemas/agents.js.map +1 -0
- package/dist/schemas/automations.d.ts +736 -0
- package/dist/schemas/automations.d.ts.map +1 -0
- package/dist/schemas/automations.js +218 -0
- package/dist/schemas/automations.js.map +1 -0
- package/dist/schemas/capabilities.d.ts +753 -0
- package/dist/schemas/capabilities.d.ts.map +1 -0
- package/dist/schemas/capabilities.js +269 -0
- package/dist/schemas/capabilities.js.map +1 -0
- package/dist/schemas/ci.d.ts +179 -0
- package/dist/schemas/ci.d.ts.map +1 -0
- package/dist/schemas/ci.js +99 -0
- package/dist/schemas/ci.js.map +1 -0
- package/dist/schemas/claude-gate.d.ts +13 -0
- package/dist/schemas/claude-gate.d.ts.map +1 -0
- package/dist/schemas/claude-gate.js +8 -0
- package/dist/schemas/claude-gate.js.map +1 -0
- package/dist/schemas/codebase-health.d.ts +56 -0
- package/dist/schemas/codebase-health.d.ts.map +1 -0
- package/dist/schemas/codebase-health.js +43 -0
- package/dist/schemas/codebase-health.js.map +1 -0
- package/dist/schemas/computers.d.ts +386 -0
- package/dist/schemas/computers.d.ts.map +1 -0
- package/dist/schemas/computers.js +107 -0
- package/dist/schemas/computers.js.map +1 -0
- package/dist/schemas/drafts.d.ts +84 -0
- package/dist/schemas/drafts.d.ts.map +1 -0
- package/dist/schemas/drafts.js +44 -0
- package/dist/schemas/drafts.js.map +1 -0
- package/dist/schemas/environment.d.ts +349 -0
- package/dist/schemas/environment.d.ts.map +1 -0
- package/dist/schemas/environment.js +111 -0
- package/dist/schemas/environment.js.map +1 -0
- package/dist/schemas/exit.d.ts +151 -0
- package/dist/schemas/exit.d.ts.map +1 -0
- package/dist/schemas/exit.js +115 -0
- package/dist/schemas/exit.js.map +1 -0
- package/dist/schemas/extension-updates.d.ts +1014 -0
- package/dist/schemas/extension-updates.d.ts.map +1 -0
- package/dist/schemas/extension-updates.js +197 -0
- package/dist/schemas/extension-updates.js.map +1 -0
- package/dist/schemas/fast-mode.d.ts +8 -0
- package/dist/schemas/fast-mode.d.ts.map +1 -0
- package/dist/schemas/fast-mode.js +3 -0
- package/dist/schemas/fast-mode.js.map +1 -0
- package/dist/schemas/git-history.d.ts +238 -0
- package/dist/schemas/git-history.d.ts.map +1 -0
- package/dist/schemas/git-history.js +152 -0
- package/dist/schemas/git-history.js.map +1 -0
- package/dist/schemas/git.d.ts +471 -0
- package/dist/schemas/git.d.ts.map +1 -0
- package/dist/schemas/git.js +204 -0
- package/dist/schemas/git.js.map +1 -0
- package/dist/schemas/history.d.ts +100 -0
- package/dist/schemas/history.d.ts.map +1 -0
- package/dist/schemas/history.js +54 -0
- package/dist/schemas/history.js.map +1 -0
- package/dist/schemas/hosts.d.ts +41 -0
- package/dist/schemas/hosts.d.ts.map +1 -0
- package/dist/schemas/hosts.js +18 -0
- package/dist/schemas/hosts.js.map +1 -0
- package/dist/schemas/intentic.d.ts +5 -0
- package/dist/schemas/intentic.d.ts.map +1 -0
- package/dist/schemas/intentic.js +3 -0
- package/dist/schemas/intentic.js.map +1 -0
- package/dist/schemas/internal.d.ts +8 -0
- package/dist/schemas/internal.d.ts.map +1 -0
- package/dist/schemas/internal.js +12 -0
- package/dist/schemas/internal.js.map +1 -0
- package/dist/schemas/inventory.d.ts +171 -0
- package/dist/schemas/inventory.d.ts.map +1 -0
- package/dist/schemas/inventory.js +51 -0
- package/dist/schemas/inventory.js.map +1 -0
- package/dist/schemas/logs.d.ts +67 -0
- package/dist/schemas/logs.d.ts.map +1 -0
- package/dist/schemas/logs.js +54 -0
- package/dist/schemas/logs.js.map +1 -0
- package/dist/schemas/loops.d.ts +415 -0
- package/dist/schemas/loops.d.ts.map +1 -0
- package/dist/schemas/loops.js +188 -0
- package/dist/schemas/loops.js.map +1 -0
- package/dist/schemas/maintenance.d.ts +557 -0
- package/dist/schemas/maintenance.d.ts.map +1 -0
- package/dist/schemas/maintenance.js +201 -0
- package/dist/schemas/maintenance.js.map +1 -0
- package/dist/schemas/marketplace.d.ts +64 -0
- package/dist/schemas/marketplace.d.ts.map +1 -0
- package/dist/schemas/marketplace.js +17 -0
- package/dist/schemas/marketplace.js.map +1 -0
- package/dist/schemas/panels.d.ts +61 -0
- package/dist/schemas/panels.d.ts.map +1 -0
- package/dist/schemas/panels.js +51 -0
- package/dist/schemas/panels.js.map +1 -0
- package/dist/schemas/personas.d.ts +122 -0
- package/dist/schemas/personas.d.ts.map +1 -0
- package/dist/schemas/personas.js +102 -0
- package/dist/schemas/personas.js.map +1 -0
- package/dist/schemas/plan-limits.d.ts +172 -0
- package/dist/schemas/plan-limits.d.ts.map +1 -0
- package/dist/schemas/plan-limits.js +126 -0
- package/dist/schemas/plan-limits.js.map +1 -0
- package/dist/schemas/ports.d.ts +71 -0
- package/dist/schemas/ports.d.ts.map +1 -0
- package/dist/schemas/ports.js +42 -0
- package/dist/schemas/ports.js.map +1 -0
- package/dist/schemas/provider-oauth.d.ts +128 -0
- package/dist/schemas/provider-oauth.d.ts.map +1 -0
- package/dist/schemas/provider-oauth.js +91 -0
- package/dist/schemas/provider-oauth.js.map +1 -0
- package/dist/schemas/provider-subscriptions.d.ts +9 -0
- package/dist/schemas/provider-subscriptions.d.ts.map +1 -0
- package/dist/schemas/provider-subscriptions.js +3 -0
- package/dist/schemas/provider-subscriptions.js.map +1 -0
- package/dist/schemas/public.d.ts +32 -0
- package/dist/schemas/public.d.ts.map +1 -0
- package/dist/schemas/public.js +29 -0
- package/dist/schemas/public.js.map +1 -0
- package/dist/schemas/push.d.ts +55 -0
- package/dist/schemas/push.d.ts.map +1 -0
- package/dist/schemas/push.js +60 -0
- package/dist/schemas/push.js.map +1 -0
- package/dist/schemas/secrets.d.ts +86 -0
- package/dist/schemas/secrets.d.ts.map +1 -0
- package/dist/schemas/secrets.js +51 -0
- package/dist/schemas/secrets.js.map +1 -0
- package/dist/schemas/sessions.d.ts +32 -0
- package/dist/schemas/sessions.d.ts.map +1 -0
- package/dist/schemas/sessions.js +11 -0
- package/dist/schemas/sessions.js.map +1 -0
- package/dist/schemas/settings.d.ts +548 -0
- package/dist/schemas/settings.d.ts.map +1 -0
- package/dist/schemas/settings.js +259 -0
- package/dist/schemas/settings.js.map +1 -0
- package/dist/schemas/share.d.ts +49 -0
- package/dist/schemas/share.d.ts.map +1 -0
- package/dist/schemas/share.js +26 -0
- package/dist/schemas/share.js.map +1 -0
- package/dist/schemas/shared.d.ts +22 -0
- package/dist/schemas/shared.d.ts.map +1 -0
- package/dist/schemas/shared.js +16 -0
- package/dist/schemas/shared.js.map +1 -0
- package/dist/schemas/system.d.ts +86 -0
- package/dist/schemas/system.d.ts.map +1 -0
- package/dist/schemas/system.js +64 -0
- package/dist/schemas/system.js.map +1 -0
- package/dist/schemas/terminal.d.ts +230 -0
- package/dist/schemas/terminal.d.ts.map +1 -0
- package/dist/schemas/terminal.js +133 -0
- package/dist/schemas/terminal.js.map +1 -0
- package/dist/schemas/usage.d.ts +113 -0
- package/dist/schemas/usage.d.ts.map +1 -0
- package/dist/schemas/usage.js +91 -0
- package/dist/schemas/usage.js.map +1 -0
- package/dist/schemas/vpn.d.ts +229 -0
- package/dist/schemas/vpn.d.ts.map +1 -0
- package/dist/schemas/vpn.js +115 -0
- package/dist/schemas/vpn.js.map +1 -0
- package/dist/schemas/webext.d.ts +98 -0
- package/dist/schemas/webext.d.ts.map +1 -0
- package/dist/schemas/webext.js +36 -0
- package/dist/schemas/webext.js.map +1 -0
- package/dist/schemas/workflows.d.ts +881 -0
- package/dist/schemas/workflows.d.ts.map +1 -0
- package/dist/schemas/workflows.js +164 -0
- package/dist/schemas/workflows.js.map +1 -0
- package/dist/schemas/workspace-repos.d.ts +143 -0
- package/dist/schemas/workspace-repos.d.ts.map +1 -0
- package/dist/schemas/workspace-repos.js +87 -0
- package/dist/schemas/workspace-repos.js.map +1 -0
- package/dist/schemas/workspace-search.d.ts +170 -0
- package/dist/schemas/workspace-search.d.ts.map +1 -0
- package/dist/schemas/workspace-search.js +85 -0
- package/dist/schemas/workspace-search.js.map +1 -0
- package/dist/schemas/workspace-setup.d.ts +48 -0
- package/dist/schemas/workspace-setup.d.ts.map +1 -0
- package/dist/schemas/workspace-setup.js +26 -0
- package/dist/schemas/workspace-setup.js.map +1 -0
- package/dist/schemas/workspace-tree.d.ts +120 -0
- package/dist/schemas/workspace-tree.d.ts.map +1 -0
- package/dist/schemas/workspace-tree.js +111 -0
- package/dist/schemas/workspace-tree.js.map +1 -0
- package/dist/webext-links.d.ts +13 -0
- package/dist/webext-links.d.ts.map +1 -0
- package/dist/webext-links.js +24 -0
- package/dist/webext-links.js.map +1 -0
- package/dist/webext-protocol.d.ts +8 -0
- package/dist/webext-protocol.d.ts.map +1 -0
- package/dist/webext-protocol.js +7 -0
- package/dist/webext-protocol.js.map +1 -0
- package/dist/workflow-faults.d.ts +1 -1
- package/dist/workflow-faults.d.ts.map +1 -1
- package/dist/workspace-state.d.ts +11 -2
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +4 -2
- package/dist/workspace-state.js.map +1 -1
- package/package.json +17 -6
- package/src/agent-catalog.test.ts +1 -1
- package/src/agent-catalog.ts +4 -11
- package/src/chores/chores.ts +1 -1
- package/src/chores/probes.ts +1 -1
- package/src/chores/stack.test.ts +19 -0
- package/src/chores/stack.ts +19 -3
- package/src/chores/verdict.test.ts +11 -1
- package/src/chores/verdict.ts +1 -1
- package/src/command-classes.test.ts +378 -0
- package/src/command-classes.ts +378 -0
- package/src/contracts/activity.contract.ts +1 -1
- package/src/contracts/agent.contract.ts +22 -12
- package/src/contracts/agents.contract.ts +6 -6
- package/src/contracts/automations.contract.ts +2 -2
- package/src/contracts/capabilities.contract.ts +3 -4
- package/src/contracts/chores.contract.ts +2 -1
- package/src/contracts/ci.contract.ts +2 -2
- package/src/contracts/claude.contract.ts +2 -2
- package/src/contracts/cursor.contract.ts +2 -2
- package/src/contracts/drafts.contract.ts +2 -1
- package/src/contracts/endpoints.contract.ts +2 -1
- package/src/contracts/exit.contract.ts +2 -1
- package/src/contracts/extensions.contract.ts +5 -5
- package/src/contracts/git.contract.ts +19 -18
- package/src/contracts/grok.contract.ts +2 -1
- package/src/contracts/history.contract.ts +2 -1
- package/src/contracts/host.contract.ts +4 -1
- package/src/contracts/intentic.contract.ts +2 -1
- package/src/contracts/inventory.contract.ts +1 -1
- package/src/contracts/logs.contract.ts +7 -1
- package/src/contracts/loops.contract.ts +2 -2
- package/src/contracts/panels.contract.ts +2 -1
- package/src/contracts/personas.contract.ts +3 -3
- package/src/contracts/ports.contract.ts +3 -2
- package/src/contracts/prepush.contract.ts +2 -1
- package/src/contracts/providers.contract.ts +2 -1
- package/src/contracts/public.contract.ts +3 -2
- package/src/contracts/push.contract.ts +2 -1
- package/src/contracts/runner.contract.ts +33 -1
- package/src/contracts/secrets.contract.ts +2 -1
- package/src/contracts/sessions.contract.ts +1 -1
- package/src/contracts/settings.contract.ts +3 -9
- package/src/contracts/share.contract.ts +3 -2
- package/src/contracts/skills.contract.ts +2 -1
- package/src/contracts/system.contract.ts +6 -9
- package/src/contracts/translator.contract.ts +4 -1
- package/src/contracts/usage.contract.ts +1 -1
- package/src/contracts/vpn.contract.ts +2 -8
- package/src/contracts/webext.contract.ts +37 -0
- package/src/contracts/workflows.contract.ts +2 -2
- package/src/contracts/workspace.contract.ts +10 -12
- package/src/conversation-ids.test.ts +1 -1
- package/src/definition-action.ts +8 -0
- package/src/definition.ts +235 -0
- package/src/events.ts +128 -22
- package/src/fast-tier.ts +1 -1
- package/src/history-state.ts +5 -0
- package/src/host-protocol.ts +1 -1
- package/src/hostnames.test.ts +2 -2
- package/src/index.ts +61 -1
- package/src/listener-protocol.ts +1 -1
- package/src/quick-model.ts +1 -1
- package/src/runner-protocol.ts +35 -5
- package/src/schemas/activity.ts +123 -0
- package/src/schemas/agent.ts +409 -0
- package/src/schemas/agents.ts +802 -0
- package/src/schemas/automations.ts +510 -0
- package/src/schemas/capabilities.ts +729 -0
- package/src/schemas/ci.ts +235 -0
- package/src/schemas/claude-gate.ts +13 -0
- package/src/schemas/codebase-health.ts +64 -0
- package/src/schemas/computers.ts +287 -0
- package/src/schemas/drafts.ts +108 -0
- package/src/schemas/environment.ts +276 -0
- package/src/schemas/exit.ts +222 -0
- package/src/schemas/extension-updates.ts +322 -0
- package/src/schemas/fast-mode.ts +8 -0
- package/src/schemas/git-history.ts +265 -0
- package/src/schemas/git.ts +430 -0
- package/src/schemas/history.ts +112 -0
- package/src/schemas/hosts.ts +37 -0
- package/src/schemas/intentic.ts +2 -0
- package/src/schemas/internal.ts +17 -0
- package/src/schemas/inventory.ts +68 -0
- package/src/schemas/logs.ts +96 -0
- package/src/schemas/loops.ts +401 -0
- package/src/schemas/maintenance.ts +421 -0
- package/src/schemas/marketplace.ts +23 -0
- package/src/schemas/panels.ts +99 -0
- package/src/schemas/personas.ts +281 -0
- package/src/schemas/plan-limits.ts +255 -0
- package/src/schemas/ports.ts +84 -0
- package/src/schemas/provider-oauth.ts +191 -0
- package/src/schemas/provider-subscriptions.ts +11 -0
- package/src/schemas/public.ts +52 -0
- package/src/schemas/push.ts +112 -0
- package/src/schemas/secrets.ts +68 -0
- package/src/schemas/sessions.ts +16 -0
- package/src/schemas/settings.ts +932 -0
- package/src/schemas/share.ts +71 -0
- package/src/schemas/shared.ts +32 -0
- package/src/schemas/system.ts +156 -0
- package/src/schemas/terminal.ts +286 -0
- package/src/schemas/usage.ts +303 -0
- package/src/{schemas.test.ts → schemas/version-seam.test.ts} +4 -2
- package/src/schemas/vpn.ts +215 -0
- package/src/schemas/webext.ts +79 -0
- package/src/schemas/workflows.ts +413 -0
- package/src/schemas/workspace-repos.ts +123 -0
- package/src/schemas/workspace-search.ts +141 -0
- package/src/schemas/workspace-setup.ts +43 -0
- package/src/schemas/workspace-tree.ts +234 -0
- package/src/title.test.ts +1 -1
- package/src/webext-links.ts +80 -0
- package/src/webext-protocol.ts +27 -0
- package/src/workflow-faults.test.ts +1 -1
- package/src/workflow-faults.ts +1 -1
- package/src/workspace-state.test.ts +7 -3
- package/src/workspace-state.ts +27 -13
- package/dist/schemas.d.ts +0 -9800
- package/dist/schemas.d.ts.map +0 -1
- package/dist/schemas.js +0 -4252
- package/dist/schemas.js.map +0 -1
- package/src/schemas.ts +0 -9999
package/src/runner-protocol.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { DefinitionActionSchema } from "./definition-action.js";
|
|
2
3
|
|
|
3
4
|
/* THE RUNNER LINK'S EDGES: the handshake on /system/runners/connect, the env a runner boots with, and the
|
|
4
5
|
* placement value a turn request carries. The procedures spoken over the link once it exists live in
|
|
@@ -30,6 +31,13 @@ export const RunnerHelloSchema = z.object({
|
|
|
30
31
|
image: z.string(),
|
|
31
32
|
channel: z.string().optional(),
|
|
32
33
|
overlayHash: z.string().optional(),
|
|
34
|
+
/* The runner's DECLARED SHAPE, as the definition format spells it (definition.ts): a sandbox.toml whose
|
|
35
|
+
* only populated section is settings, because that is all a runner declares — capabilities and secrets
|
|
36
|
+
* never travel to one, and its repos are a mirror of the parent's git rather than clones with remotes.
|
|
37
|
+
* The parent diffs this against its own settings to itemize drift (a stale toolchain is a rebuild; a
|
|
38
|
+
* drifted setting is one applyDefinition call over this same socket), so parity stops being a bare
|
|
39
|
+
* "outdated" and becomes lines naming what differs. Absent on an image too old to derive one. */
|
|
40
|
+
definitionToml: z.string().optional(),
|
|
33
41
|
});
|
|
34
42
|
export type RunnerHello = z.infer<typeof RunnerHelloSchema>;
|
|
35
43
|
|
|
@@ -44,7 +52,8 @@ export const runnerEnrollUrl = (parentUrl: string): string => `${parentUrl.repla
|
|
|
44
52
|
* parent serves from its real git dirs (<historyRoot>/gits/<encoded id>), authenticated by the runner's own
|
|
45
53
|
* token as a bearer. One builder because three parties spell it: the parent's route, the runner's sync, and
|
|
46
54
|
* anyone debugging with a hand-typed clone. */
|
|
47
|
-
export const runnerGitUrl = (parentUrl: string, repo: string): string =>
|
|
55
|
+
export const runnerGitUrl = (parentUrl: string, repo: string): string =>
|
|
56
|
+
`${parentUrl.replace(/\/$/, "")}/system/runners/git/${encodeURIComponent(repo)}`;
|
|
48
57
|
|
|
49
58
|
/* Where a runner's push LANDS in the parent's git dirs. Never refs/heads/agent/<id> directly: that branch is
|
|
50
59
|
* checked out in the parent's mirror worktree, and git itself refuses updating a checked-out ref, which is a
|
|
@@ -52,6 +61,12 @@ export const runnerGitUrl = (parentUrl: string, repo: string): string => `${pare
|
|
|
52
61
|
* the mirror worktree to this ref, which advances the checked-out branch through the door git sanctions. */
|
|
53
62
|
export const runnerIncomingRef = (conversationId: string): string => `refs/runner-incoming/${conversationId}`;
|
|
54
63
|
|
|
64
|
+
/* THE CONTAINER A RUNNER'S NAME MEANS on the machine holding it, which is how the update and rebuild flows
|
|
65
|
+
* address it. The prefix is `ic`'s own (runner.rs SLUG_PREFIX) and the two must stay identical: a mismatch
|
|
66
|
+
* does not fail loudly, it sends an update at a container that does not exist and reports "no such sandbox"
|
|
67
|
+
* about a runner sitting right there in the list. */
|
|
68
|
+
export const runnerSlug = (name: string): string => `runner-${name}`;
|
|
69
|
+
|
|
55
70
|
/* THE CREDENTIAL DOORS: a runner's turns spend the ORIGIN sandbox's model providers, never accounts of their
|
|
56
71
|
* own. The shape is a service, not a sync: the parent resolves each turn's credential with the same code its
|
|
57
72
|
* local turns use and answers with the least that travels — an access token minted for the turn, or a route.
|
|
@@ -128,10 +143,20 @@ export const RunnerFactsSchema = z.object({
|
|
|
128
143
|
});
|
|
129
144
|
export type RunnerFacts = z.infer<typeof RunnerFactsSchema>;
|
|
130
145
|
|
|
146
|
+
/* WHETHER IT IS RUNNING WHAT THIS SANDBOX IS RUNNING (§7 of the design): `current` matches on image, channel
|
|
147
|
+
* and approved overlay; `outdated` differs on one of them and gets the update button; `unknown` is a runner
|
|
148
|
+
* that has never connected, or a parent that cannot name its own image (a dev daemon), where a warning would
|
|
149
|
+
* be one nobody can act on. Reported, never enforced: an outdated runner still runs turns. */
|
|
150
|
+
export const RunnerParitySchema = z.enum(["current", "outdated", "unknown"]);
|
|
151
|
+
export type RunnerParity = z.infer<typeof RunnerParitySchema>;
|
|
152
|
+
|
|
131
153
|
// One runner as the owner's views list it: enrolled state plus whatever the hub knows right now, the
|
|
132
154
|
// HostSummary shape retold for a runner (no platform/scopes, parity instead).
|
|
133
155
|
export const RunnerSummarySchema = z.object({
|
|
134
156
|
id: z.string(),
|
|
157
|
+
// The connected computer holding it, when this sandbox is what asked for it (the Computers view's create
|
|
158
|
+
// flow). Absent for one started by hand on a machine, which this sandbox can dispatch to but not manage.
|
|
159
|
+
host: z.string().optional(),
|
|
135
160
|
online: z.boolean(),
|
|
136
161
|
version: z.string().optional(),
|
|
137
162
|
image: z.string().optional(),
|
|
@@ -139,6 +164,14 @@ export const RunnerSummarySchema = z.object({
|
|
|
139
164
|
overlayHash: z.string().optional(),
|
|
140
165
|
facts: RunnerFactsSchema.optional(),
|
|
141
166
|
lastSeen: z.number().optional(),
|
|
167
|
+
// Computed by the daemon (runners/runner-parity.ts) rather than by each surface, so the badge on a row and
|
|
168
|
+
// the note in the placement picker cannot disagree about the same runner.
|
|
169
|
+
parity: RunnerParitySchema,
|
|
170
|
+
/* Where the runner's environment stands against this sandbox's, one line per difference (the definition
|
|
171
|
+
* surface's drift unit, computed parent-side from the hello's definitionToml plus the overlay hashes).
|
|
172
|
+
* Absent when the runner never said, empty when they agree. Lines whose subject is a Setting are fixable
|
|
173
|
+
* over the live link (the sync door); an overlay line takes a rebuild. */
|
|
174
|
+
drift: z.array(DefinitionActionSchema).optional(),
|
|
142
175
|
});
|
|
143
176
|
export type RunnerSummary = z.infer<typeof RunnerSummarySchema>;
|
|
144
177
|
|
|
@@ -202,8 +235,5 @@ export type RunnerTurn = z.infer<typeof RunnerTurnSchema>;
|
|
|
202
235
|
* client sends them. `runner` implies isolation, a remote conversation is always branch-anchored, because its
|
|
203
236
|
* branch is the unit that moves between machines. Absent means local, which is why this is optional
|
|
204
237
|
* everywhere: the default costs nothing to anyone who never uses it. */
|
|
205
|
-
export const AgentPlacementSchema = z.union([
|
|
206
|
-
z.object({ kind: z.literal("local") }),
|
|
207
|
-
z.object({ kind: z.literal("runner"), id: z.string().min(1) }),
|
|
208
|
-
]);
|
|
238
|
+
export const AgentPlacementSchema = z.union([z.object({ kind: z.literal("local") }), z.object({ kind: z.literal("runner"), id: z.string().min(1) })]);
|
|
209
239
|
export type AgentPlacement = z.infer<typeof AgentPlacementSchema>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// activity: the activity audit log (historyRoot/activity.jsonl)
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { AgentOriginSchema } from "./agent.js";
|
|
4
|
+
// One provider-agnostic event per agent↔provider interaction, appended by the daemon only (never the agent,
|
|
5
|
+
// the log lives under historyRoot, outside /work, so the agent can't read or rewrite its own trail). Discord
|
|
6
|
+
// is the first source; other cli providers reuse the same shape.
|
|
7
|
+
|
|
8
|
+
export const ActivityEventSchema = z.object({
|
|
9
|
+
id: z.string().describe("The entry's own id."),
|
|
10
|
+
// Epoch ms; also the paging cursor.
|
|
11
|
+
at: z.number().describe("When it happened, in milliseconds. Also what you page by."),
|
|
12
|
+
// "discord", …; absent on provider-less system events (a cron automation.run).
|
|
13
|
+
provider: z.string().optional().describe("Which outside service, when one was involved. Absent for the sandbox's own events."),
|
|
14
|
+
// Which provider account handled the turn, the attribution key for per-account usage totals. Absent on
|
|
15
|
+
// provider-less events and turns that ran on the provider's default account.
|
|
16
|
+
account: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Which account handled it. Absent for the sandbox's own events and for work run on a provider's default."),
|
|
20
|
+
direction: z.enum(["in", "out", "system"]).describe("Whether something arrived, something went out, or the sandbox did it to itself."),
|
|
21
|
+
// in: message.received | voice_utterance.received | voice_transcript.received
|
|
22
|
+
// out: message.send | reaction.add | messages.read | api.call (unclassified provider endpoint)
|
|
23
|
+
// system: gateway.login_failed | dispatch.failed | voice.session_started | voice.session_ended | automation.run
|
|
24
|
+
// | turn.started | turn.plan | turn.error | turn.completed (agent turn lifecycle; provider = claude/codex)
|
|
25
|
+
// | rule.blocked_push | rule.held_work | rule.continued_turn (a rule DID something, see RuleSchema.
|
|
26
|
+
// Only the three outcomes a person would otherwise have no explanation for: a push that did not
|
|
27
|
+
// go, work that did not arrive, a turn that did not end. A rule that ran and passed says nothing,
|
|
28
|
+
// because a feed that logs every green check is one the eye learns to skip.)
|
|
29
|
+
type: z
|
|
30
|
+
.string()
|
|
31
|
+
.describe(
|
|
32
|
+
"Exactly what happened: a message received or sent, a reaction, a turn starting or ending, a rule doing something. A rule that ran and passed says nothing here, because a feed of green ticks is one the eye learns to skip.",
|
|
33
|
+
),
|
|
34
|
+
channelId: z.string().optional().describe("Which channel or thread it happened in."),
|
|
35
|
+
// Inbound author display name.
|
|
36
|
+
author: z.string().optional().describe("Who sent it, for something that arrived."),
|
|
37
|
+
// Full message text (inbound) or sent payload content (outbound).
|
|
38
|
+
content: z.string().optional().describe("The message, in full, whichever direction it went."),
|
|
39
|
+
// Outbound HTTP method + endpoint path (tokens ride headers, never URLs).
|
|
40
|
+
method: z.string().optional().describe("The verb of an outgoing call."),
|
|
41
|
+
endpoint: z.string().optional().describe("The address of an outgoing call. Credentials travel in headers, so they are never here."),
|
|
42
|
+
// The agent turn that made/handled it, the join key between an inbound wake and its outbound calls.
|
|
43
|
+
sessionId: z.string().optional().describe("The provider session behind it."),
|
|
44
|
+
/* ONE TURN'S EVENTS, TIED TOGETHER. A turn writes four lifecycle events plus one per outbound provider call,
|
|
45
|
+
* and read as five rows they say one thing five times, so the feed groups on this instead. It cannot be
|
|
46
|
+
* sessionId: the runtime does not mint one until the stream's first frame, which is AFTER turn.started, so
|
|
47
|
+
* the very event carrying the prompt is the one that could never be joined. Minted by the turn itself. */
|
|
48
|
+
turnId: z
|
|
49
|
+
.string()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe(
|
|
52
|
+
"Ties one turn's entries together. A turn writes several, and read as separate rows they say one thing several times, so a feed groups on this.",
|
|
53
|
+
),
|
|
54
|
+
// The stable conversation the turn belongs to. Outlives sessionId, which a provider/account/harness switch
|
|
55
|
+
// retires mid-conversation, so this, not sessionId, is what "the same agent" means across a feed.
|
|
56
|
+
conversationId: z
|
|
57
|
+
.string()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe(
|
|
60
|
+
"Which conversation. This, rather than the provider session, is what the same agent means across a feed, because a session is retired whenever the model changes.",
|
|
61
|
+
),
|
|
62
|
+
// The conversation's display title as it stood when the event was written. Denormalised on purpose: the
|
|
63
|
+
// registry entry it came from is prunable and renameable, and an audit row must still read as words years
|
|
64
|
+
// later. Absent on the first event of a fresh conversation, the auto-namer has not run yet.
|
|
65
|
+
title: z
|
|
66
|
+
.string()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe(
|
|
69
|
+
"What that conversation was called at the time. Copied in rather than looked up, because an audit entry must still read as words years later, after the conversation has been renamed or pruned.",
|
|
70
|
+
),
|
|
71
|
+
// What woke the conversation from outside, when something did (see AgentOriginSchema), the feed's "who
|
|
72
|
+
// called me" attribution, and how a turn is filed under Discord rather than under the runtime that served it.
|
|
73
|
+
origin: AgentOriginSchema.optional().describe(
|
|
74
|
+
"What woke the conversation from outside, when something did. It is how a turn gets filed under the chat service that caused it rather than under the model that served it.",
|
|
75
|
+
),
|
|
76
|
+
automationIds: z.array(z.string()).optional().describe("Which automations were involved."),
|
|
77
|
+
outcome: z.enum(["ok", "error"]).optional().describe("How it ended."),
|
|
78
|
+
error: z.string().optional().describe("What went wrong, when something did."),
|
|
79
|
+
// Source-specific detail: guildId, attachments, transcript path, participants…
|
|
80
|
+
extra: z
|
|
81
|
+
.record(z.string(), z.unknown())
|
|
82
|
+
.optional()
|
|
83
|
+
.describe("Whatever else the source had to say: attachments, participants, a recording's path. Shape varies by source."),
|
|
84
|
+
});
|
|
85
|
+
export type ActivityEvent = z.infer<typeof ActivityEventSchema>;
|
|
86
|
+
export const ActivityQuerySchema = z.object({
|
|
87
|
+
provider: z.string().optional().describe("Narrow it to one outside service."),
|
|
88
|
+
limit: z.coerce.number().min(1).max(500).default(100).describe("How many entries to return."),
|
|
89
|
+
// `at` cursor, exclusive, newest-first paging.
|
|
90
|
+
before: z.coerce.number().optional().describe("Only entries older than this timestamp, so paging walks backwards through the feed."),
|
|
91
|
+
});
|
|
92
|
+
export type ActivityQuery = z.infer<typeof ActivityQuerySchema>;
|
|
93
|
+
export const ActivityListSchema = z.object({ events: z.array(ActivityEventSchema).describe("The audit entries, newest first.") });
|
|
94
|
+
// Live connection health, probed per provider capability (not stored): gateway state from the client pool
|
|
95
|
+
// (idle = the gateway is up but has no enabled listener automation to connect for, distinct from a
|
|
96
|
+
// connection that should be up but isn't; pairing = the socket is up but the credential is a ceremony nobody
|
|
97
|
+
// has finished, which no amount of waiting fixes), lastError from the newest system-error event in the log.
|
|
98
|
+
export const ActivityConnectionSchema = z.object({
|
|
99
|
+
capabilityId: z.string().describe("Which connection."),
|
|
100
|
+
provider: z.string().describe("Which service it is."),
|
|
101
|
+
gateway: z
|
|
102
|
+
.enum(["ready", "connecting", "pairing", "disconnected", "idle"])
|
|
103
|
+
.describe(
|
|
104
|
+
"Idle means it is up but has nothing to listen for, which is different from a connection that should be up and is not. Pairing means somebody started a sign-in and never finished it, which no amount of waiting will fix.",
|
|
105
|
+
),
|
|
106
|
+
lastError: z.string().optional().describe("The most recent thing that went wrong on it."),
|
|
107
|
+
});
|
|
108
|
+
export const ActivityStatusSchema = z.object({
|
|
109
|
+
connections: z
|
|
110
|
+
.array(ActivityConnectionSchema)
|
|
111
|
+
.describe("Each source feeding the record, and whether it is working. Probed now rather than remembered."),
|
|
112
|
+
// The daemon's live voice session, when one is up.
|
|
113
|
+
voice: z
|
|
114
|
+
.object({
|
|
115
|
+
channelId: z.string().describe("Which channel."),
|
|
116
|
+
channelName: z.string().describe("What it is called."),
|
|
117
|
+
startedAt: z.number().describe("When it joined, in milliseconds."),
|
|
118
|
+
participants: z.array(z.string()).describe("Who else is in it."),
|
|
119
|
+
})
|
|
120
|
+
.optional()
|
|
121
|
+
.describe("A voice call the sandbox is currently in, when it is in one."),
|
|
122
|
+
});
|
|
123
|
+
export type ActivityStatus = z.infer<typeof ActivityStatusSchema>;
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AgentPlacementSchema } from "../runner-protocol.js";
|
|
3
|
+
import { entryId } from "./internal.js";
|
|
4
|
+
// The agent runtimes the daemon can serve, the vocabulary every surface that picks an agent shares (chat
|
|
5
|
+
// turns, automations). The NATIVE providers have dedicated adapters (and their ids are reserved); an
|
|
6
|
+
// `endpoint/<id>` value names an installed `endpoint`-kind capability (a model API the user pointed us at,
|
|
7
|
+
// see EndpointConfigSchema); any other value is the id of an installed `agent`-kind capability served over
|
|
8
|
+
// ACP (Agent Client Protocol).
|
|
9
|
+
// Kept as a bare string on the wire (not an enum) so an unknown id is a clean error frame from the agent
|
|
10
|
+
// route, the same bet RepoParamSchema makes, and adding an ACP agent needs no contract change.
|
|
11
|
+
export const NATIVE_PROVIDERS = ["claude", "codex", "grok", "kimi", "gemini", "cursor"] as const;
|
|
12
|
+
export type NativeProvider = (typeof NATIVE_PROVIDERS)[number];
|
|
13
|
+
export const AgentProviderSchema = z.string().min(1);
|
|
14
|
+
export type AgentProvider = z.infer<typeof AgentProviderSchema>;
|
|
15
|
+
// The provider naming a catalog in the one route every native provider shares (providers.contract.ts). An ENUM
|
|
16
|
+
// rather than the bare-string schema above, and deliberately so: the open vocabulary exists because an ACP agent
|
|
17
|
+
// or an endpoint can be added without a contract change, but neither has a daemon-held catalog, this route's
|
|
18
|
+
// subjects are exactly the five the daemon keeps one for. Closing it here is what makes an unknown id a 400 from
|
|
19
|
+
// the contract instead of a registry lookup that reads back `undefined` and serves an empty list.
|
|
20
|
+
export const NativeProviderParamSchema = z.object({ provider: z.enum(NATIVE_PROVIDERS) });
|
|
21
|
+
// The harness (agentic loop) a turn runs on, orthogonal to the provider. See AgentTurnSchema.harness.
|
|
22
|
+
export const AgentHarnessSchema = z.enum(["native", "claude-code"]);
|
|
23
|
+
export type AgentHarness = z.infer<typeof AgentHarnessSchema>;
|
|
24
|
+
// One repository at one immutable commit. Workflow runs use this both as the checkout instruction for every
|
|
25
|
+
// candidate and as the comparison base written into handoffs, so a multi-repo run has one provenance record
|
|
26
|
+
// rather than a hard-coded branch name that only happens to work in the root repository.
|
|
27
|
+
export const RepoBaseSchema = z.object({ repo: z.string(), base: z.string().min(1) });
|
|
28
|
+
export type RepoBase = z.infer<typeof RepoBaseSchema>;
|
|
29
|
+
// What the user is looking at in the editor, attached to a turn only when they explicitly opt in (the
|
|
30
|
+
// composer chip, off by default). The daemon folds it into the prompt as a context note, so deictic
|
|
31
|
+
// prompts ("fix this") resolve without an @-mention. Selection is bounded, it's context, not an upload.
|
|
32
|
+
export const EditorContextSchema = z.object({
|
|
33
|
+
// Workspace-relative path of the file open in the editor.
|
|
34
|
+
file: z.string().min(1).describe("The file open in the editor, as a workspace path."),
|
|
35
|
+
// 1-based line range of the selection; absent when the whole file is the context.
|
|
36
|
+
startLine: z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.min(1)
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("First line of the selection, counting from one. Leave both out when the whole file is the context."),
|
|
42
|
+
endLine: z.number().int().min(1).optional().describe("Last line of the selection, counting from one."),
|
|
43
|
+
// The selected text itself, truncated client-side to the cap.
|
|
44
|
+
selection: z
|
|
45
|
+
.string()
|
|
46
|
+
.max(20_000)
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("The selected text itself. Cut it down before sending if it is long: this is context, not an upload."),
|
|
49
|
+
});
|
|
50
|
+
export type EditorContext = z.infer<typeof EditorContextSchema>;
|
|
51
|
+
// The client-minted stable conversation identity. Constrained because isolated conversations also use it in
|
|
52
|
+
// branch names (agent/<id>) and filesystem paths, the regex is the injection guard. Shared by turn + attach,
|
|
53
|
+
// and by the workspace scope (WorkspaceScopeSchema), which names a conversation to read a file tree AS.
|
|
54
|
+
export const ConversationIdSchema = z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/);
|
|
55
|
+
// Where a conversation came from when nobody typed it into the browser: an automation wake carrying a message
|
|
56
|
+
// from OUTSIDE the sandbox (a Discord mention, a web-chat visitor, a webhook). Such a wake runs as an ordinary
|
|
57
|
+
// isolated conversation, registry entry, worktree, chat tab, land flow, and this is the only thing that
|
|
58
|
+
// distinguishes it on the surface: the card's provenance line and the reason its first prompt is not the
|
|
59
|
+
// user's. Set daemon-side by the dispatcher that received the message; the browser never sends one.
|
|
60
|
+
export const AgentOriginSchema = z.object({
|
|
61
|
+
// The automation whose configured prompt opened the conversation.
|
|
62
|
+
automationId: z.string(),
|
|
63
|
+
// The listener provider that received the message ("discord", "webchat", …) or "webhook" for an event
|
|
64
|
+
// trigger. An open string for the same reason Trigger.provider is: sources are extension-declared.
|
|
65
|
+
provider: z.string(),
|
|
66
|
+
// The external thread it arrived on, a Discord channel id, a widget conversation id. Absent for webhooks.
|
|
67
|
+
channelId: z.string().optional(),
|
|
68
|
+
// Who sent it, as the source names them.
|
|
69
|
+
author: z.string().optional(),
|
|
70
|
+
});
|
|
71
|
+
export type AgentOrigin = z.infer<typeof AgentOriginSchema>;
|
|
72
|
+
/* The class of thing asking to START a session, the admission policy's key space. Derived daemon-side from
|
|
73
|
+
* the automation's trigger (guard/actions.ts wakeSourceOf) or named by the door itself (the workflow release
|
|
74
|
+
* gate); never sent by a client. Chat and loops are absent deliberately: both begin with the owner's own
|
|
75
|
+
* click, and holding the owner's work in their own queue is a queue entry that says nothing (the same argument
|
|
76
|
+
* fireAutomation's `cleared` makes about a by-hand fire). */
|
|
77
|
+
export const WakeSourceSchema = z.enum(["schedule", "event", "listener", "webchat", "workspace", "workflow"]);
|
|
78
|
+
export type WakeSource = z.infer<typeof WakeSourceSchema>;
|
|
79
|
+
// One admission verdict the owner can configure: let it run, hold it for approval, or refuse it outright.
|
|
80
|
+
export const AdmissionRuleSchema = z.enum(["allow", "hold", "deny"]);
|
|
81
|
+
export type AdmissionRule = z.infer<typeof AdmissionRuleSchema>;
|
|
82
|
+
/* WHAT KIND OF THING A SHELL COMMAND IS, the command gate's key space, the second layer under the admission
|
|
83
|
+
* floor above. The floor decides whether a session may START; these decide whether one PARTICULAR command
|
|
84
|
+
* inside a running session may go ahead, which is the only question left once the agent is already working.
|
|
85
|
+
*
|
|
86
|
+
* Five, chosen for one property: everything in them is hard or impossible to take back, so a person seeing it
|
|
87
|
+
* once beats an audit trail read afterwards. Everything else an agent runs, builds, tests, greps, edits, is
|
|
88
|
+
* recoverable in a container that is itself disposable, and gating it would be friction bought with nothing. */
|
|
89
|
+
export const CommandClassSchema = z.enum([
|
|
90
|
+
// Rewrites or discards committed work: force-push, hard reset, force-delete a branch, clean -f, filter-branch.
|
|
91
|
+
"git.destructive",
|
|
92
|
+
// Recursive-force deletion (`rm -rf`), and its spelling in a script (`fs.rm(p, { recursive: true })`).
|
|
93
|
+
"files.destructive",
|
|
94
|
+
/* State nothing here brings back: a formatted or overwritten disk, a deleted Docker volume, a recursive
|
|
95
|
+
* delete aimed at a root rather than at something inside one. The only class the daemon holds where the
|
|
96
|
+
* owner wrote no rule, which is why it is separate from files.destructive rather than a shade of it:
|
|
97
|
+
* `rm -rf build` is ordinary work in a disposable container and `rm -rf /` is the end of the machine. */
|
|
98
|
+
"system.destructive",
|
|
99
|
+
// Names credential material: a .env file, an ssh key, ~/.aws/credentials, .npmrc, a stored token file.
|
|
100
|
+
"secrets.access",
|
|
101
|
+
// Publishes outward and irreversibly: npm/pnpm/yarn/cargo publish, gh release create, docker push.
|
|
102
|
+
"package.publish",
|
|
103
|
+
// curl/wget to a non-local address, the general exfiltration channel under the per-provider actionRules.
|
|
104
|
+
"network.outbound",
|
|
105
|
+
]);
|
|
106
|
+
export type CommandClass = z.infer<typeof CommandClassSchema>;
|
|
107
|
+
/* THE ADMISSION FLOOR, the workspace-wide rule per wake source, consulted by the session.start guard on every
|
|
108
|
+
* outside-driven wake. Per-automation `requireApproval` / `holdForSeconds` remain the per-object override; the
|
|
109
|
+
* floor composes with them most-restrictive-wins, so "hold every webchat session" needs no edit to each
|
|
110
|
+
* automation. `workflow` is allow|deny only: the release gate answers a CI runner holding a connection with a
|
|
111
|
+
* deadline, so a hold there is indistinguishable from a timeout, deny is the honest refusal. */
|
|
112
|
+
export const AdmissionPolicySchema = z.object({
|
|
113
|
+
schedule: AdmissionRuleSchema.default("allow"),
|
|
114
|
+
event: AdmissionRuleSchema.default("allow"),
|
|
115
|
+
listener: AdmissionRuleSchema.default("allow"),
|
|
116
|
+
webchat: AdmissionRuleSchema.default("allow"),
|
|
117
|
+
workspace: AdmissionRuleSchema.default("allow"),
|
|
118
|
+
workflow: z.enum(["allow", "deny"]).default("allow"),
|
|
119
|
+
});
|
|
120
|
+
export type AdmissionPolicy = z.infer<typeof AdmissionPolicySchema>;
|
|
121
|
+
// How tool calls are gated, the Claude Agent SDK's PermissionMode, narrowed to the four the composer offers
|
|
122
|
+
// (the SDK also has 'dontAsk'/'auto', which have no UI here). The user picks one per turn AND the agent can
|
|
123
|
+
// move itself between them mid-turn, so this is both a turn input and the payload of the `mode` frame.
|
|
124
|
+
export const PermissionModeSchema = z.enum(["default", "acceptEdits", "plan", "bypassPermissions"]);
|
|
125
|
+
export type PermissionMode = z.infer<typeof PermissionModeSchema>;
|
|
126
|
+
/* WHERE A CONVERSATION WAS CUT FROM, the durable half of a fork, carried on the registry entry so both ends
|
|
127
|
+
* can find each other. `index` is the message the cut sat above in the SOURCE, which is what lets the source's
|
|
128
|
+
* transcript put the mark back in the right gap. */
|
|
129
|
+
export const ForkedFromSchema = z.object({
|
|
130
|
+
conversationId: ConversationIdSchema,
|
|
131
|
+
index: z.number().int().nonnegative(),
|
|
132
|
+
// Which files this fork opened on, the half of the choice that used to be silent, kept so the fork can
|
|
133
|
+
// still say it tomorrow rather than only in the seconds after the click.
|
|
134
|
+
files: z.enum(["then", "now"]),
|
|
135
|
+
});
|
|
136
|
+
export type ForkedFrom = z.infer<typeof ForkedFromSchema>;
|
|
137
|
+
export const AgentTurnSchema = z
|
|
138
|
+
.object({
|
|
139
|
+
prompt: z.string().describe("What to say to the agent. May be empty if you are only attaching files."),
|
|
140
|
+
// The client's display title for the conversation, seeds a FRESH registry entry (so a renamed draft's
|
|
141
|
+
// first turn keeps its user-chosen title); an existing entry's title always wins.
|
|
142
|
+
title: z
|
|
143
|
+
.string()
|
|
144
|
+
.max(80)
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("A title for a conversation this turn is opening. Ignored for a conversation that already has one."),
|
|
147
|
+
// Workspace-relative paths of files the user attached, already uploaded via /workspace/upload
|
|
148
|
+
// (the browser puts them under .intentic/records/artifacts/attachments/<uuid>/<name>). The daemon hands them to the
|
|
149
|
+
// provider: Claude reads them from disk via its Read tool; Codex gets images as native inputs.
|
|
150
|
+
attachments: z
|
|
151
|
+
.array(z.string().min(1))
|
|
152
|
+
.max(20)
|
|
153
|
+
.optional()
|
|
154
|
+
.describe("Files to hand the agent along with the prompt, as workspace paths. Upload them first."),
|
|
155
|
+
// Which provider (model + account) serves the turn; absent = claude. A sessionId only resumes on the
|
|
156
|
+
// provider that minted it (Claude Code sessions vs Codex threads vs Grok/OpenCode sessions are separate
|
|
157
|
+
// stores), a mid-conversation provider/account/harness switch sends `history` instead of resuming.
|
|
158
|
+
agent: AgentProviderSchema.optional().describe("Which model provider serves this turn. Leave it out for Claude."),
|
|
159
|
+
// Which harness (agentic loop) runs the turn, orthogonal to the provider above. Absent = "native": each
|
|
160
|
+
// provider on its own runtime (Claude Code SDK / Codex CLI / opencode) with its subscription OAuth.
|
|
161
|
+
// "claude-code" forces the Claude Code Agent SDK loop for ANY provider, codex/grok then drive their model
|
|
162
|
+
// through the sandbox's bundled Anthropic↔OpenAI translator, which needs that provider's API key (its
|
|
163
|
+
// subscription OAuth can't reach a gateway). For the claude provider the two are identical.
|
|
164
|
+
harness: AgentHarnessSchema.optional().describe("Which agentic loop runs the turn. Leave it out to use each provider's own."),
|
|
165
|
+
// Which connected account of that provider serves the turn; absent = the provider's first account.
|
|
166
|
+
account: z.string().optional().describe("Which of that provider's connected accounts pays for the turn. Leave it out for the first one."),
|
|
167
|
+
/* WHICH PERSONA THE TURN SHOWS THE OUTSIDE WORLD, a PersonaSchema id, deliberately NOT the `account`
|
|
168
|
+
* directly above it. The two words are one letter apart in meaning and a world apart in consequence:
|
|
169
|
+
* `account` is which subscription PAYS for the turn, `actsAs` is whose name is on what the turn posts.
|
|
170
|
+
* Naming both "account" is how someone eventually pins a nightly job to the right billing and the wrong
|
|
171
|
+
* Reddit.
|
|
172
|
+
*
|
|
173
|
+
* Absent means opposite things either side of the "is anyone watching" line, which is the owner's chosen
|
|
174
|
+
* posture and the reason this is resolved in one place (turnPersona): an ordinary chat with no persona
|
|
175
|
+
* keeps every connected account, because a person is there to catch a mistake; an `unattended` turn with
|
|
176
|
+
* no persona gets NONE, because at 3am the prompt's wording is the only thing left and that is not
|
|
177
|
+
* enough to bet an unrepeatable post on. */
|
|
178
|
+
actsAs: entryId.optional().describe("Which persona the turn speaks as out in the world. Not the same as which account pays for it."),
|
|
179
|
+
sessionId: z.string().optional().describe("Resume this provider session instead of starting a fresh one."),
|
|
180
|
+
// The client-minted stable conversation identity (survives provider/account/harness switches, which
|
|
181
|
+
// retire sessions). Keys the fleet registry entry and turn run, plus the worktree when isolated.
|
|
182
|
+
conversationId: ConversationIdSchema.optional().describe(
|
|
183
|
+
"The conversation this turn belongs to. You choose it, it survives model switches, and it is how you address the conversation later. Naming one that does not exist opens it.",
|
|
184
|
+
),
|
|
185
|
+
// When true, the turn runs in the conversation's isolated git worktree (created lazily on first use)
|
|
186
|
+
// instead of the shared /work tree, the parallel-agents mode. Requires conversationId.
|
|
187
|
+
isolated: z
|
|
188
|
+
.boolean()
|
|
189
|
+
.optional()
|
|
190
|
+
.describe(
|
|
191
|
+
"Work in this conversation's own private copy of the repos rather than the shared tree, so several agents can work at once. Needs a conversation id.",
|
|
192
|
+
),
|
|
193
|
+
/* WHERE the conversation executes, decided like `isolated` directly above: the request's choice on the
|
|
194
|
+
* first turn, the registry entry's on every turn after. `runner` implies isolation (the branch is what
|
|
195
|
+
* moves between machines) and needs a conversation id for the same reason `isolated` does. Absent =
|
|
196
|
+
* local. Design: docs/remote-runners-plan.md; refused until runners ship. */
|
|
197
|
+
placement: AgentPlacementSchema.optional().describe(
|
|
198
|
+
"Where this conversation runs: this sandbox (leave it out), or a paired runner by id. Decided on the first turn; later turns follow the conversation.",
|
|
199
|
+
),
|
|
200
|
+
/* Pin a NEW isolated conversation's worktree composition to these repository commits. Daemon-owned:
|
|
201
|
+
* ordinary chats omit it and keep rebasing onto the current workspace; a workflow supplies the one
|
|
202
|
+
* snapshot all of its candidates must share. Repeated iterations carry it too, which suppresses the
|
|
203
|
+
* ordinary pre-turn rebase for the lifetime of that workflow step. */
|
|
204
|
+
worktreeBase: z
|
|
205
|
+
.array(RepoBaseSchema)
|
|
206
|
+
.min(1)
|
|
207
|
+
.max(50)
|
|
208
|
+
.optional()
|
|
209
|
+
.describe(
|
|
210
|
+
"Pin a new private copy to these exact commits instead of today's workspace. Used when several agents must start from identical files.",
|
|
211
|
+
),
|
|
212
|
+
// Override landing for this turn only. Workflow steps set false so candidate branches cannot leak into
|
|
213
|
+
// the workspace before the synthesis step has compared them; ordinary turns inherit agent/workspace
|
|
214
|
+
// posture exactly as before.
|
|
215
|
+
autoLand: z
|
|
216
|
+
.boolean()
|
|
217
|
+
.optional()
|
|
218
|
+
.describe(
|
|
219
|
+
"Whether this turn's work merges into the workspace when it finishes. Overrides the conversation's own setting for this turn only.",
|
|
220
|
+
),
|
|
221
|
+
// Set ONLY by the daemon's own automation dispatchers: this turn opens a conversation on behalf of an
|
|
222
|
+
// outside message rather than a user. Recorded on the registry entry so the fleet can say where the
|
|
223
|
+
// agent came from. Requires conversationId, there is nothing to record it on otherwise.
|
|
224
|
+
origin: AgentOriginSchema.optional().describe(
|
|
225
|
+
"Set by the sandbox alone: this turn opened a conversation on behalf of a message from outside rather than a person.",
|
|
226
|
+
),
|
|
227
|
+
// No `history` field: a turn that switched provider/account/harness carries no transcript up the wire.
|
|
228
|
+
// The daemon seeds the replacement session from its OWN record of the conversation, which is keyed by
|
|
229
|
+
// conversationId and outlives every session (sessions/turn-transcript.ts → handoffHistory).
|
|
230
|
+
/* WHERE A FORK WAS CUT FROM, on its first turn, the one case the daemon cannot work out for itself,
|
|
231
|
+
* because a fork is a NEW conversation whose record is empty and the cut is a gesture only the client
|
|
232
|
+
* saw. `keep` counts the source's RECORD rows to copy, not its bubbles (see the web transcript's
|
|
233
|
+
* recordedRows). The daemon copies that prefix into the new conversation's record before the turn runs,
|
|
234
|
+
* after which a fork is an ordinary conversation: it seeds like any other and reads back in full.
|
|
235
|
+
* Requires conversationId, the fork it describes IS that conversation.
|
|
236
|
+
*
|
|
237
|
+
* `files` is the half the user actually chooses between, and the half that used to be silent. "now"
|
|
238
|
+
* inherits the workspace as it stands (the fork is a fresh line of conversation over today's files);
|
|
239
|
+
* "then" puts the fork on the files as they were AT THE CUT, which it can only do in a checkout of its
|
|
240
|
+
* own, so it implies `isolated`, and the daemon resolves the cut's per-repo commits from the source's
|
|
241
|
+
* own turn anchors rather than trusting the client with shas. A "then" fork of a conversation that has
|
|
242
|
+
* no anchor at that index falls back to "now" and says so on the turn, because silently starting from
|
|
243
|
+
* the wrong files is the failure this whole field exists to prevent. */
|
|
244
|
+
forkOf: z
|
|
245
|
+
.object({
|
|
246
|
+
conversationId: ConversationIdSchema.describe("The conversation this one was cut from."),
|
|
247
|
+
keep: z.number().int().nonnegative().describe("How many of that conversation's messages to copy in before this turn runs."),
|
|
248
|
+
files: z
|
|
249
|
+
.enum(["then", "now"])
|
|
250
|
+
.describe(
|
|
251
|
+
'Which files the fork opens on: "now" is the workspace as it stands, "then" is the files as they were at the cut, which needs a private copy.',
|
|
252
|
+
),
|
|
253
|
+
})
|
|
254
|
+
.optional()
|
|
255
|
+
.describe("Where this conversation was cut from, on its first turn only. Only the client knows this, so only the client can say it."),
|
|
256
|
+
// The browser sends the chosen model per turn; the provider token is the sandbox's own stored credential.
|
|
257
|
+
model: z.string().optional().describe("Which model to use. Leave it out for the provider's default."),
|
|
258
|
+
/* NOBODY PICKED A MODEL FOR THIS TURN, a surface started it (Fix with agent, a Maintenance chore, a
|
|
259
|
+
* Documentation or Acceptance run, the fix a failed pre-push check proposes) rather than a person at a
|
|
260
|
+
* composer. That is the whole distinction the flag carries, and it is why it cannot be inferred: a chat
|
|
261
|
+
* turn ALSO arrives with no `model` whenever the live catalog hasn't loaded yet, and the two want
|
|
262
|
+
* opposite defaults, the chat wants the provider's own catalog default, an unattended run wants the
|
|
263
|
+
* tier its owner chose for work that spends money while they are not watching.
|
|
264
|
+
*
|
|
265
|
+
* The daemon fills `agent`/`model`/`effort` from agentRunModels/agentRunEffort for any turn that says
|
|
266
|
+
* this and names none of them (startConversationTurn), walking that list until one can actually be
|
|
267
|
+
* started. Naming one still wins: every surface-started run now carries a caret that overrides the list
|
|
268
|
+
* for that run alone, and Acceptance picks per run because it fans a session out per story. Either way
|
|
269
|
+
* the pick is the user's, made a second ago. */
|
|
270
|
+
unattended: z
|
|
271
|
+
.boolean()
|
|
272
|
+
.optional()
|
|
273
|
+
.describe(
|
|
274
|
+
"Nobody chose a model for this turn because a screen started it rather than a person. The sandbox then fills in the model its owner picked for unwatched work.",
|
|
275
|
+
),
|
|
276
|
+
/* OUTSIDE CONTENT CAUSED THIS TURN, and what to call the source, "discord", "webchat", whichever
|
|
277
|
+
* listener provider carried the message. Set by the dispatchers that wake an agent on somebody else's
|
|
278
|
+
* words; absent for a turn the owner started, a schedule, or a workspace event.
|
|
279
|
+
*
|
|
280
|
+
* It is the birth half of the turn's taint (guard/turn-taint.ts). The other half marks itself as the
|
|
281
|
+
* turn works, a fetched page, a foreign MCP server's answer, and together they are what the command
|
|
282
|
+
* gate reads before letting a command read credential material unasked. Distinct from `unattended`,
|
|
283
|
+
* which is about whether anyone is WATCHING: a Front Desk wake is both, an owner asking the agent to read
|
|
284
|
+
* a web page is neither, and each flag governs a different decision. */
|
|
285
|
+
outsideWake: z
|
|
286
|
+
.string()
|
|
287
|
+
.min(1)
|
|
288
|
+
.optional()
|
|
289
|
+
.describe(
|
|
290
|
+
"Content from outside caused this turn, and what to call the source. It is what makes the sandbox treat the turn as carrying somebody else's words.",
|
|
291
|
+
),
|
|
292
|
+
// How tool calls are gated for this turn (the SDK's permissionMode, verbatim). 'plan' runs the
|
|
293
|
+
// propose → approve → execute flow; 'default' prompts per tool on the permission side channel;
|
|
294
|
+
// 'acceptEdits' auto-accepts file edits; 'bypassPermissions' runs everything. The agent can move
|
|
295
|
+
// itself between modes mid-turn (EnterPlanMode/ExitPlanMode), which rides back as a `mode` frame.
|
|
296
|
+
permissionMode: PermissionModeSchema.optional().describe(
|
|
297
|
+
"How tool calls are gated: ask each time, accept file edits, propose a plan first, or run everything. The agent can move itself between these mid-turn.",
|
|
298
|
+
),
|
|
299
|
+
/* Narrows the turn to these tool names (the SDK option of the same name, not to be confused with the
|
|
300
|
+
* daemon's MCP `tools`, which are servers). Absent ⇒ every tool the runtime has, which is what an
|
|
301
|
+
* owner-driven chat wants. Set by the automation dispatchers from Automation.allowedTools: a wake driven
|
|
302
|
+
* by an OUTSIDE message runs bypassPermissions like any other automation turn, so for a public Front Desk
|
|
303
|
+
* this list is the actual boundary, prompt wording is advice, an empty toolbox is not. */
|
|
304
|
+
allowedTools: z
|
|
305
|
+
.array(z.string().min(1))
|
|
306
|
+
.optional()
|
|
307
|
+
.describe(
|
|
308
|
+
"Narrow the turn to these tools. Leave it out for everything the runtime has. For a turn driven by an outside message this list is the real boundary, because prompt wording is only advice.",
|
|
309
|
+
),
|
|
310
|
+
effort: z.string().optional().describe("How hard the model should think, where the provider offers a choice."),
|
|
311
|
+
thinking: z.boolean().optional().describe("Whether to show the model's reasoning as it works."),
|
|
312
|
+
/* Ask the harness to serve this turn at fast speed, the same tokens at a higher rate, for a higher
|
|
313
|
+
* per-token price. A REQUEST, never a promise: the harness answers it against the plan, the model and
|
|
314
|
+
* the endpoint, and reports what it actually did on the `fast_mode` frame. Absent/false ⇒ standard
|
|
315
|
+
* speed, which is also what a runtime that doesn't declare the capability gets (turn-plan drops it).
|
|
316
|
+
*
|
|
317
|
+
* Not a sandbox setting, for the same reason effort isn't: it changes what a turn COSTS, so it belongs
|
|
318
|
+
* to the turn that spends it rather than to the workspace it ran in. */
|
|
319
|
+
fast: z
|
|
320
|
+
.boolean()
|
|
321
|
+
.optional()
|
|
322
|
+
.describe(
|
|
323
|
+
"Ask for the same work at a higher rate for a higher price. A request rather than a promise: the answer says what actually happened.",
|
|
324
|
+
),
|
|
325
|
+
/* KEEP THIS TURN ON THE MODEL I PICKED: the user's veto over automatic tier selection, riding the turn
|
|
326
|
+
* like `fast` does because it changes what the turn costs and so belongs to the turn rather than to the
|
|
327
|
+
* workspace. The judge still runs and the verdict is still recorded — a deny is the strongest label the
|
|
328
|
+
* calibration ledger ever gets (UsageTurn.tierDenied) — but nothing is substituted. The composer sends
|
|
329
|
+
* its conversation-level toggle here every turn, and the registry persists it beside `fast`, so the
|
|
330
|
+
* choice survives reopening the tab. Absent ⇒ no opinion, routing follows settings.autoTier. */
|
|
331
|
+
tierHold: z
|
|
332
|
+
.boolean()
|
|
333
|
+
.optional()
|
|
334
|
+
.describe(
|
|
335
|
+
"Run exactly the model that was picked, even when the turn looks simple enough for a cheaper one. The judgement is still recorded; nothing is substituted.",
|
|
336
|
+
),
|
|
337
|
+
// The opt-in editor context chip: what the user is looking at, folded into the prompt daemon-side.
|
|
338
|
+
editorContext: EditorContextSchema.optional().describe(
|
|
339
|
+
'What the user has open in their editor, folded into the prompt so that pointing words like "this" resolve.',
|
|
340
|
+
),
|
|
341
|
+
})
|
|
342
|
+
// An attachment-only send (no text) is legal; an entirely empty turn is not.
|
|
343
|
+
.refine((turn) => turn.prompt.trim().length > 0 || (turn.attachments?.length ?? 0) > 0, {
|
|
344
|
+
message: "prompt or attachments required",
|
|
345
|
+
})
|
|
346
|
+
.refine((turn) => turn.isolated !== true || turn.conversationId !== undefined, {
|
|
347
|
+
message: "isolated requires conversationId",
|
|
348
|
+
})
|
|
349
|
+
.refine((turn) => turn.worktreeBase === undefined || (turn.isolated === true && turn.conversationId !== undefined), {
|
|
350
|
+
message: "worktreeBase requires an isolated conversationId",
|
|
351
|
+
})
|
|
352
|
+
.refine((turn) => turn.origin === undefined || turn.conversationId !== undefined, {
|
|
353
|
+
message: "origin requires conversationId",
|
|
354
|
+
})
|
|
355
|
+
.refine((turn) => turn.forkOf === undefined || turn.conversationId !== undefined, {
|
|
356
|
+
message: "forkOf requires conversationId",
|
|
357
|
+
})
|
|
358
|
+
// A fork that wants the files as they were needs a checkout of its own to put them in, the shared tree is
|
|
359
|
+
// everyone else's too, and rolling it back under them is what `files: "then"` must never mean.
|
|
360
|
+
.refine((turn) => turn.forkOf?.files !== "then" || turn.isolated === true, {
|
|
361
|
+
message: 'forkOf.files "then" requires isolated',
|
|
362
|
+
});
|
|
363
|
+
export type AgentTurn = z.infer<typeof AgentTurnSchema>;
|
|
364
|
+
/* A MODEL CHOSEN FOR ONE SURFACE-STARTED RUN, what the caret on the shared run button (<AgentRunButton>) sends
|
|
365
|
+
* along with the click that starts it.
|
|
366
|
+
*
|
|
367
|
+
* Shared rather than re-declared per route because every surface that starts an agent for the user now carries
|
|
368
|
+
* that caret, and they must all mean the same thing by it: the pair rides onto the turn as `agent`/`model`, and
|
|
369
|
+
* the daemon's own fill step then leaves it alone (turn-resume.ts fills only what is absent). ABSENT is the
|
|
370
|
+
* ordinary case and the one to keep cheap, nobody touched the caret, so `agentRunModels` answers.
|
|
371
|
+
*
|
|
372
|
+
* Both halves or neither, because a model id is only meaningful to the provider that vends it: half a pick
|
|
373
|
+
* would send a Codex model id to Claude. Routes that accept this pass it through verbatim; a model this build
|
|
374
|
+
* has never heard of is a supported pick, since the picker offers a custom-id escape hatch. */
|
|
375
|
+
export const AgentRunPickSchema = z
|
|
376
|
+
.object({
|
|
377
|
+
agent: z.string().min(1).describe("Which provider."),
|
|
378
|
+
model: z
|
|
379
|
+
.string()
|
|
380
|
+
.min(1)
|
|
381
|
+
.describe("Which of its models. Both or neither, because a model name only means anything to the provider that serves it."),
|
|
382
|
+
})
|
|
383
|
+
.optional();
|
|
384
|
+
export type AgentRunPick = z.infer<typeof AgentRunPickSchema>;
|
|
385
|
+
// POST /agent's ack: the daemon-minted id of the detached turn run it started. The turn executes daemon-side
|
|
386
|
+
// regardless of any client connection; every window, the initiator included, renders it via /agent/attach.
|
|
387
|
+
export const StartedTurnSchema = z.object({
|
|
388
|
+
run: z.string().describe("The id of the run that just started. Hand it back when you attach, so the stream resumes rather than replaying."),
|
|
389
|
+
});
|
|
390
|
+
export type StartedTurn = z.infer<typeof StartedTurnSchema>;
|
|
391
|
+
// Attach to a conversation's turn run (live, or finished within the retention window). `run`+`after` is the
|
|
392
|
+
// resume cursor of a client whose stream dropped: frames after `after` replay when `run` still names the
|
|
393
|
+
// current run; a mismatch (a newer turn started meanwhile) replays that run from its first frame instead.
|
|
394
|
+
export const AttachTurnSchema = z.object({
|
|
395
|
+
conversationId: ConversationIdSchema.describe("Which conversation to watch."),
|
|
396
|
+
run: z
|
|
397
|
+
.string()
|
|
398
|
+
.optional()
|
|
399
|
+
.describe("The run you were watching. If a newer turn has started since, the stream replays that one from its beginning instead."),
|
|
400
|
+
after: z
|
|
401
|
+
.number()
|
|
402
|
+
.int()
|
|
403
|
+
.min(0)
|
|
404
|
+
.optional()
|
|
405
|
+
.describe(
|
|
406
|
+
"The last frame you already have. Everything after it replays, then the stream goes live. Leave it out to start from the beginning.",
|
|
407
|
+
),
|
|
408
|
+
});
|
|
409
|
+
export type AttachTurn = z.infer<typeof AttachTurnSchema>;
|