@intentic/sandbox-contract 1.232.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 +7 -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 +40 -2
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +4 -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 +7 -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 +45 -2
- package/dist/contracts/runner.contract.d.ts.map +1 -1
- package/dist/contracts/runner.contract.js +10 -2
- 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 +31 -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 +124 -21
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +29 -7
- package/dist/definition.js.map +1 -1
- package/dist/events.d.ts +101 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +25 -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 +355 -103
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -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 +2 -2
- package/dist/workspace-state.d.ts.map +1 -1
- package/dist/workspace-state.js +2 -2
- package/dist/workspace-state.js.map +1 -1
- package/package.json +15 -4
- 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 +4 -13
- 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 +18 -2
- 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 +74 -10
- package/src/events.ts +84 -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 +60 -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 +3 -3
- package/src/workspace-state.ts +8 -13
- package/dist/schemas.d.ts +0 -9909
- package/dist/schemas.d.ts.map +0 -1
- package/dist/schemas.js +0 -4288
- package/dist/schemas.js.map +0 -1
- package/src/schemas.ts +0 -10090
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// ci: pipeline runs on the workspace repos' github/gitlab remotes
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { AgentRunPickSchema } from "./agent.js";
|
|
4
|
+
// The daemon maps each workspace repo to the CI project behind its remote (a connected github/gitlab
|
|
5
|
+
// capability supplies the token), registers a webhook so completed pipelines dispatch `ci` listener
|
|
6
|
+
// automations instantly, and serves the Pipelines rail view from a webhook-freshened cache backfilled over the
|
|
7
|
+
// same REST clients. `host` names WHICH provider API serves a repo; the listener provider is always `ci`, one
|
|
8
|
+
// automation covers both hosts because the repo, not the vendor, is what a trigger narrows to.
|
|
9
|
+
|
|
10
|
+
export const CiHostSchema = z.enum(["github", "gitlab"]);
|
|
11
|
+
export type CiHost = z.infer<typeof CiHostSchema>;
|
|
12
|
+
// Terminal-or-not over both vendors' vocabularies: github's status+conclusion pair and gitlab's single status
|
|
13
|
+
// both collapse onto these five. `running` covers everything non-terminal (queued, manual, preparing …), the
|
|
14
|
+
// view only needs "still moving" vs the three ways it stopped.
|
|
15
|
+
export const PipelineStatusSchema = z.enum(["running", "success", "failed", "canceled", "skipped"]);
|
|
16
|
+
export type PipelineStatus = z.infer<typeof PipelineStatusSchema>;
|
|
17
|
+
export const PipelineRunSchema = z.object({
|
|
18
|
+
// The workspace repo dir (the panels `repo` convention), the join key back to the tree and to triggers.
|
|
19
|
+
repo: z.string().describe("Which workspace repository it belongs to."),
|
|
20
|
+
host: CiHostSchema.describe("Which forge is running it."),
|
|
21
|
+
// owner/name (github) or the full project path (gitlab).
|
|
22
|
+
project: z.string().describe("The project there, as that forge names it."),
|
|
23
|
+
// The vendor's numeric run/pipeline id, what rerun/cancel address.
|
|
24
|
+
runId: z.number().describe("The forge's own id for the run, which is what re-running and cancelling take."),
|
|
25
|
+
// The run's headline: github's display_title (the commit subject, or the PR title when a PR triggered it),
|
|
26
|
+
// gitlab's pipeline name or the head commit's subject. Absent ⇒ the view falls back to ref@sha.
|
|
27
|
+
title: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("The run's headline, usually the commit subject or the pull request's title. Absent means falling back to the branch and commit."),
|
|
31
|
+
// Who the vendor credits for the run, the actor who set it off, matching what both vendors' own UIs
|
|
32
|
+
// show. The avatar is a vendor-hosted URL; absent ⇒ the view draws the author's initials instead.
|
|
33
|
+
authorName: z.string().optional().describe("Who the forge credits for setting it off."),
|
|
34
|
+
authorAvatarUrl: z.string().optional().describe("Their picture, hosted by the forge. Absent means drawing their initials instead."),
|
|
35
|
+
// What set the run off, in the vendor's own vocabulary: gitlab's pipeline `source` (push, schedule,
|
|
36
|
+
// merge_request_event, web, api, trigger…) or github's `event` (push, pull_request, schedule,
|
|
37
|
+
// workflow_dispatch…). Left raw rather than flattened into a shared enum, the vendor's word is the
|
|
38
|
+
// precise one, and the view only calls it out when it isn't the everyday push.
|
|
39
|
+
trigger: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe(
|
|
43
|
+
"What set it off, in the forge's own word rather than flattened into a shared vocabulary, because the forge's word is the precise one.",
|
|
44
|
+
),
|
|
45
|
+
branch: z.string().describe("Which branch."),
|
|
46
|
+
sha: z.string().describe("Which commit."),
|
|
47
|
+
status: PipelineStatusSchema.describe(
|
|
48
|
+
"How it is going. Running covers everything still moving, since the only distinction that matters is that against the three ways it can stop.",
|
|
49
|
+
),
|
|
50
|
+
// The vendor's run page, the deep link out.
|
|
51
|
+
url: z.string().describe("Its page on the forge."),
|
|
52
|
+
createdAt: z.number().describe("When it started, in milliseconds."),
|
|
53
|
+
durationSeconds: z.number().optional().describe("How long it took."),
|
|
54
|
+
// Names of the failed jobs, fetched only for failed runs (one extra call), so a wake or a view names what broke.
|
|
55
|
+
failedJobs: z
|
|
56
|
+
.array(z.string())
|
|
57
|
+
.optional()
|
|
58
|
+
.describe(
|
|
59
|
+
"What broke, by name. Fetched only for failed runs, so that a notification or a screen can say what went wrong rather than just that something did.",
|
|
60
|
+
),
|
|
61
|
+
});
|
|
62
|
+
export type PipelineRun = z.infer<typeof PipelineRunSchema>;
|
|
63
|
+
/* One job inside a pipeline run. The view fetches these lazily (one extra call per visible run) so the list
|
|
64
|
+
* endpoint stays cheap. Both GitHub Actions jobs and GitLab CI jobs normalize onto these fields.
|
|
65
|
+
*
|
|
66
|
+
* HOW THE VIEW LEARNS THE RUN'S SHAPE, in descending order of truth:
|
|
67
|
+
* 1. `needs`, the dependencies the pipeline itself declares. The real graph, and the only one that can say
|
|
68
|
+
* a job waited on THIS one rather than on everything before it. Neither vendor's jobs API returns it, so
|
|
69
|
+
* it is read out of the pipeline definition (github: workflowGraph.ts) and is absent whenever that could
|
|
70
|
+
* not be resolved, a private workflow file, a deleted one, a name no declared job matches.
|
|
71
|
+
* 2. `stage`. GitLab's native sequential grouping, returned by its jobs API and used verbatim.
|
|
72
|
+
* 3. The timestamps, the last resort, and GitHub's before `needs` existed: overlapping runtimes ⇒ the jobs
|
|
73
|
+
* ran in parallel. Honest about when things happened, silent about what actually gated what.
|
|
74
|
+
* Both timestamps are epoch ms; absent while a job is still queued. */
|
|
75
|
+
export const PipelineJobSchema = z.object({
|
|
76
|
+
name: z.string().describe("The job's name."),
|
|
77
|
+
status: PipelineStatusSchema.describe("How it went."),
|
|
78
|
+
stage: z.string().optional().describe("Which stage it belongs to, where the pipeline groups its jobs that way."),
|
|
79
|
+
// Names of jobs IN THIS RUN that this one declared it waits on. Absent ⇒ nothing was resolved and the view
|
|
80
|
+
// must fall back; an empty array is the different, meaningful claim that this job is a root.
|
|
81
|
+
needs: z
|
|
82
|
+
.array(z.string())
|
|
83
|
+
.optional()
|
|
84
|
+
.describe(
|
|
85
|
+
"Which jobs in this run it declared it waits on: the real shape of the pipeline. Absent means nothing could be read, which is different from an empty list, which is the claim that it waits on nothing.",
|
|
86
|
+
),
|
|
87
|
+
startedAt: z.number().optional().describe("When it began, in milliseconds. Absent while it is queued."),
|
|
88
|
+
finishedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
89
|
+
durationSeconds: z.number().optional().describe("How long it took."),
|
|
90
|
+
// The job's page on its host, the shortest path from "this step failed" to the log that says why.
|
|
91
|
+
webUrl: z.string().optional().describe("Its page on the forge, which is the shortest path from this step failed to the log that says why."),
|
|
92
|
+
});
|
|
93
|
+
export type PipelineJob = z.infer<typeof PipelineJobSchema>;
|
|
94
|
+
export const CiJobsResponseSchema = z.object({
|
|
95
|
+
jobs: z.array(PipelineJobSchema).describe("The steps inside one run. Fetched separately from the run list, so that list stays cheap."),
|
|
96
|
+
});
|
|
97
|
+
export type CiJobsResponse = z.infer<typeof CiJobsResponseSchema>;
|
|
98
|
+
// One mapped repo's CI wiring state. `hookWarning` is the manual-setup story when webhook registration was
|
|
99
|
+
// refused (token scope, role) or impossible (no public URL): what happened plus the target URL + secret to
|
|
100
|
+
// paste into the repo's webhook settings, the git-access sshRegistrationWarning pattern.
|
|
101
|
+
export const CiRepoSchema = z.object({
|
|
102
|
+
repo: z.string().describe("Which workspace repository."),
|
|
103
|
+
host: CiHostSchema.describe("Which forge it lives on."),
|
|
104
|
+
project: z.string().describe("The project there."),
|
|
105
|
+
// The project's home page on its host.
|
|
106
|
+
url: z.string().describe("Its page on the forge."),
|
|
107
|
+
hookWarning: z
|
|
108
|
+
.string()
|
|
109
|
+
.optional()
|
|
110
|
+
.describe(
|
|
111
|
+
"Present when the sandbox could not register for instant notifications, with what happened and what to paste in by hand. Without them the sandbox polls instead, so this costs a couple of minutes' delay rather than the feature.",
|
|
112
|
+
),
|
|
113
|
+
});
|
|
114
|
+
export type CiRepo = z.infer<typeof CiRepoSchema>;
|
|
115
|
+
/* How often the daemon polls a repo whose webhook could NOT be registered (ci/poller.ts), the fallback that
|
|
116
|
+
* keeps a `ci` automation firing on a sandbox with no public URL or a token without hook scope.
|
|
117
|
+
*
|
|
118
|
+
* Here rather than beside the poller because both ends need the number: the daemon to run on it, and the
|
|
119
|
+
* automation editor to tell the owner what a `hookWarning` actually costs them. "Webhooks are off" is a fact
|
|
120
|
+
* about infrastructure; "this fires within two minutes instead of instantly" is the answer to the question
|
|
121
|
+
* they were really asking. */
|
|
122
|
+
export const CI_POLL_INTERVAL_MS = 2 * 60_000;
|
|
123
|
+
export const CiRunsResponseSchema = z.object({
|
|
124
|
+
repos: z.array(CiRepoSchema).describe("Which workspace repositories are wired to a forge, and how each one's notifications are set up."),
|
|
125
|
+
// Newest first, across all mapped repos.
|
|
126
|
+
runs: z.array(PipelineRunSchema).describe("Runs across all of them, newest first."),
|
|
127
|
+
// When the owner last opened the pipelines view. Rides the runs response so the rail can decide what is
|
|
128
|
+
// NEW without a second call, a breakage older than this has already been seen and must not badge again.
|
|
129
|
+
// Absent ⇒ never opened, so everything counts as unseen.
|
|
130
|
+
seenAt: z
|
|
131
|
+
.number()
|
|
132
|
+
.optional()
|
|
133
|
+
.describe(
|
|
134
|
+
"When this was last looked at, in milliseconds, so a badge can tell new breakages from ones already read without a second call. Absent means never, so everything counts as new.",
|
|
135
|
+
),
|
|
136
|
+
});
|
|
137
|
+
export type CiRunsResponse = z.infer<typeof CiRunsResponseSchema>;
|
|
138
|
+
// Stamping the view as read hands back the timestamp it wrote, so the client updates without a refetch.
|
|
139
|
+
export const CiSeenResponseSchema = z.object({
|
|
140
|
+
seenAt: z.number().describe("The timestamp that was written, handed back so a caller can update without asking again."),
|
|
141
|
+
});
|
|
142
|
+
export type CiSeenResponse = z.infer<typeof CiSeenResponseSchema>;
|
|
143
|
+
// rerun/cancel/fix address a run by repo + vendor id; the daemon re-resolves repo → project + token per call,
|
|
144
|
+
// so a stale card can't act on a project the workspace no longer maps to.
|
|
145
|
+
export const CiRunParamSchema = z.object({
|
|
146
|
+
repo: z
|
|
147
|
+
.string()
|
|
148
|
+
.describe(
|
|
149
|
+
"Which workspace repository. The project behind it is resolved fresh each call, so a stale screen cannot act on one the workspace no longer maps to.",
|
|
150
|
+
),
|
|
151
|
+
runId: z.number().describe("Which run, by the forge's own id."),
|
|
152
|
+
});
|
|
153
|
+
export type CiRunParam = z.infer<typeof CiRunParamSchema>;
|
|
154
|
+
// Fixing takes one thing the vendor proxies do not: which model to open the session on, when the user reached
|
|
155
|
+
// for the caret beside the button rather than pressing it (AgentRunPickSchema). Absent is the ordinary path.
|
|
156
|
+
export const CiFixParamSchema = CiRunParamSchema.extend({
|
|
157
|
+
pick: AgentRunPickSchema.describe(
|
|
158
|
+
"Which model to open the conversation on, when somebody chose one. Leave it out for the sandbox's own choice, which is the ordinary path.",
|
|
159
|
+
),
|
|
160
|
+
});
|
|
161
|
+
export type CiFixParam = z.infer<typeof CiFixParamSchema>;
|
|
162
|
+
// The fix route opens an isolated conversation (fleet card + chat tab) seeded with the failure context.
|
|
163
|
+
export const CiFixResponseSchema = z.object({
|
|
164
|
+
conversationId: z.string().describe("The conversation that was opened, already holding the failure. Open it to watch, or attach to its turn."),
|
|
165
|
+
});
|
|
166
|
+
export type CiFixResponse = z.infer<typeof CiFixResponseSchema>;
|
|
167
|
+
/* ---- the pre-push check: the workspace's own answer to "would this push go red" ----
|
|
168
|
+
*
|
|
169
|
+
* WHERE THIS SITS. A fleet of 5-20 agents lands work into the main tree, the user reviews and commits it by
|
|
170
|
+
* parts, pushes, and CI answers minutes later. The check front-runs that answer at the push itself, the last
|
|
171
|
+
* moment before the work leaves the machine, and the first moment at which what will be pushed is finally
|
|
172
|
+
* settled.
|
|
173
|
+
*
|
|
174
|
+
* WHY THE PUSH AND NOT THE LAND, which is where this used to run. A post-land verdict is about a tree that
|
|
175
|
+
* keeps moving: the user commits by parts, another agent lands, an edit arrives, so the verdict spent its life
|
|
176
|
+
* either stale or being recomputed, and needed a content fingerprint, a staleness rule and a badge to say which.
|
|
177
|
+
* All of that machinery existed to answer a question the push asks for free, because at the push there is
|
|
178
|
+
* exactly one artifact and the user is standing in front of it waiting.
|
|
179
|
+
*
|
|
180
|
+
* SO THERE IS NO STORED VERDICT AND NOTHING IS POLLED AT REST. A run exists while it runs, reports to the
|
|
181
|
+
* dialog that started it, and is gone. Nothing survives a daemon restart because nothing needs to: the next
|
|
182
|
+
* push asks again. */
|
|
183
|
+
|
|
184
|
+
/* Where a run is.
|
|
185
|
+
*
|
|
186
|
+
* idle , nothing has run in this daemon's life, or the last run was cleared.
|
|
187
|
+
* running , the check is live. Its output is the terminal's (`session`), not this object's.
|
|
188
|
+
* passed , exited 0. The push goes.
|
|
189
|
+
* failed , exited non-zero, or was killed by prepushTimeoutMs (`timedOut`). The state a fix answers.
|
|
190
|
+
* error , the check could not run at all: the command was not spawnable. NOT a fix-able failure, because
|
|
191
|
+
* there is nothing wrong with the code, the command is misconfigured, and saying "tests failed"
|
|
192
|
+
* would send an agent hunting a bug that isn't there.
|
|
193
|
+
* cancelled, the user stopped the run.
|
|
194
|
+
*/
|
|
195
|
+
export const PrepushStatusSchema = z.enum(["idle", "running", "passed", "failed", "error", "cancelled"]);
|
|
196
|
+
export type PrepushStatus = z.infer<typeof PrepushStatusSchema>;
|
|
197
|
+
export const PrepushRunSchema = z.object({
|
|
198
|
+
status: PrepushStatusSchema.describe(
|
|
199
|
+
"Where the run is. Failed and error are deliberately different: failed means the code is wrong, error means the command could not be run at all, and calling the second one a test failure would send an agent hunting a bug that is not there.",
|
|
200
|
+
),
|
|
201
|
+
// The command this run executed, echoed rather than read back from settings: a result read after the
|
|
202
|
+
// setting changed still has to say what produced it.
|
|
203
|
+
command: z
|
|
204
|
+
.string()
|
|
205
|
+
.describe(
|
|
206
|
+
"What actually ran, echoed here rather than read back from the settings, so a result looked at after the setting changed still says what produced it.",
|
|
207
|
+
),
|
|
208
|
+
startedAt: z.number().optional().describe("When it began, in milliseconds."),
|
|
209
|
+
finishedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
210
|
+
exitCode: z.number().optional().describe("How the command exited."),
|
|
211
|
+
timedOut: z.boolean().optional().describe("It was killed for taking too long rather than finishing."),
|
|
212
|
+
/* The tmux session the suite runs in, for the browser to open the terminals panel on, the check is a
|
|
213
|
+
* visible terminal like every other shell command the daemon runs on a click (terminal/terminal-run.ts), so
|
|
214
|
+
* WATCHING it is not this object's job and never was. Absent where the sandbox has no tmux wrapper (local
|
|
215
|
+
* dev): the runner falls back to an invisible shell, and a name nothing can attach to would send the browser
|
|
216
|
+
* after a tab that is never going to be listed. */
|
|
217
|
+
session: z
|
|
218
|
+
.string()
|
|
219
|
+
.optional()
|
|
220
|
+
.describe(
|
|
221
|
+
"The terminal it runs in, which is where to watch it. Absent where the sandbox has no terminals, in which case there is nothing to attach to.",
|
|
222
|
+
),
|
|
223
|
+
/* What the fix proposal quotes, and its only reader, tail-capped (PREPUSH_OUTPUT_BYTES) so a prompt seeded
|
|
224
|
+
* from a red run stays about fixing rather than scrolling. The TAIL, not the head: a suite's verdict and its
|
|
225
|
+
* failure summary are at the end. PLAIN TEXT, not what the terminal received: the suite's colour codes and
|
|
226
|
+
* redrawn progress lines are resolved away (terminal/plain-text.ts) before the cap, so a quoted tail reads
|
|
227
|
+
* as a failure instead of as litter. Empty while the run is going, and for a run that was killed: the pane
|
|
228
|
+
* (and its log) is where the whole of it lives. */
|
|
229
|
+
output: z
|
|
230
|
+
.string()
|
|
231
|
+
.describe(
|
|
232
|
+
"The end of what it printed, as plain text with the colour codes and redrawn progress lines resolved away. The end rather than the beginning, because a suite's verdict is at the end. Empty while it runs, and for one that was killed.",
|
|
233
|
+
),
|
|
234
|
+
});
|
|
235
|
+
export type PrepushRun = z.infer<typeof PrepushRunSchema>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// The GATE signal: whether the provider is letting turns through right now, and, when it is refusing, which
|
|
3
|
+
// window is binding and when it lifts. This is the SDK's rate_limit_event, mapped one-to-one, and it is only
|
|
4
|
+
// ever about the CURRENT moment. It is deliberately NOT the thing the headroom displays read: the event names a
|
|
5
|
+
// single window (whichever the CLI considered binding), which is how "weekly 1%" ended up standing in for an
|
|
6
|
+
// account that was really at 98% on another weekly pool.
|
|
7
|
+
export const RateLimitInfoSchema = z.object({
|
|
8
|
+
status: z.enum(["allowed", "allowed_warning", "rejected"]),
|
|
9
|
+
resetsAt: z.number().optional(), // epoch seconds
|
|
10
|
+
rateLimitType: z.string().optional(), // 'five_hour' | 'seven_day' | 'seven_day_opus' | ...
|
|
11
|
+
utilization: z.number().optional(), // 0-100, how much of the window is used
|
|
12
|
+
});
|
|
13
|
+
export type RateLimitInfo = z.infer<typeof RateLimitInfoSchema>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// codebase health: one repository's structure and risk, in numbers
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { WorkspaceSearchFreshnessSchema } from "./workspace-search.js";
|
|
4
|
+
// The repo-level companion to the management panel and the git-history graph: what the same resident engine's
|
|
5
|
+
// `hotspots` (churn × complexity) and `map` (PageRank over the import graph) verbs rank, as figures a panel can
|
|
6
|
+
// plot instead of lines a terminal prints.
|
|
7
|
+
//
|
|
8
|
+
// Every field is a COUNT that can be recounted in the files themselves, commits, branch points, exported
|
|
9
|
+
// symbols. Deliberately no composite "maintainability grade": those aren't comparable across projects and can't
|
|
10
|
+
// be checked, and a repo-health surface that launders counts into a letter is worse than none.
|
|
11
|
+
// How many hotspot files and key modules a report carries when the caller names no limit. A leaderboard, not an
|
|
12
|
+
// inventory: past a screenful the ranking stops being the point, and the reader should be reading the files.
|
|
13
|
+
export const HEALTH_LIMIT = 20;
|
|
14
|
+
export const WorkspaceHealthQuerySchema = z.object({
|
|
15
|
+
// "root" (the /work repo) or a nested repo's root-relative dir, the same {repo} ids the git routes take.
|
|
16
|
+
repo: z.string().min(1).describe("Which repository, using the same ids the git routes take."),
|
|
17
|
+
// Churn window (2d, 12h, 1w, 3m). Absent = all of history, which is what a hotspot ranking wants by default.
|
|
18
|
+
since: z
|
|
19
|
+
.string()
|
|
20
|
+
.max(16)
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("How far back to count changes, written as a span such as 2d, 12h, 1w or 3m. Leave it out for all of history."),
|
|
23
|
+
limit: z.coerce
|
|
24
|
+
.number()
|
|
25
|
+
.int()
|
|
26
|
+
.positive()
|
|
27
|
+
.max(200)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("How many files and modules to rank. A leaderboard rather than an inventory: past a screenful the ranking stops being the point."),
|
|
30
|
+
});
|
|
31
|
+
// One file that is BOTH churning and tangled. `score` is the product the ranking sorts by, carried explicitly
|
|
32
|
+
// so the panel plots the number it ranks by rather than recomputing it.
|
|
33
|
+
export const WorkspaceHotspotSchema = z.object({
|
|
34
|
+
path: z.string(),
|
|
35
|
+
commits: z.number(),
|
|
36
|
+
adds: z.number(),
|
|
37
|
+
dels: z.number(),
|
|
38
|
+
complexity: z.number(),
|
|
39
|
+
score: z.number(),
|
|
40
|
+
// Epoch ms of the latest commit touching the file, within the window.
|
|
41
|
+
latestMs: z.number(),
|
|
42
|
+
});
|
|
43
|
+
export type WorkspaceHotspot = z.infer<typeof WorkspaceHotspotSchema>;
|
|
44
|
+
// A file of the import graph's ranked skeleton, order IS the rank, so no rank number rides along.
|
|
45
|
+
export const WorkspaceKeyModuleSchema = z.object({ path: z.string(), exports: z.number() });
|
|
46
|
+
export type WorkspaceKeyModule = z.infer<typeof WorkspaceKeyModuleSchema>;
|
|
47
|
+
export const WorkspaceHealthSchema = z.object({
|
|
48
|
+
repo: z.string().describe("Which repository this describes."),
|
|
49
|
+
totals: z
|
|
50
|
+
.object({
|
|
51
|
+
files: z.number().describe("Files counted."),
|
|
52
|
+
symbols: z.number().describe("Named things they export."),
|
|
53
|
+
complexity: z.number().describe("Branch points across all of them added up."),
|
|
54
|
+
hotspots: z.number().describe("How many files qualify as hotspots at all. The list below is capped; this is not."),
|
|
55
|
+
})
|
|
56
|
+
.describe(
|
|
57
|
+
"Counts anybody could recount in the files themselves. Deliberately no single maintainability grade: those cannot be checked and are not comparable between projects.",
|
|
58
|
+
),
|
|
59
|
+
hotspots: z.array(WorkspaceHotspotSchema).describe("Files that change often and are complicated at the same time, worst first."),
|
|
60
|
+
modules: z.array(WorkspaceKeyModuleSchema).describe("The parts of the codebase the rest of it leans on most."),
|
|
61
|
+
// Same index-freshness signal the search route reports: a panel drawn off a half-built index says so.
|
|
62
|
+
freshness: WorkspaceSearchFreshnessSchema.describe("Whether the index these numbers were read from is up to date."),
|
|
63
|
+
});
|
|
64
|
+
export type WorkspaceHealth = z.infer<typeof WorkspaceHealthSchema>;
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// computers: what ONE of the user's own machines is running
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { HostFactsSchema } from "./hosts.js";
|
|
4
|
+
/* The other end of desktop sync, stated as a fact instead of a claim.
|
|
5
|
+
*
|
|
6
|
+
* Everything here already existed, as the machine agent's printed status on a terminal nobody running the desktop app
|
|
7
|
+
* has open, and as `docker ps` rows only the desktop app could see. Three surfaces each held a third of it: the
|
|
8
|
+
* desktop app knew the containers and nothing about sync, the Desktop sync card knew an enrollment record and
|
|
9
|
+
* printed the status command for the rest, and the folder a machine syncs into was known to neither
|
|
10
|
+
* (SYNC_DIR is local agent state; the daemon is never told it). This is that one shape, so the same report can
|
|
11
|
+
* be produced by the agent, read by the daemon, and rendered by one component in both apps.
|
|
12
|
+
*
|
|
13
|
+
* The producer is `intentic-machine status --json` in every carrier (this report rides as its `sync` half), the desktop app spawns it, the mirror watcher
|
|
14
|
+
* posts it, a `host` capability runs it over run_command. One producer is what keeps the three from drifting,
|
|
15
|
+
* the same argument as the desktop app spawning connect.sh rather than reimplementing it.
|
|
16
|
+
*
|
|
17
|
+
* WHO FILLS WHAT is the disclosure rule, made structural. The agent reports only what it uniquely knows, its
|
|
18
|
+
* own pairings, folders, ports, watcher, and NEVER `sandboxes`: enumerating a machine's other containers to one
|
|
19
|
+
* of them is the leak this design exists to avoid, and a sync agent has no business doing it anyway. The docker
|
|
20
|
+
* half is supplied by whoever is READING (the desktop app from its own `docker ps`, the daemon from a
|
|
21
|
+
* `host`-capability one), which is also the only side that has a reason to be trusted with it.
|
|
22
|
+
*
|
|
23
|
+
* What remains is scoping: a report reaching a sandbox carries that sandbox's pairing, not its siblings', and a
|
|
24
|
+
* `mirror` enrollment, a collaborator's own laptop, drops `localDir` with it. So a member who mirrors one
|
|
25
|
+
* dev-server port does not hand the sandbox's owner a map of their machine. */
|
|
26
|
+
|
|
27
|
+
// One sandbox container on the machine, the docker half, filled in by the reader, never by the sync agent.
|
|
28
|
+
export const MachineSandboxSchema = z.object({
|
|
29
|
+
slug: z.string(),
|
|
30
|
+
container: z.string(),
|
|
31
|
+
// The display name, when the machine has one recorded. Docker knows only the container name.
|
|
32
|
+
name: z.string().optional(),
|
|
33
|
+
running: z.boolean(),
|
|
34
|
+
image: z.string(),
|
|
35
|
+
// Absent when the sandbox has no cloudflared sidecar AT ALL (reached over the user's own proxy), which is
|
|
36
|
+
// not the same fact as a sidecar that is down, and must not render as one.
|
|
37
|
+
tunnelRunning: z.boolean().optional(),
|
|
38
|
+
});
|
|
39
|
+
export type MachineSandbox = z.infer<typeof MachineSandboxSchema>;
|
|
40
|
+
/* ONE OPERATION ON ONE SANDBOX ON ONE MACHINE, the Computers view's buttons, and the only thing that changes a
|
|
41
|
+
* machine's fleet from a browser.
|
|
42
|
+
*
|
|
43
|
+
* All nine ops travel one route because they are one decision to the person clicking, however differently they
|
|
44
|
+
* behave underneath: three are a docker call that returns in a second, four run the `ic` flow for minutes, one
|
|
45
|
+
* deletes, and one only reads. Splitting them by duration would put the same button on two doors and give the
|
|
46
|
+
* view two shapes to render. So every op answers as a STREAM of lines ending in a result, the fast ones simply
|
|
47
|
+
* have little to say, and `logs` is the case where the lines ARE the answer.
|
|
48
|
+
*
|
|
49
|
+
* `prepare` is the one that changes nothing on purpose: it downloads and builds the next update and stops
|
|
50
|
+
* there, leaving the container running the image it was already running. It is what turns `update` from a wait
|
|
51
|
+
* of minutes into a restart of seconds, and it is safe to offer at any moment for exactly that reason.
|
|
52
|
+
*
|
|
53
|
+
* `logs` is here rather than on a route of its own for the same reason the rest share it: it is a button in the
|
|
54
|
+
* same row as the others, on a container that may be too broken to answer any other way, and the stream shape
|
|
55
|
+
* already carries "many lines, then an outcome" exactly as a log tail wants to arrive.
|
|
56
|
+
*
|
|
57
|
+
* The machine enforces which of them it will do: `sandboxes` covers everything but removal, which takes its own
|
|
58
|
+
* switch, and a refusal comes back as the machine's own sentence naming the control to flip. */
|
|
59
|
+
/* `runner-up` / `runner-remove` are the same door for a container that belongs to THIS SANDBOX rather than to
|
|
60
|
+
* a person: a runner (runners/, docs/remote-runners-plan.md at the workspace root). They ride here because to
|
|
61
|
+
* the machine they are the same act it already does, run and remove a sandbox container, and to the person
|
|
62
|
+
* clicking they are the same row of buttons. Both take the `sandboxes` switch and neither takes the removal
|
|
63
|
+
* one: a runner holds no workspace of its own, only a mirror of the parent's git, so removing it destroys
|
|
64
|
+
* nothing the parent does not still have. */
|
|
65
|
+
export const MachineSandboxOpSchema = z.enum([
|
|
66
|
+
"start",
|
|
67
|
+
"stop",
|
|
68
|
+
"restart",
|
|
69
|
+
"prepare",
|
|
70
|
+
"update",
|
|
71
|
+
"rebuild",
|
|
72
|
+
"rollback",
|
|
73
|
+
"remove",
|
|
74
|
+
"logs",
|
|
75
|
+
"runner-up",
|
|
76
|
+
"runner-remove",
|
|
77
|
+
]);
|
|
78
|
+
export type MachineSandboxOp = z.infer<typeof MachineSandboxOpSchema>;
|
|
79
|
+
export const MachineSandboxFlowSchema = z.object({
|
|
80
|
+
op: MachineSandboxOpSchema,
|
|
81
|
+
// Which sandbox, or, for the two runner ops, which RUNNER: the name it is known by at both ends, the
|
|
82
|
+
// parent's `/system/runners` list and the machine's `ic runner list`.
|
|
83
|
+
slug: z.string().min(1),
|
|
84
|
+
// The approved overlay's sha256, required by `rebuild` and meaningless to the rest. It is the trust anchor:
|
|
85
|
+
// only content that still hashes to what the owner reviewed is ever built.
|
|
86
|
+
hash: z.string().optional(),
|
|
87
|
+
/* `runner-up` only, and both are filled in by the DAEMON, never by the caller: where the runner dials
|
|
88
|
+
* (this sandbox's public URL) and the single-use pairing it redeems there. The browser asks for a runner
|
|
89
|
+
* on a machine; it never holds the credential that makes one, which is what keeps a pairing out of every
|
|
90
|
+
* surface between here and that machine. */
|
|
91
|
+
parentUrl: z.string().optional(),
|
|
92
|
+
pair: z.string().optional().meta({ secret: true }),
|
|
93
|
+
/* `runner-up` only, daemon-filled like the pair: the parent's SHAPE, riding to the machine so the runner
|
|
94
|
+
* starts as this sandbox's twin instead of a bare base image.
|
|
95
|
+
*
|
|
96
|
+
* `definition` is a settings-only sandbox.toml the container boots with as SANDBOX_DEFINITION_SEED (the
|
|
97
|
+
* fleet door in @intentic/sandbox-run); the daemon scopes it before sending, capabilities and secret
|
|
98
|
+
* names deliberately never ride to a runner. `overlay`/`overlayHash` are the parent's APPROVED composed
|
|
99
|
+
* overlay, byte-exact with its sha256: the parent's owner already approved those bytes, so `ic runner up`
|
|
100
|
+
* re-checks the hash and builds them at creation — approval by provenance, the same byte-exact check
|
|
101
|
+
* `ic sandbox rebuild` runs, where a definition handed to a STRANGER must park at an approval gate. */
|
|
102
|
+
definition: z.string().optional(),
|
|
103
|
+
overlay: z.string().optional(),
|
|
104
|
+
overlayHash: z.string().optional(),
|
|
105
|
+
});
|
|
106
|
+
export type MachineSandboxFlow = z.infer<typeof MachineSandboxFlowSchema>;
|
|
107
|
+
// The same input plus which machine it is for, the browser's half, since the daemon reaches the machine by id.
|
|
108
|
+
export const MachineSandboxFlowInputSchema = MachineSandboxFlowSchema.extend({ id: z.string().min(1) });
|
|
109
|
+
export type MachineSandboxFlowInput = z.infer<typeof MachineSandboxFlowInputSchema>;
|
|
110
|
+
/* What a running operation says, in the one line shape every streamed flow in this product already uses
|
|
111
|
+
* (IntenticLineSchema, which the browser's reader parses): `line` as the machine prints it, then exactly one
|
|
112
|
+
* terminal frame, `result` when it worked, `error` when it did not, carrying the machine's own words either
|
|
113
|
+
* way rather than a code this side invented. */
|
|
114
|
+
export const MachineFlowLineSchema = z.discriminatedUnion("kind", [
|
|
115
|
+
z.object({ kind: z.literal("line"), text: z.string() }),
|
|
116
|
+
z.object({ kind: z.literal("result"), message: z.string() }),
|
|
117
|
+
z.object({ kind: z.literal("error"), message: z.string() }),
|
|
118
|
+
]);
|
|
119
|
+
export type MachineFlowLine = z.infer<typeof MachineFlowLineSchema>;
|
|
120
|
+
// One paired sandbox as the local agent holds it. `localDir` is the answer to the question the Desktop sync card
|
|
121
|
+
// has never been able to answer: which folder on that computer this sandbox's /work actually is.
|
|
122
|
+
export const MachinePairingSchema = z.object({
|
|
123
|
+
sandboxId: z.string(),
|
|
124
|
+
mode: z.enum(["sync", "mirror"]),
|
|
125
|
+
// Set only for mode "sync", and only for the sandbox being reported to, see the redaction note above.
|
|
126
|
+
localDir: z.string().optional(),
|
|
127
|
+
// Mutagen's own word for what the session is doing ("watching", "scanning", "transitioning", "halted-…").
|
|
128
|
+
// Carried verbatim rather than mapped to a traffic light: the halted states name their own cause, and a UI
|
|
129
|
+
// that reduces them to "problem" sends the user back to the terminal this report exists to replace.
|
|
130
|
+
mutagenStatus: z.string().optional(),
|
|
131
|
+
// Conflicts Mutagen is holding rather than clobbering (the sync mode is two-way-SAFE). Nothing else in the
|
|
132
|
+
// product surfaces these, so a file edited on both ends stays stuck until someone runs the CLI.
|
|
133
|
+
conflicts: z.number().int().nonnegative().optional(),
|
|
134
|
+
paused: z.boolean().optional(),
|
|
135
|
+
/* The SECOND session's word, the one-way mirror carrying the sandbox's state dir down (sync's backupSpec).
|
|
136
|
+
* Reported separately rather than folded into the status above, because the two fail independently and mean
|
|
137
|
+
* different things: the first going quiet stops the owner's edits moving, the second going quiet stops their
|
|
138
|
+
* personas, skills, automations, drafts and transcripts from surviving the sandbox. A backup that is not
|
|
139
|
+
* running is only dangerous while nobody knows, so it gets its own word on the line. */
|
|
140
|
+
backupStatus: z.string().optional(),
|
|
141
|
+
});
|
|
142
|
+
export type MachinePairing = z.infer<typeof MachinePairingSchema>;
|
|
143
|
+
/* One sandbox port and what became of it on this machine's localhost. The rows that did NOT make it are the
|
|
144
|
+
* reason this carries a state rather than being a list of live forwards: two sandboxes on one computer routinely
|
|
145
|
+
* serve the same dev-server port and only one can own localhost:6480, so the loser's port is simply missing from
|
|
146
|
+
* localhost with nothing anywhere saying why. Today that fact exists only as a line in mirror.log. */
|
|
147
|
+
export const MachinePortStateSchema = z.enum([
|
|
148
|
+
// Forwarded: the sandbox's listener answers on this machine's localhost at the same number.
|
|
149
|
+
"mirrored",
|
|
150
|
+
// Another PAIRED SANDBOX got there first (first paired wins), `heldBy` names it, because "busy on this
|
|
151
|
+
// machine" sends people hunting for a process that does not exist.
|
|
152
|
+
"held-by-sandbox",
|
|
153
|
+
// Something else on this computer already binds the port, a local dev server, another tool. Not ours to
|
|
154
|
+
// name, and not ours to take.
|
|
155
|
+
"busy",
|
|
156
|
+
]);
|
|
157
|
+
export const MachinePortSchema = z.object({
|
|
158
|
+
port: z.number().int().min(1).max(65535),
|
|
159
|
+
host: z.enum(["127.0.0.1", "::1"]),
|
|
160
|
+
// The sandbox serving the port, whose /ports listed it, not whoever ended up holding the local bind.
|
|
161
|
+
sandboxId: z.string(),
|
|
162
|
+
state: MachinePortStateSchema,
|
|
163
|
+
// Set only for "held-by-sandbox": the sandbox id that owns the local bind instead.
|
|
164
|
+
heldBy: z.string().optional(),
|
|
165
|
+
// What is listening on the sandbox side ("node …/vite"), for a row the user has to recognise to act on.
|
|
166
|
+
command: z.string().optional(),
|
|
167
|
+
});
|
|
168
|
+
export type MachinePort = z.infer<typeof MachinePortSchema>;
|
|
169
|
+
/* The resident watcher's liveness. This is the field that decides whether everything ELSE in the report is still
|
|
170
|
+
* true: a healthy session list under a dead watcher means new dev-server ports stop appearing on localhost and
|
|
171
|
+
* commits stop arriving in the local clones, while every other row keeps reading exactly as it did. */
|
|
172
|
+
export const MachineWatcherSchema = z.object({
|
|
173
|
+
running: z.boolean(),
|
|
174
|
+
pid: z.number().int().optional(),
|
|
175
|
+
/* When the watcher last FINISHED a pass, the field that makes `running` mean something. The agent holds its
|
|
176
|
+
* SSH transport listeners on its own event loop, so a failure that escapes the loop leaves a process that is
|
|
177
|
+
* alive and a loop that is gone: pid present, unit "active", mirroring and the git bridge stopped. Absent
|
|
178
|
+
* means the agent has not reported one (too old to stamp, or its first pass has not landed), which is not
|
|
179
|
+
* the same as stalled, and readers must not treat it as either state. */
|
|
180
|
+
lastTickAt: z.number().optional(),
|
|
181
|
+
});
|
|
182
|
+
export type MachineWatcher = z.infer<typeof MachineWatcherSchema>;
|
|
183
|
+
/* How long a watcher may go without finishing a pass before "running" stops being the honest word for it. Its
|
|
184
|
+
* loop polls every 5s and its slowest step is bounded by two 10s network timeouts per pairing, so a minute is
|
|
185
|
+
* several passes of slack, the same yardstick the Computers view already ages a whole report by.
|
|
186
|
+
*
|
|
187
|
+
* The rule lives HERE, next to the field, because the terminal and the browser both answer this question and a
|
|
188
|
+
* machine that is "running" in one and "stalled" in the other is worse than either answer alone. */
|
|
189
|
+
export const WATCHER_STALL_AFTER_MS = 60_000;
|
|
190
|
+
export const watcherStalled = (watcher: MachineWatcher, now: number): boolean =>
|
|
191
|
+
watcher.running && watcher.lastTickAt !== undefined && now - watcher.lastTickAt > WATCHER_STALL_AFTER_MS;
|
|
192
|
+
export const MachineReportSchema = z.object({
|
|
193
|
+
/* The OS hostname, and the JOIN KEY. A machine can arrive here two ways at once, volunteered by its sync
|
|
194
|
+
* agent, and read through its `host` capability, and those two know it by different names (the enrolled
|
|
195
|
+
* key's comment vs. the capability id the user typed). The hostname is the one thing both can state about
|
|
196
|
+
* the same box, so it is what dedupes them into a single row. */
|
|
197
|
+
hostname: z.string(),
|
|
198
|
+
os: z.string(),
|
|
199
|
+
// Which of this machine's agents are installed, and at what version, a machine running an old build is
|
|
200
|
+
// visible rather than mysteriously lacking a field. Same argument as HostSummary.version. `host` is filled
|
|
201
|
+
// by the daemon at merge time (it already knows it from the socket), not by the sync agent, which would have
|
|
202
|
+
// to go reading another agent's config to guess at it.
|
|
203
|
+
agents: z.object({ sync: z.string().optional(), host: z.string().optional() }),
|
|
204
|
+
// Filled by the READER, never the agent (see above). Empty is the resting state: no Docker on the machine,
|
|
205
|
+
// or nothing has looked. Neither is an error, and neither means "no sandboxes exist".
|
|
206
|
+
sandboxes: z.array(MachineSandboxSchema),
|
|
207
|
+
pairings: z.array(MachinePairingSchema),
|
|
208
|
+
ports: z.array(MachinePortSchema),
|
|
209
|
+
watcher: MachineWatcherSchema,
|
|
210
|
+
// When the machine took this reading. NOT when the daemon received it. A report is a snapshot from a box
|
|
211
|
+
// that may since have gone to sleep, and the UI ages it against this rather than presenting it as now.
|
|
212
|
+
capturedAt: z.number(),
|
|
213
|
+
});
|
|
214
|
+
export type MachineReport = z.infer<typeof MachineReportSchema>;
|
|
215
|
+
// Why a computer that is plainly THERE has no report to show. Each is a different errand for the reader, which is
|
|
216
|
+
// the whole reason they are not collapsed into one "unavailable".
|
|
217
|
+
export const ComputerGapSchema = z.enum([
|
|
218
|
+
// A host capability that is enrolled but has no socket right now. Laptops sleep; this is not a fault.
|
|
219
|
+
"offline",
|
|
220
|
+
// Connected, but "Run commands" is switched off on its capability card, so the daemon may not ask it
|
|
221
|
+
// anything. The one gap the user can close in a single click, and the UI says which switch.
|
|
222
|
+
"scope-off",
|
|
223
|
+
// Reachable, asked, but has no `intentic-machine` on it, so nothing knows about folders or mirrored ports there.
|
|
224
|
+
"no-agent",
|
|
225
|
+
// A sync-enrolled machine that has not posted a report yet: either it just enrolled, or its agent predates
|
|
226
|
+
// machine reports. Distinct from "no-agent" because the agent IS there and the folders ARE syncing.
|
|
227
|
+
"unreported",
|
|
228
|
+
]);
|
|
229
|
+
export type ComputerGap = z.infer<typeof ComputerGapSchema>;
|
|
230
|
+
/* ONE COMPUTER, however the sandbox happens to be able to see it, and it may be both ways at once.
|
|
231
|
+
*
|
|
232
|
+
* A machine reaches a sandbox through two independent doors: a desktop-sync enrollment (which volunteers its own
|
|
233
|
+
* report) and a `host` capability (which the daemon can ask). They know the same box by different names, the
|
|
234
|
+
* enrolled ssh key's comment vs. the capability id the user typed, so the two are reconciled on the `hostname`
|
|
235
|
+
* their reports agree on, and left as separate rows when there is nothing to reconcile them by. Guessing that two
|
|
236
|
+
* differently-named machines are the same one would merge two people's laptops on a shared sandbox. */
|
|
237
|
+
export const ComputerSchema = z.object({
|
|
238
|
+
// Stable row key: the reported hostname when either door produced one, else the name that door knows it by.
|
|
239
|
+
key: z.string(),
|
|
240
|
+
// What to call it on screen, the user's own name for the machine wherever one exists.
|
|
241
|
+
label: z.string(),
|
|
242
|
+
// Whether a desktop-sync enrollment exists for this machine (it syncs files and/or mirrors ports).
|
|
243
|
+
syncEnrolled: z.boolean(),
|
|
244
|
+
// The host capability's id, when this machine is also a connected computer. Absent otherwise.
|
|
245
|
+
hostId: z.string().optional(),
|
|
246
|
+
// Host-capability liveness. Absent when there is no host capability, which is NOT the same as offline.
|
|
247
|
+
online: z.boolean().optional(),
|
|
248
|
+
/* WHAT THE COMPUTER IS, as distinct from how it is reachable, the half a row used to leave out entirely,
|
|
249
|
+
* so a Windows laptop and a Linux desktop were two identical lines of text with different names on them.
|
|
250
|
+
*
|
|
251
|
+
* It is carried BESIDE the report rather than inside it because the rows that need it most are the ones with
|
|
252
|
+
* no report: a connected computer with no sync agent, or one that is asleep, still knows its own OS. Nothing
|
|
253
|
+
* here depends on an agent being installed, and the daemon has held all of it since the machine connected.
|
|
254
|
+
*
|
|
255
|
+
* `platform` is the slug this side classifies the machine by, the host capability's own card ("windows",
|
|
256
|
+
* "linux"), or the platform token a sync report carries, normalised to the same words. `facts` is the
|
|
257
|
+
* machine's connect-time description of ITSELF, which is what says which Windows and which shell. */
|
|
258
|
+
platform: z.string().optional(),
|
|
259
|
+
facts: HostFactsSchema.optional(),
|
|
260
|
+
// The host agent's version and when the machine last held a socket, how a connected computer AGES. An old
|
|
261
|
+
// agent explains a row that lacks something newer machines have, and "last seen" is the one honest thing an
|
|
262
|
+
// offline row can still say about itself.
|
|
263
|
+
hostAgent: z.string().optional(),
|
|
264
|
+
lastSeen: z.number().optional(),
|
|
265
|
+
report: MachineReportSchema.optional(),
|
|
266
|
+
gap: ComputerGapSchema.optional(),
|
|
267
|
+
});
|
|
268
|
+
export type Computer = z.infer<typeof ComputerSchema>;
|
|
269
|
+
export const ComputersListSchema = z.object({ computers: z.array(ComputerSchema) });
|
|
270
|
+
// GET /system/sync, the enrollment state the Desktop sync card is built on, plus what each enrolled machine has
|
|
271
|
+
// said about itself. `machines` is optional because a daemon predating machine reports omits it, and an SPA is
|
|
272
|
+
// routinely newer than the daemon it is pointed at during a rolling update.
|
|
273
|
+
export const SyncStatusSchema = z.object({
|
|
274
|
+
enrolled: z.boolean(),
|
|
275
|
+
/* Whether this sandbox can do desktop sync at all. It used to be the SSH hostname the laptop would dial, and
|
|
276
|
+
* its absence meant "this sandbox's reachability can't carry SSH", true of every sandbox on the platform's
|
|
277
|
+
* own fabric, which is what made sync fail on the default path. The transport rides the daemon's own HTTPS
|
|
278
|
+
* surface now, so a sandbox that can answer this read can also sync. Kept as a field rather than assumed,
|
|
279
|
+
* because the card branches on it and a daemon too old to say is one that should not be offered sync. */
|
|
280
|
+
available: z.boolean().optional(),
|
|
281
|
+
// The single machine holding file sync, and when its heartbeat last landed.
|
|
282
|
+
syncingFrom: z.string().optional(),
|
|
283
|
+
syncSeenAt: z.number().optional(),
|
|
284
|
+
mirroredBy: z.array(z.string()).optional(),
|
|
285
|
+
machines: z.array(MachineReportSchema).optional(),
|
|
286
|
+
});
|
|
287
|
+
export type SyncStatus = z.infer<typeof SyncStatusSchema>;
|