@cuna_labs/cli 0.1.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/LICENSE +201 -0
- package/NOTICE +9 -0
- package/README.md +169 -0
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/dist/api/capability-evidence.d.ts +19 -0
- package/dist/api/capability-evidence.d.ts.map +1 -0
- package/dist/api/capability-evidence.js +38 -0
- package/dist/api/capability-evidence.js.map +1 -0
- package/dist/api/client.d.ts +167 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +937 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/contracts.d.ts +345 -0
- package/dist/api/contracts.d.ts.map +1 -0
- package/dist/api/contracts.js +976 -0
- package/dist/api/contracts.js.map +1 -0
- package/dist/api/execution-workspaces.d.ts +17 -0
- package/dist/api/execution-workspaces.d.ts.map +1 -0
- package/dist/api/execution-workspaces.js +46 -0
- package/dist/api/execution-workspaces.js.map +1 -0
- package/dist/api/http.d.ts +76 -0
- package/dist/api/http.d.ts.map +1 -0
- package/dist/api/http.js +838 -0
- package/dist/api/http.js.map +1 -0
- package/dist/api/managed-executions.d.ts +37 -0
- package/dist/api/managed-executions.d.ts.map +1 -0
- package/dist/api/managed-executions.js +80 -0
- package/dist/api/managed-executions.js.map +1 -0
- package/dist/api/observer-v2-schema.d.ts +206 -0
- package/dist/api/observer-v2-schema.d.ts.map +1 -0
- package/dist/api/observer-v2-schema.js +264 -0
- package/dist/api/observer-v2-schema.js.map +1 -0
- package/dist/api/observer-v2.d.ts +33 -0
- package/dist/api/observer-v2.d.ts.map +1 -0
- package/dist/api/observer-v2.js +60 -0
- package/dist/api/observer-v2.js.map +1 -0
- package/dist/api/owner-observe-grants-v2-schema.d.ts +678 -0
- package/dist/api/owner-observe-grants-v2-schema.d.ts.map +1 -0
- package/dist/api/owner-observe-grants-v2-schema.js +887 -0
- package/dist/api/owner-observe-grants-v2-schema.js.map +1 -0
- package/dist/api/owner-observe-grants-v2.d.ts +268 -0
- package/dist/api/owner-observe-grants-v2.d.ts.map +1 -0
- package/dist/api/owner-observe-grants-v2.js +604 -0
- package/dist/api/owner-observe-grants-v2.js.map +1 -0
- package/dist/api/provider-v2-schema.d.ts +293 -0
- package/dist/api/provider-v2-schema.d.ts.map +1 -0
- package/dist/api/provider-v2-schema.js +381 -0
- package/dist/api/provider-v2-schema.js.map +1 -0
- package/dist/api/provider-v2.d.ts +55 -0
- package/dist/api/provider-v2.d.ts.map +1 -0
- package/dist/api/provider-v2.js +54 -0
- package/dist/api/provider-v2.js.map +1 -0
- package/dist/api/remote-workspace.d.ts +29 -0
- package/dist/api/remote-workspace.d.ts.map +1 -0
- package/dist/api/remote-workspace.js +62 -0
- package/dist/api/remote-workspace.js.map +1 -0
- package/dist/api/supervisor-live-update.d.ts +248 -0
- package/dist/api/supervisor-live-update.d.ts.map +1 -0
- package/dist/api/supervisor-live-update.js +434 -0
- package/dist/api/supervisor-live-update.js.map +1 -0
- package/dist/api/terminal-reason.d.ts +5 -0
- package/dist/api/terminal-reason.d.ts.map +1 -0
- package/dist/api/terminal-reason.js +12 -0
- package/dist/api/terminal-reason.js.map +1 -0
- package/dist/auth/browser-handoff.d.ts +59 -0
- package/dist/auth/browser-handoff.d.ts.map +1 -0
- package/dist/auth/browser-handoff.js +33 -0
- package/dist/auth/browser-handoff.js.map +1 -0
- package/dist/auth/browser.d.ts +11 -0
- package/dist/auth/browser.d.ts.map +1 -0
- package/dist/auth/browser.js +47 -0
- package/dist/auth/browser.js.map +1 -0
- package/dist/auth/human-client.d.ts +39 -0
- package/dist/auth/human-client.d.ts.map +1 -0
- package/dist/auth/human-client.js +66 -0
- package/dist/auth/human-client.js.map +1 -0
- package/dist/auth/human-contracts.d.ts +52 -0
- package/dist/auth/human-contracts.d.ts.map +1 -0
- package/dist/auth/human-contracts.js +229 -0
- package/dist/auth/human-contracts.js.map +1 -0
- package/dist/auth/human-session.d.ts +48 -0
- package/dist/auth/human-session.d.ts.map +1 -0
- package/dist/auth/human-session.js +902 -0
- package/dist/auth/human-session.js.map +1 -0
- package/dist/auth/onboarding-state.d.ts +31 -0
- package/dist/auth/onboarding-state.d.ts.map +1 -0
- package/dist/auth/onboarding-state.js +52 -0
- package/dist/auth/onboarding-state.js.map +1 -0
- package/dist/auth/pkce.d.ts +15 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +19 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/bin/cuna.d.ts +3 -0
- package/dist/bin/cuna.d.ts.map +1 -0
- package/dist/bin/cuna.js +4 -0
- package/dist/bin/cuna.js.map +1 -0
- package/dist/build-identity.d.ts +20 -0
- package/dist/build-identity.d.ts.map +1 -0
- package/dist/build-identity.js +77 -0
- package/dist/build-identity.js.map +1 -0
- package/dist/cli/command-help.d.ts +9 -0
- package/dist/cli/command-help.d.ts.map +1 -0
- package/dist/cli/command-help.js +324 -0
- package/dist/cli/command-help.js.map +1 -0
- package/dist/cli/help.d.ts +40 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +256 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/output.d.ts +28 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +95 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/parser.d.ts +65 -0
- package/dist/cli/parser.d.ts.map +1 -0
- package/dist/cli/parser.js +294 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/cli/process-entrypoint.d.ts +18 -0
- package/dist/cli/process-entrypoint.d.ts.map +1 -0
- package/dist/cli/process-entrypoint.js +26 -0
- package/dist/cli/process-entrypoint.js.map +1 -0
- package/dist/cli/run.d.ts +114 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +1969 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/commands/commands.d.ts +74 -0
- package/dist/commands/commands.d.ts.map +1 -0
- package/dist/commands/commands.js +2814 -0
- package/dist/commands/commands.js.map +1 -0
- package/dist/config/config.d.ts +86 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +323 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/infra-contract-witness.d.ts +29 -0
- package/dist/config/infra-contract-witness.d.ts.map +1 -0
- package/dist/config/infra-contract-witness.js +30 -0
- package/dist/config/infra-contract-witness.js.map +1 -0
- package/dist/core/browser-url.d.ts +2 -0
- package/dist/core/browser-url.d.ts.map +1 -0
- package/dist/core/browser-url.js +20 -0
- package/dist/core/browser-url.js.map +1 -0
- package/dist/core/deployed-wire-compatibility.d.ts +15 -0
- package/dist/core/deployed-wire-compatibility.d.ts.map +1 -0
- package/dist/core/deployed-wire-compatibility.js +15 -0
- package/dist/core/deployed-wire-compatibility.js.map +1 -0
- package/dist/core/errors.d.ts +59 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +82 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/exit-codes.d.ts +68 -0
- package/dist/core/exit-codes.d.ts.map +1 -0
- package/dist/core/exit-codes.js +84 -0
- package/dist/core/exit-codes.js.map +1 -0
- package/dist/core/instant.d.ts +60 -0
- package/dist/core/instant.d.ts.map +1 -0
- package/dist/core/instant.js +90 -0
- package/dist/core/instant.js.map +1 -0
- package/dist/core/namespace.d.ts +171 -0
- package/dist/core/namespace.d.ts.map +1 -0
- package/dist/core/namespace.js +227 -0
- package/dist/core/namespace.js.map +1 -0
- package/dist/core/observation-budget.d.ts +185 -0
- package/dist/core/observation-budget.d.ts.map +1 -0
- package/dist/core/observation-budget.js +209 -0
- package/dist/core/observation-budget.js.map +1 -0
- package/dist/core/product-web.d.ts +81 -0
- package/dist/core/product-web.d.ts.map +1 -0
- package/dist/core/product-web.js +87 -0
- package/dist/core/product-web.js.map +1 -0
- package/dist/core/validation.d.ts +90 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +199 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/credentials/contracts.d.ts +82 -0
- package/dist/credentials/contracts.d.ts.map +1 -0
- package/dist/credentials/contracts.js +2 -0
- package/dist/credentials/contracts.js.map +1 -0
- package/dist/credentials/errors.d.ts +19 -0
- package/dist/credentials/errors.d.ts.map +1 -0
- package/dist/credentials/errors.js +16 -0
- package/dist/credentials/errors.js.map +1 -0
- package/dist/credentials/index.d.ts +6 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +6 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/credentials/local-session.d.ts +101 -0
- package/dist/credentials/local-session.d.ts.map +1 -0
- package/dist/credentials/local-session.js +839 -0
- package/dist/credentials/local-session.js.map +1 -0
- package/dist/credentials/secret-material.d.ts +17 -0
- package/dist/credentials/secret-material.d.ts.map +1 -0
- package/dist/credentials/secret-material.js +49 -0
- package/dist/credentials/secret-material.js.map +1 -0
- package/dist/credentials/vault.d.ts +41 -0
- package/dist/credentials/vault.d.ts.map +1 -0
- package/dist/credentials/vault.js +719 -0
- package/dist/credentials/vault.js.map +1 -0
- package/dist/daemon/endpoint.d.ts +29 -0
- package/dist/daemon/endpoint.d.ts.map +1 -0
- package/dist/daemon/endpoint.js +66 -0
- package/dist/daemon/endpoint.js.map +1 -0
- package/dist/daemon/journal.d.ts +62 -0
- package/dist/daemon/journal.d.ts.map +1 -0
- package/dist/daemon/journal.js +299 -0
- package/dist/daemon/journal.js.map +1 -0
- package/dist/daemon/lease.d.ts +25 -0
- package/dist/daemon/lease.d.ts.map +1 -0
- package/dist/daemon/lease.js +94 -0
- package/dist/daemon/lease.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +14 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -0
- package/dist/daemon/lifecycle.js +29 -0
- package/dist/daemon/lifecycle.js.map +1 -0
- package/dist/daemon/protocol.d.ts +65 -0
- package/dist/daemon/protocol.d.ts.map +1 -0
- package/dist/daemon/protocol.js +194 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/daemon/supervisor.d.ts +29 -0
- package/dist/daemon/supervisor.d.ts.map +1 -0
- package/dist/daemon/supervisor.js +87 -0
- package/dist/daemon/supervisor.js.map +1 -0
- package/dist/daemon/views.d.ts +31 -0
- package/dist/daemon/views.d.ts.map +1 -0
- package/dist/daemon/views.js +86 -0
- package/dist/daemon/views.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/journey/api-effects.d.ts +59 -0
- package/dist/journey/api-effects.d.ts.map +1 -0
- package/dist/journey/api-effects.js +386 -0
- package/dist/journey/api-effects.js.map +1 -0
- package/dist/journey/derived-identity.d.ts +91 -0
- package/dist/journey/derived-identity.d.ts.map +1 -0
- package/dist/journey/derived-identity.js +123 -0
- package/dist/journey/derived-identity.js.map +1 -0
- package/dist/journey/index.d.ts +6 -0
- package/dist/journey/index.d.ts.map +1 -0
- package/dist/journey/index.js +6 -0
- package/dist/journey/index.js.map +1 -0
- package/dist/journey/intent.d.ts +36 -0
- package/dist/journey/intent.d.ts.map +1 -0
- package/dist/journey/intent.js +191 -0
- package/dist/journey/intent.js.map +1 -0
- package/dist/journey/orchestrator.d.ts +140 -0
- package/dist/journey/orchestrator.d.ts.map +1 -0
- package/dist/journey/orchestrator.js +415 -0
- package/dist/journey/orchestrator.js.map +1 -0
- package/dist/journey/provider-launch-intent.d.ts +12 -0
- package/dist/journey/provider-launch-intent.d.ts.map +1 -0
- package/dist/journey/provider-launch-intent.js +40 -0
- package/dist/journey/provider-launch-intent.js.map +1 -0
- package/dist/journey/remote-workspace.d.ts +34 -0
- package/dist/journey/remote-workspace.d.ts.map +1 -0
- package/dist/journey/remote-workspace.js +91 -0
- package/dist/journey/remote-workspace.js.map +1 -0
- package/dist/journey/root-entry.d.ts +56 -0
- package/dist/journey/root-entry.d.ts.map +1 -0
- package/dist/journey/root-entry.js +19 -0
- package/dist/journey/root-entry.js.map +1 -0
- package/dist/journey/selection.d.ts +165 -0
- package/dist/journey/selection.d.ts.map +1 -0
- package/dist/journey/selection.js +565 -0
- package/dist/journey/selection.js.map +1 -0
- package/dist/journey/session-failure.d.ts +4 -0
- package/dist/journey/session-failure.d.ts.map +1 -0
- package/dist/journey/session-failure.js +28 -0
- package/dist/journey/session-failure.js.map +1 -0
- package/dist/journey/workspace-effects.d.ts +30 -0
- package/dist/journey/workspace-effects.d.ts.map +1 -0
- package/dist/journey/workspace-effects.js +348 -0
- package/dist/journey/workspace-effects.js.map +1 -0
- package/dist/local-actions/broker.d.ts +32 -0
- package/dist/local-actions/broker.d.ts.map +1 -0
- package/dist/local-actions/broker.js +400 -0
- package/dist/local-actions/broker.js.map +1 -0
- package/dist/local-actions/browser-action.d.ts +78 -0
- package/dist/local-actions/browser-action.d.ts.map +1 -0
- package/dist/local-actions/browser-action.js +307 -0
- package/dist/local-actions/browser-action.js.map +1 -0
- package/dist/local-actions/callback-relay.d.ts +45 -0
- package/dist/local-actions/callback-relay.d.ts.map +1 -0
- package/dist/local-actions/callback-relay.js +265 -0
- package/dist/local-actions/callback-relay.js.map +1 -0
- package/dist/local-actions/clipboard.d.ts +3 -0
- package/dist/local-actions/clipboard.d.ts.map +1 -0
- package/dist/local-actions/clipboard.js +18 -0
- package/dist/local-actions/clipboard.js.map +1 -0
- package/dist/local-actions/contracts.d.ts +63 -0
- package/dist/local-actions/contracts.d.ts.map +1 -0
- package/dist/local-actions/contracts.js +18 -0
- package/dist/local-actions/contracts.js.map +1 -0
- package/dist/local-actions/desktop-presentation.d.ts +141 -0
- package/dist/local-actions/desktop-presentation.d.ts.map +1 -0
- package/dist/local-actions/desktop-presentation.js +253 -0
- package/dist/local-actions/desktop-presentation.js.map +1 -0
- package/dist/local-actions/device-selection.d.ts +43 -0
- package/dist/local-actions/device-selection.d.ts.map +1 -0
- package/dist/local-actions/device-selection.js +154 -0
- package/dist/local-actions/device-selection.js.map +1 -0
- package/dist/local-actions/executor.d.ts +49 -0
- package/dist/local-actions/executor.d.ts.map +1 -0
- package/dist/local-actions/executor.js +329 -0
- package/dist/local-actions/executor.js.map +1 -0
- package/dist/local-actions/file-transfers.d.ts +141 -0
- package/dist/local-actions/file-transfers.d.ts.map +1 -0
- package/dist/local-actions/file-transfers.js +446 -0
- package/dist/local-actions/file-transfers.js.map +1 -0
- package/dist/local-actions/foreground-notifications.d.ts +45 -0
- package/dist/local-actions/foreground-notifications.d.ts.map +1 -0
- package/dist/local-actions/foreground-notifications.js +163 -0
- package/dist/local-actions/foreground-notifications.js.map +1 -0
- package/dist/local-actions/git-signing.d.ts +39 -0
- package/dist/local-actions/git-signing.d.ts.map +1 -0
- package/dist/local-actions/git-signing.js +135 -0
- package/dist/local-actions/git-signing.js.map +1 -0
- package/dist/local-actions/index.d.ts +19 -0
- package/dist/local-actions/index.d.ts.map +1 -0
- package/dist/local-actions/index.js +19 -0
- package/dist/local-actions/index.js.map +1 -0
- package/dist/local-actions/local-service-actions.d.ts +87 -0
- package/dist/local-actions/local-service-actions.d.ts.map +1 -0
- package/dist/local-actions/local-service-actions.js +347 -0
- package/dist/local-actions/local-service-actions.js.map +1 -0
- package/dist/local-actions/loopback.d.ts +5 -0
- package/dist/local-actions/loopback.d.ts.map +1 -0
- package/dist/local-actions/loopback.js +15 -0
- package/dist/local-actions/loopback.js.map +1 -0
- package/dist/local-actions/policy-store.d.ts +7 -0
- package/dist/local-actions/policy-store.d.ts.map +1 -0
- package/dist/local-actions/policy-store.js +70 -0
- package/dist/local-actions/policy-store.js.map +1 -0
- package/dist/local-actions/policy.d.ts +21 -0
- package/dist/local-actions/policy.d.ts.map +1 -0
- package/dist/local-actions/policy.js +43 -0
- package/dist/local-actions/policy.js.map +1 -0
- package/dist/local-actions/private-port-forward.d.ts +36 -0
- package/dist/local-actions/private-port-forward.d.ts.map +1 -0
- package/dist/local-actions/private-port-forward.js +154 -0
- package/dist/local-actions/private-port-forward.js.map +1 -0
- package/dist/local-actions/provider-mcp-config.d.ts +101 -0
- package/dist/local-actions/provider-mcp-config.d.ts.map +1 -0
- package/dist/local-actions/provider-mcp-config.js +166 -0
- package/dist/local-actions/provider-mcp-config.js.map +1 -0
- package/dist/local-actions/providers.d.ts +12 -0
- package/dist/local-actions/providers.d.ts.map +1 -0
- package/dist/local-actions/providers.js +42 -0
- package/dist/local-actions/providers.js.map +1 -0
- package/dist/local-actions/schemas.d.ts +4 -0
- package/dist/local-actions/schemas.d.ts.map +1 -0
- package/dist/local-actions/schemas.js +314 -0
- package/dist/local-actions/schemas.js.map +1 -0
- package/dist/local-actions/sensitive-consent.d.ts +32 -0
- package/dist/local-actions/sensitive-consent.d.ts.map +1 -0
- package/dist/local-actions/sensitive-consent.js +47 -0
- package/dist/local-actions/sensitive-consent.js.map +1 -0
- package/dist/machines/command-launch.d.ts +17 -0
- package/dist/machines/command-launch.d.ts.map +1 -0
- package/dist/machines/command-launch.js +52 -0
- package/dist/machines/command-launch.js.map +1 -0
- package/dist/machines/execution-receipt.d.ts +18 -0
- package/dist/machines/execution-receipt.d.ts.map +1 -0
- package/dist/machines/execution-receipt.js +87 -0
- package/dist/machines/execution-receipt.js.map +1 -0
- package/dist/machines/executions-screen.d.ts +6 -0
- package/dist/machines/executions-screen.d.ts.map +1 -0
- package/dist/machines/executions-screen.js +410 -0
- package/dist/machines/executions-screen.js.map +1 -0
- package/dist/machines/explorer.d.ts +75 -0
- package/dist/machines/explorer.d.ts.map +1 -0
- package/dist/machines/explorer.js +1726 -0
- package/dist/machines/explorer.js.map +1 -0
- package/dist/machines/live-supervisor-update.d.ts +325 -0
- package/dist/machines/live-supervisor-update.d.ts.map +1 -0
- package/dist/machines/live-supervisor-update.js +513 -0
- package/dist/machines/live-supervisor-update.js.map +1 -0
- package/dist/machines/machine-first.d.ts +123 -0
- package/dist/machines/machine-first.d.ts.map +1 -0
- package/dist/machines/machine-first.js +119 -0
- package/dist/machines/machine-first.js.map +1 -0
- package/dist/machines/opencode-supervisor.d.ts +51 -0
- package/dist/machines/opencode-supervisor.d.ts.map +1 -0
- package/dist/machines/opencode-supervisor.js +124 -0
- package/dist/machines/opencode-supervisor.js.map +1 -0
- package/dist/machines/pagination.d.ts +4 -0
- package/dist/machines/pagination.d.ts.map +1 -0
- package/dist/machines/pagination.js +7 -0
- package/dist/machines/pagination.js.map +1 -0
- package/dist/machines/provider-availability.d.ts +42 -0
- package/dist/machines/provider-availability.d.ts.map +1 -0
- package/dist/machines/provider-availability.js +82 -0
- package/dist/machines/provider-availability.js.map +1 -0
- package/dist/machines/provider-screen.d.ts +12 -0
- package/dist/machines/provider-screen.d.ts.map +1 -0
- package/dist/machines/provider-screen.js +129 -0
- package/dist/machines/provider-screen.js.map +1 -0
- package/dist/machines/session-actionability.d.ts +86 -0
- package/dist/machines/session-actionability.d.ts.map +1 -0
- package/dist/machines/session-actionability.js +125 -0
- package/dist/machines/session-actionability.js.map +1 -0
- package/dist/machines/session-visibility.d.ts +139 -0
- package/dist/machines/session-visibility.d.ts.map +1 -0
- package/dist/machines/session-visibility.js +109 -0
- package/dist/machines/session-visibility.js.map +1 -0
- package/dist/platform/adapter.d.ts +62 -0
- package/dist/platform/adapter.d.ts.map +1 -0
- package/dist/platform/adapter.js +240 -0
- package/dist/platform/adapter.js.map +1 -0
- package/dist/platform/support.d.ts +12 -0
- package/dist/platform/support.d.ts.map +1 -0
- package/dist/platform/support.js +25 -0
- package/dist/platform/support.js.map +1 -0
- package/dist/pty/contracts.d.ts +45 -0
- package/dist/pty/contracts.d.ts.map +1 -0
- package/dist/pty/contracts.js +2 -0
- package/dist/pty/contracts.js.map +1 -0
- package/dist/pty/evidence-gate.d.ts +14 -0
- package/dist/pty/evidence-gate.d.ts.map +1 -0
- package/dist/pty/evidence-gate.js +35 -0
- package/dist/pty/evidence-gate.js.map +1 -0
- package/dist/pty/index.d.ts +5 -0
- package/dist/pty/index.d.ts.map +1 -0
- package/dist/pty/index.js +5 -0
- package/dist/pty/index.js.map +1 -0
- package/dist/pty/node-host-terminal.d.ts +14 -0
- package/dist/pty/node-host-terminal.d.ts.map +1 -0
- package/dist/pty/node-host-terminal.js +173 -0
- package/dist/pty/node-host-terminal.js.map +1 -0
- package/dist/pty/node-process.d.ts +26 -0
- package/dist/pty/node-process.d.ts.map +1 -0
- package/dist/pty/node-process.js +102 -0
- package/dist/pty/node-process.js.map +1 -0
- package/dist/runtime/api-terminal-control-plane.d.ts +7 -0
- package/dist/runtime/api-terminal-control-plane.d.ts.map +1 -0
- package/dist/runtime/api-terminal-control-plane.js +95 -0
- package/dist/runtime/api-terminal-control-plane.js.map +1 -0
- package/dist/runtime/backoff.d.ts +17 -0
- package/dist/runtime/backoff.d.ts.map +1 -0
- package/dist/runtime/backoff.js +61 -0
- package/dist/runtime/backoff.js.map +1 -0
- package/dist/runtime/boundary.d.ts +171 -0
- package/dist/runtime/boundary.d.ts.map +1 -0
- package/dist/runtime/boundary.js +1858 -0
- package/dist/runtime/boundary.js.map +1 -0
- package/dist/runtime/capability-gate.d.ts +25 -0
- package/dist/runtime/capability-gate.d.ts.map +1 -0
- package/dist/runtime/capability-gate.js +77 -0
- package/dist/runtime/capability-gate.js.map +1 -0
- package/dist/runtime/contracts.d.ts +25 -0
- package/dist/runtime/contracts.d.ts.map +1 -0
- package/dist/runtime/contracts.js +66 -0
- package/dist/runtime/contracts.js.map +1 -0
- package/dist/runtime/errors.d.ts +20 -0
- package/dist/runtime/errors.d.ts.map +1 -0
- package/dist/runtime/errors.js +22 -0
- package/dist/runtime/errors.js.map +1 -0
- package/dist/runtime/index.d.ts +9 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +9 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/node-foreground-session.d.ts +50 -0
- package/dist/runtime/node-foreground-session.d.ts.map +1 -0
- package/dist/runtime/node-foreground-session.js +431 -0
- package/dist/runtime/node-foreground-session.js.map +1 -0
- package/dist/runtime/node-websocket-connector.d.ts +6 -0
- package/dist/runtime/node-websocket-connector.d.ts.map +1 -0
- package/dist/runtime/node-websocket-connector.js +344 -0
- package/dist/runtime/node-websocket-connector.js.map +1 -0
- package/dist/runtime/observer-screen.d.ts +6 -0
- package/dist/runtime/observer-screen.d.ts.map +1 -0
- package/dist/runtime/observer-screen.js +144 -0
- package/dist/runtime/observer-screen.js.map +1 -0
- package/dist/runtime/owner-grant-operations.d.ts +136 -0
- package/dist/runtime/owner-grant-operations.d.ts.map +1 -0
- package/dist/runtime/owner-grant-operations.js +216 -0
- package/dist/runtime/owner-grant-operations.js.map +1 -0
- package/dist/runtime/owner-grants-screen.d.ts +40 -0
- package/dist/runtime/owner-grants-screen.d.ts.map +1 -0
- package/dist/runtime/owner-grants-screen.js +987 -0
- package/dist/runtime/owner-grants-screen.js.map +1 -0
- package/dist/runtime/terminal-transport.d.ts +85 -0
- package/dist/runtime/terminal-transport.d.ts.map +1 -0
- package/dist/runtime/terminal-transport.js +152 -0
- package/dist/runtime/terminal-transport.js.map +1 -0
- package/dist/sync/continuous-sync-supervisor.d.ts +107 -0
- package/dist/sync/continuous-sync-supervisor.d.ts.map +1 -0
- package/dist/sync/continuous-sync-supervisor.js +1117 -0
- package/dist/sync/continuous-sync-supervisor.js.map +1 -0
- package/dist/sync/index.d.ts +9 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +9 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/journal.d.ts +57 -0
- package/dist/sync/journal.d.ts.map +1 -0
- package/dist/sync/journal.js +685 -0
- package/dist/sync/journal.js.map +1 -0
- package/dist/sync/revisions.d.ts +118 -0
- package/dist/sync/revisions.d.ts.map +1 -0
- package/dist/sync/revisions.js +364 -0
- package/dist/sync/revisions.js.map +1 -0
- package/dist/sync/supervisor.d.ts +107 -0
- package/dist/sync/supervisor.d.ts.map +1 -0
- package/dist/sync/supervisor.js +246 -0
- package/dist/sync/supervisor.js.map +1 -0
- package/dist/sync/workspace-sync-client.d.ts +18 -0
- package/dist/sync/workspace-sync-client.d.ts.map +1 -0
- package/dist/sync/workspace-sync-client.js +150 -0
- package/dist/sync/workspace-sync-client.js.map +1 -0
- package/dist/sync/workspace-sync-coordinator.d.ts +76 -0
- package/dist/sync/workspace-sync-coordinator.d.ts.map +1 -0
- package/dist/sync/workspace-sync-coordinator.js +621 -0
- package/dist/sync/workspace-sync-coordinator.js.map +1 -0
- package/dist/sync/workspace-sync-product-service.d.ts +79 -0
- package/dist/sync/workspace-sync-product-service.d.ts.map +1 -0
- package/dist/sync/workspace-sync-product-service.js +398 -0
- package/dist/sync/workspace-sync-product-service.js.map +1 -0
- package/dist/sync/workspace-sync-protocol.d.ts +145 -0
- package/dist/sync/workspace-sync-protocol.d.ts.map +1 -0
- package/dist/sync/workspace-sync-protocol.js +347 -0
- package/dist/sync/workspace-sync-protocol.js.map +1 -0
- package/dist/terminal/appbar.d.ts +40 -0
- package/dist/terminal/appbar.d.ts.map +1 -0
- package/dist/terminal/appbar.js +55 -0
- package/dist/terminal/appbar.js.map +1 -0
- package/dist/terminal/cell-width.d.ts +3 -0
- package/dist/terminal/cell-width.d.ts.map +1 -0
- package/dist/terminal/cell-width.js +53 -0
- package/dist/terminal/cell-width.js.map +1 -0
- package/dist/terminal/codec.d.ts +107 -0
- package/dist/terminal/codec.d.ts.map +1 -0
- package/dist/terminal/codec.js +538 -0
- package/dist/terminal/codec.js.map +1 -0
- package/dist/terminal/foreground.d.ts +135 -0
- package/dist/terminal/foreground.d.ts.map +1 -0
- package/dist/terminal/foreground.js +2097 -0
- package/dist/terminal/foreground.js.map +1 -0
- package/dist/terminal/generated/terminal-wire-v1.d.ts +26 -0
- package/dist/terminal/generated/terminal-wire-v1.d.ts.map +1 -0
- package/dist/terminal/generated/terminal-wire-v1.js +27 -0
- package/dist/terminal/generated/terminal-wire-v1.js.map +1 -0
- package/dist/terminal/mode.d.ts +33 -0
- package/dist/terminal/mode.d.ts.map +1 -0
- package/dist/terminal/mode.js +99 -0
- package/dist/terminal/mode.js.map +1 -0
- package/dist/terminal/passthrough.d.ts +47 -0
- package/dist/terminal/passthrough.d.ts.map +1 -0
- package/dist/terminal/passthrough.js +666 -0
- package/dist/terminal/passthrough.js.map +1 -0
- package/dist/terminal/resume.d.ts +58 -0
- package/dist/terminal/resume.d.ts.map +1 -0
- package/dist/terminal/resume.js +185 -0
- package/dist/terminal/resume.js.map +1 -0
- package/dist/terminal/viewport.d.ts +93 -0
- package/dist/terminal/viewport.d.ts.map +1 -0
- package/dist/terminal/viewport.js +266 -0
- package/dist/terminal/viewport.js.map +1 -0
- package/dist/terminal/workbench.d.ts +32 -0
- package/dist/terminal/workbench.d.ts.map +1 -0
- package/dist/terminal/workbench.js +316 -0
- package/dist/terminal/workbench.js.map +1 -0
- package/dist/terminal/xterm-vte.d.ts +49 -0
- package/dist/terminal/xterm-vte.d.ts.map +1 -0
- package/dist/terminal/xterm-vte.js +602 -0
- package/dist/terminal/xterm-vte.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/workspace/binding-path.d.ts +17 -0
- package/dist/workspace/binding-path.d.ts.map +1 -0
- package/dist/workspace/binding-path.js +91 -0
- package/dist/workspace/binding-path.js.map +1 -0
- package/dist/workspace/binding-store.d.ts +107 -0
- package/dist/workspace/binding-store.d.ts.map +1 -0
- package/dist/workspace/binding-store.js +783 -0
- package/dist/workspace/binding-store.js.map +1 -0
- package/dist/workspace/binding.d.ts +35 -0
- package/dist/workspace/binding.d.ts.map +1 -0
- package/dist/workspace/binding.js +70 -0
- package/dist/workspace/binding.js.map +1 -0
- package/dist/workspace/errors.d.ts +4 -0
- package/dist/workspace/errors.d.ts.map +1 -0
- package/dist/workspace/errors.js +19 -0
- package/dist/workspace/errors.js.map +1 -0
- package/dist/workspace/exclusion.d.ts +21 -0
- package/dist/workspace/exclusion.d.ts.map +1 -0
- package/dist/workspace/exclusion.js +243 -0
- package/dist/workspace/exclusion.js.map +1 -0
- package/dist/workspace/index.d.ts +8 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +8 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/lifecycle.d.ts +56 -0
- package/dist/workspace/lifecycle.d.ts.map +1 -0
- package/dist/workspace/lifecycle.js +94 -0
- package/dist/workspace/lifecycle.js.map +1 -0
- package/dist/workspace/manifest.d.ts +47 -0
- package/dist/workspace/manifest.d.ts.map +1 -0
- package/dist/workspace/manifest.js +243 -0
- package/dist/workspace/manifest.js.map +1 -0
- package/dist/workspace/paths.d.ts +14 -0
- package/dist/workspace/paths.d.ts.map +1 -0
- package/dist/workspace/paths.js +67 -0
- package/dist/workspace/paths.js.map +1 -0
- package/dist/workspace/schema.d.ts +15 -0
- package/dist/workspace/schema.d.ts.map +1 -0
- package/dist/workspace/schema.js +33 -0
- package/dist/workspace/schema.js.map +1 -0
- package/dist/workspace/selection-screen.d.ts +4 -0
- package/dist/workspace/selection-screen.d.ts.map +1 -0
- package/dist/workspace/selection-screen.js +216 -0
- package/dist/workspace/selection-screen.js.map +1 -0
- package/dist/workspace/selection-service.d.ts +16 -0
- package/dist/workspace/selection-service.d.ts.map +1 -0
- package/dist/workspace/selection-service.js +65 -0
- package/dist/workspace/selection-service.js.map +1 -0
- package/node_modules/@xterm/headless/README.md +31 -0
- package/node_modules/@xterm/headless/lib-headless/xterm-headless.js +2 -0
- package/node_modules/@xterm/headless/lib-headless/xterm-headless.js.map +1 -0
- package/node_modules/@xterm/headless/lib-headless/xterm-headless.mjs +46 -0
- package/node_modules/@xterm/headless/lib-headless/xterm-headless.mjs.map +7 -0
- package/node_modules/@xterm/headless/package.json +29 -0
- package/node_modules/@xterm/headless/typings/xterm-headless.d.ts +1385 -0
- package/package.json +75 -0
|
@@ -0,0 +1,976 @@
|
|
|
1
|
+
import { isTerminalReason } from "./terminal-reason.js";
|
|
2
|
+
import { containsCredentialValue, isApiKeyDisplayPrefix, isSecretApiKey, isTerminalConnectToken, isTerminalStreamUrl, } from "../core/namespace.js";
|
|
3
|
+
import { DEPLOYED_WIRE_COMPATIBILITY } from "../core/deployed-wire-compatibility.js";
|
|
4
|
+
import { contractViolation, isObject, optionalDisplayString, optionalNumber, optionalString, requiredDisplayString, requiredString, underField, } from "../core/validation.js";
|
|
5
|
+
const AVAILABILITY = new Set(["supported", "unsupported", "temporarily_unavailable", "unknown"]);
|
|
6
|
+
const INTERACTION = new Set(["native", "read_only", "browser_handoff"]);
|
|
7
|
+
const MUTATION = new Set(["none", "reversible", "destructive", "secret_revealing", "financial"]);
|
|
8
|
+
const SCOPE = new Set(["account", "machine", "agent_session"]);
|
|
9
|
+
function stringArray(value, key) {
|
|
10
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
11
|
+
throw contractViolation("array_of_strings", key);
|
|
12
|
+
}
|
|
13
|
+
return Object.freeze([...value]);
|
|
14
|
+
}
|
|
15
|
+
function decodeCapability(value) {
|
|
16
|
+
if (!isObject(value))
|
|
17
|
+
throw contractViolation("object");
|
|
18
|
+
const id = requiredString(value, "id");
|
|
19
|
+
const rawAvailability = requiredString(value, "availability");
|
|
20
|
+
const rawInteraction = requiredString(value, "interaction");
|
|
21
|
+
const rawMutation = requiredString(value, "mutation_class");
|
|
22
|
+
const known = AVAILABILITY.has(rawAvailability) && INTERACTION.has(rawInteraction) && MUTATION.has(rawMutation);
|
|
23
|
+
const reasonCode = optionalString(value, "reason_code");
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
id,
|
|
26
|
+
availability: (known ? rawAvailability : "unknown"),
|
|
27
|
+
interaction: (INTERACTION.has(rawInteraction) ? rawInteraction : "unknown"),
|
|
28
|
+
mutationClass: (MUTATION.has(rawMutation) ? rawMutation : "unknown"),
|
|
29
|
+
surfaces: stringArray(value.surfaces, "surfaces"),
|
|
30
|
+
requiredPermissions: stringArray(value.required_permissions, "required_permissions"),
|
|
31
|
+
...(reasonCode === undefined ? {} : { reasonCode }),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function decodeCapabilitySnapshot(value) {
|
|
35
|
+
if (!isObject(value))
|
|
36
|
+
throw contractViolation("object");
|
|
37
|
+
const rawScope = requiredString(value, "subject_scope");
|
|
38
|
+
if (!SCOPE.has(rawScope))
|
|
39
|
+
throw contractViolation("known_subject_scope", "subject_scope");
|
|
40
|
+
if (!Array.isArray(value.capabilities))
|
|
41
|
+
throw contractViolation("array", "capabilities");
|
|
42
|
+
const subjectId = optionalString(value, "subject_id");
|
|
43
|
+
const schemaVersion = requiredString(value, "schema_version");
|
|
44
|
+
if (schemaVersion !== "1.0")
|
|
45
|
+
throw contractViolation("supported_schema_version", "schema_version");
|
|
46
|
+
const snapshot = Object.freeze({
|
|
47
|
+
schemaVersion,
|
|
48
|
+
subjectScope: rawScope,
|
|
49
|
+
...(subjectId === undefined ? {} : { subjectId }),
|
|
50
|
+
observedAt: requiredString(value, "observed_at"),
|
|
51
|
+
expiresAt: requiredString(value, "expires_at"),
|
|
52
|
+
etag: requiredString(value, "etag"),
|
|
53
|
+
capabilities: Object.freeze(value.capabilities.map((item, index) => underField(`capabilities[${index}]`, () => decodeCapability(item)))),
|
|
54
|
+
});
|
|
55
|
+
// Split from one compound check into two, because they name different fields.
|
|
56
|
+
// Reported together, a stale `expires_at` sent the reader to `observed_at`.
|
|
57
|
+
if (!Number.isFinite(Date.parse(snapshot.observedAt))) {
|
|
58
|
+
throw contractViolation("parsable_timestamp", "observed_at");
|
|
59
|
+
}
|
|
60
|
+
if (!Number.isFinite(Date.parse(snapshot.expiresAt))) {
|
|
61
|
+
throw contractViolation("parsable_timestamp", "expires_at");
|
|
62
|
+
}
|
|
63
|
+
return snapshot;
|
|
64
|
+
}
|
|
65
|
+
function decodeMachine(value) {
|
|
66
|
+
if (!isObject(value))
|
|
67
|
+
throw contractViolation("object");
|
|
68
|
+
const id = canonicalUuid(value, "id");
|
|
69
|
+
const createOperation = value.create_operation === undefined ? undefined
|
|
70
|
+
: underField("create_operation", () => decodeMachineCreateRequest(value.create_operation));
|
|
71
|
+
if (createOperation !== undefined && createOperation.machineId !== id) {
|
|
72
|
+
throw contractViolation("matches_machine_id", "create_operation.machine_id");
|
|
73
|
+
}
|
|
74
|
+
const state = optionalDisplayString(value, "state") ?? optionalDisplayString(value, "status") ?? "unknown";
|
|
75
|
+
const memoryMiB = optionalNumber(value, "memory_mib");
|
|
76
|
+
const vcpus = optionalNumber(value, "vcpus");
|
|
77
|
+
const agent = optionalDisplayString(value, "agent");
|
|
78
|
+
const createdAt = optionalString(value, "created_at");
|
|
79
|
+
const updatedAt = optionalString(value, "updated_at");
|
|
80
|
+
return Object.freeze({
|
|
81
|
+
id,
|
|
82
|
+
...(createOperation === undefined ? {} : { createOperation }),
|
|
83
|
+
name: optionalDisplayString(value, "name") ?? optionalDisplayString(value, "slug") ?? requiredString(value, "id"),
|
|
84
|
+
state,
|
|
85
|
+
...(agent === undefined ? {} : { agent }),
|
|
86
|
+
...(vcpus === undefined ? {} : { vcpus }),
|
|
87
|
+
...(memoryMiB === undefined ? {} : { memoryMiB }),
|
|
88
|
+
...(createdAt === undefined ? {} : { createdAt }),
|
|
89
|
+
...(updatedAt === undefined ? {} : { updatedAt }),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
export function decodeMachinePage(value) {
|
|
93
|
+
if (Array.isArray(value)) {
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
items: Object.freeze(value.map((item, index) => underField(`[${index}]`, () => decodeMachine(item)))),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (!isObject(value) || !Array.isArray(value.items))
|
|
99
|
+
throw contractViolation("object_with_items_array");
|
|
100
|
+
const nextCursor = optionalString(value, "next_cursor");
|
|
101
|
+
return Object.freeze({
|
|
102
|
+
items: Object.freeze(value.items.map((item, index) => underField(`items[${index}]`, () => decodeMachine(item)))),
|
|
103
|
+
...(nextCursor === undefined ? {} : { nextCursor }),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
export function decodeMachineItem(value) {
|
|
107
|
+
return decodeMachine(value);
|
|
108
|
+
}
|
|
109
|
+
export function decodeMachineCreateRequest(value) {
|
|
110
|
+
if (!isObject(value))
|
|
111
|
+
throw contractViolation("object");
|
|
112
|
+
exactKeys(value, ["id", "machine_id", "state", "retryable", "action", "updated_at"]);
|
|
113
|
+
const state = requiredString(value, "state");
|
|
114
|
+
const action = requiredString(value, "action");
|
|
115
|
+
const updatedAt = requiredString(value, "updated_at");
|
|
116
|
+
if (!new Set([
|
|
117
|
+
"prepared", "in_progress", "unknown", "provider_succeeded", "settled", "terminal_failed",
|
|
118
|
+
]).has(state)) {
|
|
119
|
+
throw contractViolation("known_enum_value", "state");
|
|
120
|
+
}
|
|
121
|
+
if (!new Set(["retry_create", "reconcile", "wait", "none"]).has(action)) {
|
|
122
|
+
throw contractViolation("known_enum_value", "action");
|
|
123
|
+
}
|
|
124
|
+
if (typeof value.retryable !== "boolean")
|
|
125
|
+
throw contractViolation("boolean", "retryable");
|
|
126
|
+
if (!Number.isFinite(Date.parse(updatedAt)))
|
|
127
|
+
throw contractViolation("parsable_timestamp", "updated_at");
|
|
128
|
+
return Object.freeze({
|
|
129
|
+
id: canonicalUuid(value, "id"),
|
|
130
|
+
machineId: canonicalUuid(value, "machine_id"),
|
|
131
|
+
state,
|
|
132
|
+
retryable: value.retryable,
|
|
133
|
+
action,
|
|
134
|
+
updatedAt,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
export function decodeWorkspaceBindingAuthority(value) {
|
|
138
|
+
if (!isObject(value))
|
|
139
|
+
throw contractViolation("object");
|
|
140
|
+
exactKeys(value, [
|
|
141
|
+
"binding_id", "workspace_id", "project_id", "local_instance_id", "machine_id", "execution_workspace_id",
|
|
142
|
+
"remote_root", "exclusion_policy_digest", "active_generation", "active_manifest_root",
|
|
143
|
+
"binding_epoch", "minimum_reader", "minimum_writer", "created_at", "updated_at",
|
|
144
|
+
]);
|
|
145
|
+
const bindingId = canonicalUuid(value, "binding_id");
|
|
146
|
+
const projectId = canonicalUuid(value, "project_id");
|
|
147
|
+
const executionWorkspaceId = value.execution_workspace_id === null ? null : canonicalUuid(value, "execution_workspace_id");
|
|
148
|
+
const exclusionPolicyDigest = requiredString(value, "exclusion_policy_digest");
|
|
149
|
+
const activeManifestRoot = requiredString(value, "active_manifest_root");
|
|
150
|
+
const remoteRoot = requiredString(value, "remote_root");
|
|
151
|
+
const createdAt = requiredString(value, "created_at");
|
|
152
|
+
const updatedAt = requiredString(value, "updated_at");
|
|
153
|
+
const activeGeneration = optionalNumber(value, "active_generation");
|
|
154
|
+
const bindingEpoch = optionalNumber(value, "binding_epoch");
|
|
155
|
+
const minimumReader = optionalNumber(value, "minimum_reader");
|
|
156
|
+
const minimumWriter = optionalNumber(value, "minimum_writer");
|
|
157
|
+
if (remoteRoot !== (executionWorkspaceId === null ? `/workspace/projects/${projectId}` : `/workspace/workspaces/${executionWorkspaceId}`)) {
|
|
158
|
+
throw contractViolation("remote_root_matches_execution_workspace", "remote_root");
|
|
159
|
+
}
|
|
160
|
+
if (!/^[0-9a-f]{64}$/u.test(exclusionPolicyDigest)) {
|
|
161
|
+
throw contractViolation("sha256_digest", "exclusion_policy_digest");
|
|
162
|
+
}
|
|
163
|
+
if (!/^[0-9a-f]{64}$/u.test(activeManifestRoot)) {
|
|
164
|
+
throw contractViolation("sha256_digest", "active_manifest_root");
|
|
165
|
+
}
|
|
166
|
+
if (!Number.isSafeInteger(activeGeneration) || Number(activeGeneration) < 0) {
|
|
167
|
+
throw contractViolation("safe_non_negative_integer", "active_generation");
|
|
168
|
+
}
|
|
169
|
+
if (!Number.isSafeInteger(bindingEpoch) || Number(bindingEpoch) < 1) {
|
|
170
|
+
throw contractViolation("safe_positive_integer", "binding_epoch");
|
|
171
|
+
}
|
|
172
|
+
if (!Number.isSafeInteger(minimumReader) || Number(minimumReader) < 1) {
|
|
173
|
+
throw contractViolation("safe_positive_integer", "minimum_reader");
|
|
174
|
+
}
|
|
175
|
+
if (!Number.isSafeInteger(minimumWriter) || Number(minimumWriter) < 1) {
|
|
176
|
+
throw contractViolation("safe_positive_integer", "minimum_writer");
|
|
177
|
+
}
|
|
178
|
+
if (!Number.isFinite(Date.parse(createdAt)))
|
|
179
|
+
throw contractViolation("parsable_timestamp", "created_at");
|
|
180
|
+
if (!Number.isFinite(Date.parse(updatedAt)))
|
|
181
|
+
throw contractViolation("parsable_timestamp", "updated_at");
|
|
182
|
+
return Object.freeze({
|
|
183
|
+
bindingId,
|
|
184
|
+
executionWorkspaceId,
|
|
185
|
+
workspaceId: canonicalUuid(value, "workspace_id"),
|
|
186
|
+
projectId,
|
|
187
|
+
localInstanceId: canonicalUuid(value, "local_instance_id"),
|
|
188
|
+
machineId: canonicalUuid(value, "machine_id"),
|
|
189
|
+
remoteRoot,
|
|
190
|
+
exclusionPolicyDigest,
|
|
191
|
+
activeGeneration: Number(activeGeneration),
|
|
192
|
+
activeManifestRoot,
|
|
193
|
+
bindingEpoch: Number(bindingEpoch),
|
|
194
|
+
minimumReader: Number(minimumReader),
|
|
195
|
+
minimumWriter: Number(minimumWriter),
|
|
196
|
+
createdAt,
|
|
197
|
+
updatedAt,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Validate `workspace.usage` and decode it.
|
|
202
|
+
*
|
|
203
|
+
* `balance_unavailable_reason` is the one optional key, present exactly when
|
|
204
|
+
* `balance_status` is `unavailable`. Everything else is required, and this is
|
|
205
|
+
* closed: a server that adds a field is refused rather than silently displayed.
|
|
206
|
+
*
|
|
207
|
+
* Separate from the identity decode on purpose. Usage is read by one command;
|
|
208
|
+
* identity is read by every command that needs to know who you are. A usage
|
|
209
|
+
* field this does not recognise must not decide whether a terminal can open.
|
|
210
|
+
*/
|
|
211
|
+
function decodeWorkspaceUsage(usage) {
|
|
212
|
+
if (Object.keys(usage).some((key) => ![
|
|
213
|
+
"est_spend_usd",
|
|
214
|
+
"est_spend_is_lower_bound",
|
|
215
|
+
"balance_status",
|
|
216
|
+
"balance_usd",
|
|
217
|
+
"balance_unavailable_reason",
|
|
218
|
+
"note",
|
|
219
|
+
].includes(key))) {
|
|
220
|
+
throw contractViolation("no_unknown_fields", "workspace.usage");
|
|
221
|
+
}
|
|
222
|
+
if (typeof usage.est_spend_usd !== "number" || !Number.isFinite(usage.est_spend_usd)) {
|
|
223
|
+
throw contractViolation("finite_number", "workspace.usage.est_spend_usd");
|
|
224
|
+
}
|
|
225
|
+
// A constant, not a flag: `false` would be a different contract.
|
|
226
|
+
if (usage.est_spend_is_lower_bound !== true) {
|
|
227
|
+
throw contractViolation("const_true", "workspace.usage.est_spend_is_lower_bound");
|
|
228
|
+
}
|
|
229
|
+
if (usage.balance_status !== "available" && usage.balance_status !== "unavailable") {
|
|
230
|
+
throw contractViolation("balance_status_vocabulary", "workspace.usage.balance_status");
|
|
231
|
+
}
|
|
232
|
+
if (usage.balance_status === "available") {
|
|
233
|
+
if (typeof usage.balance_usd !== "number" || !Number.isFinite(usage.balance_usd)) {
|
|
234
|
+
throw contractViolation("finite_number", "workspace.usage.balance_usd");
|
|
235
|
+
}
|
|
236
|
+
if (usage.balance_unavailable_reason !== undefined) {
|
|
237
|
+
throw contractViolation("absent_when_available", "workspace.usage.balance_unavailable_reason");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
// `null`, not absent and not zero: a zero balance is a real reading.
|
|
242
|
+
if (usage.balance_usd !== null) {
|
|
243
|
+
throw contractViolation("null_when_unavailable", "workspace.usage.balance_usd");
|
|
244
|
+
}
|
|
245
|
+
if (typeof usage.balance_unavailable_reason !== "string" || usage.balance_unavailable_reason === "") {
|
|
246
|
+
throw contractViolation("required_when_balance_unavailable", "workspace.usage.balance_unavailable_reason");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (typeof usage.note !== "string") {
|
|
250
|
+
throw contractViolation("string", "workspace.usage.note");
|
|
251
|
+
}
|
|
252
|
+
return Object.freeze({
|
|
253
|
+
estimatedSpendUsd: Number(usage.est_spend_usd),
|
|
254
|
+
estimatedSpendIsLowerBound: true,
|
|
255
|
+
balanceStatus: usage.balance_status,
|
|
256
|
+
balanceUsd: usage.balance_usd,
|
|
257
|
+
...(usage.balance_unavailable_reason === undefined
|
|
258
|
+
? {}
|
|
259
|
+
: { balanceUnavailableReason: String(usage.balance_unavailable_reason) }),
|
|
260
|
+
note: String(usage.note),
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Decode `/v1/me`.
|
|
265
|
+
*
|
|
266
|
+
* THE COMPOUND CHECKS BELOW WERE SPLIT DELIBERATELY, and the accept/reject
|
|
267
|
+
* boundary is unchanged: exactly the same bodies are accepted and rejected as
|
|
268
|
+
* before. What changed is that a rejection now names ONE field.
|
|
269
|
+
*
|
|
270
|
+
* This is the decoder that motivated the whole change. Production omits
|
|
271
|
+
* `workspace.id` while its own published OpenAPI marks it required when
|
|
272
|
+
* `assigned` is true, so this function is the single most likely source of
|
|
273
|
+
* `cuna.remote.malformed_response` in the field — and it used to answer with
|
|
274
|
+
* "Malformed Cuna workspace identity" for any of TEN different faults. The one
|
|
275
|
+
* fact the user needed was already computed here and thrown away.
|
|
276
|
+
*/
|
|
277
|
+
export function decodeCunaIdentity(value) {
|
|
278
|
+
if (!isObject(value))
|
|
279
|
+
throw contractViolation("object");
|
|
280
|
+
if (!isObject(value.workspace))
|
|
281
|
+
throw contractViolation("object", "workspace");
|
|
282
|
+
if (Object.keys(value).some((key) => key !== "id" && key !== "email" && key !== "workspace")) {
|
|
283
|
+
throw contractViolation("no_unknown_fields");
|
|
284
|
+
}
|
|
285
|
+
const assigned = value.workspace.assigned;
|
|
286
|
+
if (typeof assigned !== "boolean")
|
|
287
|
+
throw contractViolation("boolean", "workspace.assigned");
|
|
288
|
+
const workspaceKeys = Object.keys(value.workspace);
|
|
289
|
+
if (assigned) {
|
|
290
|
+
if (workspaceKeys.some((key) => key !== "assigned" && key !== "id" && key !== "usage")) {
|
|
291
|
+
throw contractViolation("no_unknown_fields", "workspace");
|
|
292
|
+
}
|
|
293
|
+
// The measured production defect lands exactly here.
|
|
294
|
+
if (typeof value.workspace.id !== "string") {
|
|
295
|
+
throw contractViolation("required_when_workspace_assigned", "workspace.id");
|
|
296
|
+
}
|
|
297
|
+
if (!isObject(value.workspace.usage)) {
|
|
298
|
+
throw contractViolation("required_when_workspace_assigned", "workspace.usage");
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
if (workspaceKeys.some((key) => key !== "assigned" && key !== "waitlist_position")) {
|
|
303
|
+
throw contractViolation("no_unknown_fields", "workspace");
|
|
304
|
+
}
|
|
305
|
+
if (!Number.isSafeInteger(value.workspace.waitlist_position) ||
|
|
306
|
+
Number(value.workspace.waitlist_position) < 0) {
|
|
307
|
+
throw contractViolation("safe_non_negative_integer", "workspace.waitlist_position");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// A usage fault is recorded, not thrown: it stops `cuna usage show` and
|
|
311
|
+
// nothing else. Letting it throw here took down every command that reads an
|
|
312
|
+
// identity, including the one that opens a terminal.
|
|
313
|
+
let decodedUsage = {};
|
|
314
|
+
if (assigned) {
|
|
315
|
+
try {
|
|
316
|
+
decodedUsage = {
|
|
317
|
+
workspaceUsage: underField("workspace.usage", () => decodeWorkspaceUsage(value.workspace.usage)),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
decodedUsage = {
|
|
322
|
+
workspaceUsageProblem: error instanceof Error ? error.message : "workspace usage is off contract",
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return Object.freeze({
|
|
327
|
+
id: canonicalUuid(value, "id"),
|
|
328
|
+
email: requiredString(value, "email"),
|
|
329
|
+
workspaceAssigned: assigned,
|
|
330
|
+
...(assigned
|
|
331
|
+
? {
|
|
332
|
+
workspaceId: underField("workspace", () => canonicalUuid(value.workspace, "id")),
|
|
333
|
+
...decodedUsage,
|
|
334
|
+
}
|
|
335
|
+
: { waitlistPosition: Number(value.workspace.waitlist_position) }),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
export const AGENT_SESSION_AUTH_ADAPTER_VERSION = DEPLOYED_WIRE_COMPATIBILITY.agentSessionAuthAdapterVersion;
|
|
339
|
+
export const AGENT_SESSION_AUTH_MAX_TTL_MS = 30_000;
|
|
340
|
+
export const AGENT_SESSION_AUTH_MAX_FUTURE_SKEW_MS = 5_000;
|
|
341
|
+
const AGENTS = new Set(["claude-code", "codex", "openclaw", "opencode"]);
|
|
342
|
+
const AUTH_MODES = new Set(["interactive_login", "credential_binding"]);
|
|
343
|
+
const DESIRED_STATES = new Set(["running", "terminated"]);
|
|
344
|
+
const REQUEST_STATES = new Set([
|
|
345
|
+
"launch_pending", "runtime_claimed", "launched", "termination_pending", "terminal", "failed",
|
|
346
|
+
]);
|
|
347
|
+
const PROCESS_STATES = new Set([
|
|
348
|
+
"unknown", "starting", "ready", "running", "exited", "failed", "terminating", "terminated",
|
|
349
|
+
]);
|
|
350
|
+
const PROCESS_OBSERVATIONS = new Set([
|
|
351
|
+
"observed", "unproven", "unknown",
|
|
352
|
+
]);
|
|
353
|
+
const AGENT_AUTH_STATES = new Set([
|
|
354
|
+
"login_required", "authenticated", "configured", "unavailable",
|
|
355
|
+
]);
|
|
356
|
+
const AGENT_AUTH_EVIDENCE_CLASSES = new Set([
|
|
357
|
+
"provider_cli_login_status", "provider_cli_credential_presence", "credential_binding_authority", "insufficient",
|
|
358
|
+
]);
|
|
359
|
+
const AGENT_AUTH_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+$/u;
|
|
360
|
+
function enumField(value, key, allowed) {
|
|
361
|
+
const decoded = requiredString(value, key);
|
|
362
|
+
if (!allowed.has(decoded))
|
|
363
|
+
throw contractViolation("known_enum_value", key);
|
|
364
|
+
return decoded;
|
|
365
|
+
}
|
|
366
|
+
function decodeAgentSession(value) {
|
|
367
|
+
if (!isObject(value))
|
|
368
|
+
throw contractViolation("object");
|
|
369
|
+
const allowed = new Set([
|
|
370
|
+
"id",
|
|
371
|
+
"machine_id",
|
|
372
|
+
"workspace_binding_id",
|
|
373
|
+
"workspace_generation",
|
|
374
|
+
"project_id",
|
|
375
|
+
"workspace_failure_code",
|
|
376
|
+
"terminal_reason",
|
|
377
|
+
"name",
|
|
378
|
+
"agent",
|
|
379
|
+
"cwd",
|
|
380
|
+
"auth_mode",
|
|
381
|
+
"desired_state",
|
|
382
|
+
"request_state",
|
|
383
|
+
"process_state",
|
|
384
|
+
"process_observation",
|
|
385
|
+
"process_epoch",
|
|
386
|
+
"runtime_observed_at",
|
|
387
|
+
"runtime_expires_at",
|
|
388
|
+
"termination_requested_at",
|
|
389
|
+
"row_version",
|
|
390
|
+
"created_at",
|
|
391
|
+
"updated_at",
|
|
392
|
+
]);
|
|
393
|
+
if (Object.keys(value).some((key) => !allowed.has(key))) {
|
|
394
|
+
throw contractViolation("no_unknown_fields");
|
|
395
|
+
}
|
|
396
|
+
const agent = enumField(value, "agent", AGENTS);
|
|
397
|
+
const authMode = enumField(value, "auth_mode", AUTH_MODES);
|
|
398
|
+
// Read paths intentionally remain tolerant of legacy OpenCode rows. The
|
|
399
|
+
// producer and every mutation path reject credential bindings for OpenCode,
|
|
400
|
+
// while foreground admission rejects an unsafe legacy row before it can own
|
|
401
|
+
// a terminal. Rejecting it here would make an entire paginated list
|
|
402
|
+
// unreadable during a consumer-first rollback.
|
|
403
|
+
const desiredState = enumField(value, "desired_state", DESIRED_STATES);
|
|
404
|
+
const requestState = enumField(value, "request_state", REQUEST_STATES);
|
|
405
|
+
const workspaceFailureCode = optionalString(value, "workspace_failure_code");
|
|
406
|
+
if (workspaceFailureCode !== undefined && (requestState !== "failed" || !/^[a-z][a-z0-9_.]{0,127}$/u.test(workspaceFailureCode))) {
|
|
407
|
+
throw contractViolation("failed_request_safe_workspace_reason", "workspace_failure_code");
|
|
408
|
+
}
|
|
409
|
+
const processState = enumField(value, "process_state", PROCESS_STATES);
|
|
410
|
+
const terminalReason = optionalString(value, "terminal_reason");
|
|
411
|
+
if (terminalReason !== undefined &&
|
|
412
|
+
(!isTerminalReason(terminalReason) || !["exited", "failed", "terminated"].includes(processState))) {
|
|
413
|
+
throw contractViolation("terminal_state_safe_reason", "terminal_reason");
|
|
414
|
+
}
|
|
415
|
+
// Strict where it is present, tolerant of its absence, and never defaulted.
|
|
416
|
+
// A value this build does not know is refused rather than demoted: an
|
|
417
|
+
// unrecognised provenance could be a NEW way to say "nobody looked", and
|
|
418
|
+
// reading it as `observed` is the one error this field exists to prevent.
|
|
419
|
+
const processObservation = optionalString(value, "process_observation");
|
|
420
|
+
if (processObservation !== undefined && !PROCESS_OBSERVATIONS.has(processObservation)) {
|
|
421
|
+
throw contractViolation("known_enum_value", "process_observation");
|
|
422
|
+
}
|
|
423
|
+
const processEpoch = optionalString(value, "process_epoch");
|
|
424
|
+
const runtimeObservedAt = optionalString(value, "runtime_observed_at");
|
|
425
|
+
const runtimeExpiresAt = optionalString(value, "runtime_expires_at");
|
|
426
|
+
const terminationRequestedAt = optionalString(value, "termination_requested_at");
|
|
427
|
+
const workspaceBindingId = optionalString(value, "workspace_binding_id");
|
|
428
|
+
const workspaceGeneration = optionalNumber(value, "workspace_generation");
|
|
429
|
+
if ((workspaceBindingId === undefined) !== (workspaceGeneration === undefined)) {
|
|
430
|
+
throw contractViolation("binding_id_and_generation_present_together");
|
|
431
|
+
}
|
|
432
|
+
if (workspaceBindingId !== undefined &&
|
|
433
|
+
(!UUID.test(workspaceBindingId) ||
|
|
434
|
+
!Number.isSafeInteger(workspaceGeneration) ||
|
|
435
|
+
workspaceGeneration === undefined ||
|
|
436
|
+
workspaceGeneration < 1)) {
|
|
437
|
+
throw contractViolation("workspace_binding_identity_shape");
|
|
438
|
+
}
|
|
439
|
+
// The Project is the server's answer about this exact session, so the CLI
|
|
440
|
+
// checks its shape and otherwise carries it through untouched. Absent stays
|
|
441
|
+
// absent: a session whose Workspace the server cannot resolve has an unknown
|
|
442
|
+
// Project, and inventing one here would let a caller scope work to a Project
|
|
443
|
+
// the session does not belong to.
|
|
444
|
+
const projectId = optionalString(value, "project_id");
|
|
445
|
+
if (projectId !== undefined && !UUID.test(projectId)) {
|
|
446
|
+
throw contractViolation("project_identity_shape", "project_id");
|
|
447
|
+
}
|
|
448
|
+
const rowVersion = optionalNumber(value, "row_version");
|
|
449
|
+
if (rowVersion === undefined || !Number.isSafeInteger(rowVersion) || rowVersion < 0) {
|
|
450
|
+
throw contractViolation("safe_non_negative_integer", "row_version");
|
|
451
|
+
}
|
|
452
|
+
return Object.freeze({
|
|
453
|
+
id: canonicalUuid(value, "id"),
|
|
454
|
+
machineId: canonicalUuid(value, "machine_id"),
|
|
455
|
+
...(workspaceBindingId === undefined
|
|
456
|
+
? {}
|
|
457
|
+
: { workspaceBindingId, workspaceGeneration: workspaceGeneration }),
|
|
458
|
+
...(projectId === undefined ? {} : { projectId }),
|
|
459
|
+
...(workspaceFailureCode === undefined ? {} : { workspaceFailureCode }),
|
|
460
|
+
...(terminalReason === undefined ? {} : { terminalReason: terminalReason }),
|
|
461
|
+
name: requiredDisplayString(value, "name"),
|
|
462
|
+
agent,
|
|
463
|
+
cwd: requiredDisplayString(value, "cwd"),
|
|
464
|
+
authMode,
|
|
465
|
+
desiredState,
|
|
466
|
+
requestState,
|
|
467
|
+
processState,
|
|
468
|
+
...(processObservation === undefined
|
|
469
|
+
? {}
|
|
470
|
+
: { processObservation: processObservation }),
|
|
471
|
+
...(processEpoch === undefined
|
|
472
|
+
? {}
|
|
473
|
+
: UUID.test(processEpoch)
|
|
474
|
+
? { processEpoch }
|
|
475
|
+
: (() => { throw contractViolation("canonical_uuid", "process_epoch"); })()),
|
|
476
|
+
...(runtimeObservedAt === undefined ? {} : { runtimeObservedAt }),
|
|
477
|
+
...(runtimeExpiresAt === undefined ? {} : { runtimeExpiresAt }),
|
|
478
|
+
...(terminationRequestedAt === undefined ? {} : { terminationRequestedAt }),
|
|
479
|
+
rowVersion,
|
|
480
|
+
createdAt: requiredString(value, "created_at"),
|
|
481
|
+
updatedAt: requiredString(value, "updated_at"),
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
export function decodeAgentSessionPage(value) {
|
|
485
|
+
if (Array.isArray(value)) {
|
|
486
|
+
return Object.freeze({
|
|
487
|
+
items: Object.freeze(value.map((item, index) => underField(`[${index}]`, () => decodeAgentSession(item)))),
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
if (!isObject(value) || !Array.isArray(value.items))
|
|
491
|
+
throw contractViolation("object_with_items_array");
|
|
492
|
+
const nextCursor = optionalString(value, "next_cursor");
|
|
493
|
+
return Object.freeze({
|
|
494
|
+
items: Object.freeze(value.items.map((item, index) => underField(`items[${index}]`, () => decodeAgentSession(item)))),
|
|
495
|
+
...(nextCursor === undefined ? {} : { nextCursor }),
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
export function decodeAgentSessionItem(value) {
|
|
499
|
+
return decodeAgentSession(value);
|
|
500
|
+
}
|
|
501
|
+
export function decodeAgentSessionAuth(value) {
|
|
502
|
+
if (!isObject(value))
|
|
503
|
+
throw contractViolation("object");
|
|
504
|
+
const allowed = new Set([
|
|
505
|
+
"observation_id",
|
|
506
|
+
"agent_session_id",
|
|
507
|
+
"agent",
|
|
508
|
+
"process_epoch",
|
|
509
|
+
"auth_mode",
|
|
510
|
+
"agent_version",
|
|
511
|
+
"adapter_version",
|
|
512
|
+
"evidence_class",
|
|
513
|
+
"observed_at",
|
|
514
|
+
"valid_until",
|
|
515
|
+
"state",
|
|
516
|
+
]);
|
|
517
|
+
if (Object.keys(value).some((key) => !allowed.has(key))) {
|
|
518
|
+
throw contractViolation("no_unknown_fields");
|
|
519
|
+
}
|
|
520
|
+
const processEpoch = value.process_epoch;
|
|
521
|
+
if (processEpoch !== null && (typeof processEpoch !== "string" || !UUID.test(processEpoch))) {
|
|
522
|
+
throw contractViolation("canonical_uuid_or_null", "process_epoch");
|
|
523
|
+
}
|
|
524
|
+
const observedAt = requiredString(value, "observed_at");
|
|
525
|
+
const validUntil = requiredString(value, "valid_until");
|
|
526
|
+
const observedTime = Date.parse(observedAt);
|
|
527
|
+
const validUntilTime = Date.parse(validUntil);
|
|
528
|
+
if (!Number.isFinite(observedTime) ||
|
|
529
|
+
!Number.isFinite(validUntilTime) ||
|
|
530
|
+
validUntilTime < observedTime ||
|
|
531
|
+
validUntilTime - observedTime > AGENT_SESSION_AUTH_MAX_TTL_MS) {
|
|
532
|
+
throw contractViolation("bounded_observation_freshness");
|
|
533
|
+
}
|
|
534
|
+
const authMode = enumField(value, "auth_mode", AUTH_MODES);
|
|
535
|
+
const agentVersion = requiredDisplayString(value, "agent_version");
|
|
536
|
+
const adapterVersion = requiredDisplayString(value, "adapter_version");
|
|
537
|
+
if (adapterVersion !== AGENT_SESSION_AUTH_ADAPTER_VERSION) {
|
|
538
|
+
throw contractViolation("supported_adapter_version", "adapter_version");
|
|
539
|
+
}
|
|
540
|
+
const evidenceClass = enumField(value, "evidence_class", AGENT_AUTH_EVIDENCE_CLASSES);
|
|
541
|
+
const state = enumField(value, "state", AGENT_AUTH_STATES);
|
|
542
|
+
const unavailable = state === "unavailable";
|
|
543
|
+
const providerCredentialPresence = value.agent === "opencode" &&
|
|
544
|
+
authMode === "interactive_login" &&
|
|
545
|
+
evidenceClass === "provider_cli_credential_presence" &&
|
|
546
|
+
(state === "login_required" || state === "configured");
|
|
547
|
+
const providerLoginStatus = value.agent === "claude-code" &&
|
|
548
|
+
authMode === "interactive_login" &&
|
|
549
|
+
evidenceClass === "provider_cli_login_status" &&
|
|
550
|
+
(state === "login_required" || state === "authenticated");
|
|
551
|
+
const credentialBindingAuthority = (value.agent === "claude-code" || value.agent === "codex" || value.agent === "openclaw") &&
|
|
552
|
+
authMode === "credential_binding" &&
|
|
553
|
+
evidenceClass === "credential_binding_authority" &&
|
|
554
|
+
state === "configured";
|
|
555
|
+
if ((!unavailable && processEpoch === null) ||
|
|
556
|
+
(!unavailable && validUntilTime === observedTime) ||
|
|
557
|
+
(!unavailable && !AGENT_AUTH_VERSION.test(agentVersion)) ||
|
|
558
|
+
(!unavailable && !(providerCredentialPresence || providerLoginStatus || credentialBindingAuthority)) ||
|
|
559
|
+
(unavailable !== (evidenceClass === "insufficient")) ||
|
|
560
|
+
(unavailable && validUntilTime !== observedTime) ||
|
|
561
|
+
(agentVersion === "unavailable" && !unavailable)) {
|
|
562
|
+
throw contractViolation("self_consistent_authentication_evidence");
|
|
563
|
+
}
|
|
564
|
+
return Object.freeze({
|
|
565
|
+
observationId: canonicalUuid(value, "observation_id"),
|
|
566
|
+
agentSessionId: canonicalUuid(value, "agent_session_id"),
|
|
567
|
+
agent: enumField(value, "agent", AGENTS),
|
|
568
|
+
processEpoch,
|
|
569
|
+
authMode,
|
|
570
|
+
agentVersion,
|
|
571
|
+
adapterVersion,
|
|
572
|
+
evidenceClass,
|
|
573
|
+
observedAt,
|
|
574
|
+
validUntil,
|
|
575
|
+
state,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
export function decodeAgentSessionAuthLogout(value) {
|
|
579
|
+
if (!isObject(value))
|
|
580
|
+
throw contractViolation("object");
|
|
581
|
+
const allowed = new Set([
|
|
582
|
+
"observation_id", "agent_session_id", "process_epoch", "auth_mode", "agent",
|
|
583
|
+
"agent_version", "adapter_version", "observed_at", "outcome",
|
|
584
|
+
]);
|
|
585
|
+
if (Object.keys(value).some((key) => !allowed.has(key)) ||
|
|
586
|
+
value.auth_mode !== "interactive_login" ||
|
|
587
|
+
(value.agent !== "claude-code" && value.agent !== "codex") ||
|
|
588
|
+
typeof value.agent_version !== "string" ||
|
|
589
|
+
!AGENT_AUTH_VERSION.test(value.agent_version) ||
|
|
590
|
+
value.adapter_version !== AGENT_SESSION_AUTH_ADAPTER_VERSION ||
|
|
591
|
+
typeof value.observed_at !== "string" ||
|
|
592
|
+
!Number.isFinite(Date.parse(value.observed_at)) ||
|
|
593
|
+
value.outcome !== "logout_confirmed") {
|
|
594
|
+
throw contractViolation("sign_out_confirmation_shape");
|
|
595
|
+
}
|
|
596
|
+
return Object.freeze({
|
|
597
|
+
observationId: canonicalUuid(value, "observation_id"),
|
|
598
|
+
agentSessionId: canonicalUuid(value, "agent_session_id"),
|
|
599
|
+
processEpoch: canonicalUuid(value, "process_epoch"),
|
|
600
|
+
authMode: "interactive_login",
|
|
601
|
+
agent: value.agent,
|
|
602
|
+
agentVersion: value.agent_version,
|
|
603
|
+
adapterVersion: AGENT_SESSION_AUTH_ADAPTER_VERSION,
|
|
604
|
+
observedAt: value.observed_at,
|
|
605
|
+
outcome: "logout_confirmed",
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
export const TERMINAL_PROTOCOL = DEPLOYED_WIRE_COMPATIBILITY.terminalProtocol;
|
|
609
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
|
|
610
|
+
const TERMINAL_CAPABILITY_NAMES = new Set([
|
|
611
|
+
"acknowledgement",
|
|
612
|
+
"heartbeat",
|
|
613
|
+
"live_resize",
|
|
614
|
+
"resume",
|
|
615
|
+
"signals",
|
|
616
|
+
]);
|
|
617
|
+
const TERMINAL_CAPABILITY_AVAILABILITY = new Set([
|
|
618
|
+
"supported",
|
|
619
|
+
"unsupported",
|
|
620
|
+
"unknown",
|
|
621
|
+
]);
|
|
622
|
+
function canonicalUuid(value, key) {
|
|
623
|
+
const decoded = requiredString(value, key);
|
|
624
|
+
if (!UUID.test(decoded))
|
|
625
|
+
throw contractViolation("canonical_uuid", key);
|
|
626
|
+
return decoded;
|
|
627
|
+
}
|
|
628
|
+
function decodeTerminalCapability(value) {
|
|
629
|
+
if (!isObject(value))
|
|
630
|
+
throw contractViolation("object");
|
|
631
|
+
const name = requiredString(value, "name");
|
|
632
|
+
const availability = requiredString(value, "availability");
|
|
633
|
+
if (!TERMINAL_CAPABILITY_NAMES.has(name) ||
|
|
634
|
+
!TERMINAL_CAPABILITY_AVAILABILITY.has(availability) ||
|
|
635
|
+
Object.keys(value).some((key) => key !== "name" && key !== "availability")) {
|
|
636
|
+
throw contractViolation("terminal_capability_shape");
|
|
637
|
+
}
|
|
638
|
+
return Object.freeze({ name, availability });
|
|
639
|
+
}
|
|
640
|
+
export function decodeTerminalConnectionCancellation(value) {
|
|
641
|
+
if (!isObject(value) || value.cancelled !== true || Object.keys(value).some(key => key !== "cancelled"))
|
|
642
|
+
throw contractViolation("terminal_connection_cancellation");
|
|
643
|
+
return Object.freeze({ cancelled: true });
|
|
644
|
+
}
|
|
645
|
+
export function decodeTerminalConnectionGrant(value) {
|
|
646
|
+
if (!isObject(value))
|
|
647
|
+
throw contractViolation("object");
|
|
648
|
+
const allowed = new Set([
|
|
649
|
+
"terminal_session_id",
|
|
650
|
+
"resume_handle",
|
|
651
|
+
"connect_url",
|
|
652
|
+
"connect_token",
|
|
653
|
+
"protocol",
|
|
654
|
+
"capabilities",
|
|
655
|
+
"expires_at",
|
|
656
|
+
]);
|
|
657
|
+
if (Object.keys(value).some((key) => !allowed.has(key)) || !Array.isArray(value.capabilities)) {
|
|
658
|
+
throw contractViolation("no_unknown_fields");
|
|
659
|
+
}
|
|
660
|
+
const terminalSessionId = canonicalUuid(value, "terminal_session_id");
|
|
661
|
+
const resumeHandle = canonicalUuid(value, "resume_handle");
|
|
662
|
+
const connectUrl = requiredString(value, "connect_url");
|
|
663
|
+
const connectToken = requiredString(value, "connect_token");
|
|
664
|
+
const protocol = requiredString(value, "protocol");
|
|
665
|
+
const expiresAt = requiredString(value, "expires_at");
|
|
666
|
+
if (protocol !== TERMINAL_PROTOCOL ||
|
|
667
|
+
!isTerminalConnectToken(connectToken) ||
|
|
668
|
+
!isTerminalStreamUrl(connectUrl, terminalSessionId) ||
|
|
669
|
+
!Number.isFinite(Date.parse(expiresAt)) ||
|
|
670
|
+
value.capabilities.length !== TERMINAL_CAPABILITY_NAMES.size) {
|
|
671
|
+
throw contractViolation("terminal_grant_shape");
|
|
672
|
+
}
|
|
673
|
+
const capabilities = Object.freeze(value.capabilities.map((item, index) => underField(`capabilities[${index}]`, () => decodeTerminalCapability(item))));
|
|
674
|
+
if (new Set(capabilities.map((capability) => capability.name)).size !== TERMINAL_CAPABILITY_NAMES.size ||
|
|
675
|
+
[...TERMINAL_CAPABILITY_NAMES].some((name) => capabilities.filter((capability) => capability.name === name).length !== 1)) {
|
|
676
|
+
throw contractViolation("exactly_one_of_each_terminal_capability", "capabilities");
|
|
677
|
+
}
|
|
678
|
+
return Object.freeze({
|
|
679
|
+
terminalSessionId,
|
|
680
|
+
resumeHandle,
|
|
681
|
+
connectUrl,
|
|
682
|
+
connectToken,
|
|
683
|
+
protocol: TERMINAL_PROTOCOL,
|
|
684
|
+
capabilities,
|
|
685
|
+
expiresAt,
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Control and format characters may never reach the operator's terminal. The
|
|
690
|
+
* credential half of this guard is NOT written here: it comes from
|
|
691
|
+
* `containsCredentialValue`, the one authority, because the copy that used to
|
|
692
|
+
* live on this line knew only five of the eight minted families.
|
|
693
|
+
*/
|
|
694
|
+
const FORBIDDEN_PUBLIC_CHARACTER = /[\p{Cc}\p{Cf}]/u;
|
|
695
|
+
function exactKeys(value, required) {
|
|
696
|
+
const actual = Object.keys(value).sort();
|
|
697
|
+
const expected = [...required].sort();
|
|
698
|
+
if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
|
|
699
|
+
throw contractViolation("exact_key_set");
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function safePublicString(value, label, maximum = 4096) {
|
|
703
|
+
if (typeof value !== "string" ||
|
|
704
|
+
value.length > maximum ||
|
|
705
|
+
FORBIDDEN_PUBLIC_CHARACTER.test(value) ||
|
|
706
|
+
containsCredentialValue(value)) {
|
|
707
|
+
throw contractViolation("safe_public_string", label);
|
|
708
|
+
}
|
|
709
|
+
return value;
|
|
710
|
+
}
|
|
711
|
+
function decodeJsonValue(value, depth = 0) {
|
|
712
|
+
if (depth > 12)
|
|
713
|
+
throw contractViolation("bounded_nesting_depth");
|
|
714
|
+
if (value === null || typeof value === "boolean")
|
|
715
|
+
return value;
|
|
716
|
+
if (typeof value === "number") {
|
|
717
|
+
if (!Number.isFinite(value))
|
|
718
|
+
throw contractViolation("finite_number");
|
|
719
|
+
return value;
|
|
720
|
+
}
|
|
721
|
+
if (typeof value === "string")
|
|
722
|
+
return safePublicString(value, "detail", 16_384);
|
|
723
|
+
if (Array.isArray(value)) {
|
|
724
|
+
if (value.length > 1024)
|
|
725
|
+
throw contractViolation("bounded_array_length");
|
|
726
|
+
return Object.freeze(value.map((item) => decodeJsonValue(item, depth + 1)));
|
|
727
|
+
}
|
|
728
|
+
if (!isObject(value) || Object.keys(value).length > 1024) {
|
|
729
|
+
throw contractViolation("bounded_object_size");
|
|
730
|
+
}
|
|
731
|
+
const decoded = {};
|
|
732
|
+
for (const [key, item] of Object.entries(value)) {
|
|
733
|
+
const safeKey = safePublicString(key, "detail key", 256);
|
|
734
|
+
decoded[safeKey] = decodeJsonValue(item, depth + 1);
|
|
735
|
+
}
|
|
736
|
+
return Object.freeze(decoded);
|
|
737
|
+
}
|
|
738
|
+
function decodeAuditRecord(value) {
|
|
739
|
+
if (!isObject(value))
|
|
740
|
+
throw contractViolation("object");
|
|
741
|
+
exactKeys(value, ["id", "session_id", "kind", "summary", "detail", "created_at"]);
|
|
742
|
+
const createdAt = safePublicString(value.created_at, "created_at", 64);
|
|
743
|
+
if (!Number.isFinite(Date.parse(createdAt)))
|
|
744
|
+
throw contractViolation("parsable_timestamp", "created_at");
|
|
745
|
+
return Object.freeze({
|
|
746
|
+
id: canonicalUuid(value, "id"),
|
|
747
|
+
machineId: canonicalUuid(value, "session_id"),
|
|
748
|
+
kind: safePublicString(value.kind, "kind", 128),
|
|
749
|
+
summary: safePublicString(value.summary, "summary", 2048),
|
|
750
|
+
detail: decodeJsonValue(value.detail),
|
|
751
|
+
createdAt,
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
export function decodeAuditRecords(value) {
|
|
755
|
+
if (!Array.isArray(value) || value.length > 200)
|
|
756
|
+
throw contractViolation("bounded_array_length");
|
|
757
|
+
return Object.freeze(value.map((item, index) => underField(`[${index}]`, () => decodeAuditRecord(item))));
|
|
758
|
+
}
|
|
759
|
+
function injectionName(value, label, maximum) {
|
|
760
|
+
const text = safePublicString(value, label, maximum);
|
|
761
|
+
if (text.length === 0)
|
|
762
|
+
throw contractViolation("nonempty_string", label);
|
|
763
|
+
return text;
|
|
764
|
+
}
|
|
765
|
+
function injectionTemplate(value) {
|
|
766
|
+
if (typeof value !== "string" || value.length > 4096)
|
|
767
|
+
throw contractViolation("bounded_string", "value_template");
|
|
768
|
+
// Templates are opaque metadata, including multiline file content. Preserve
|
|
769
|
+
// whitespace without interpreting interpolation; reject terminal controls and
|
|
770
|
+
// known credential values. Human rendering must quote this string.
|
|
771
|
+
safePublicString(value.replace(/[\r\n\t]/gu, ""), "value_template", 4096);
|
|
772
|
+
return value;
|
|
773
|
+
}
|
|
774
|
+
function injectionArray(value, label, decode) {
|
|
775
|
+
if (!Array.isArray(value) || value.length > 64)
|
|
776
|
+
throw contractViolation("bounded_array_length", label);
|
|
777
|
+
return Object.freeze(value.map((item, index) => underField(`${label}[${index}]`, () => decode(item))));
|
|
778
|
+
}
|
|
779
|
+
export function decodeMachineAuthorizations(value) {
|
|
780
|
+
if (!isObject(value))
|
|
781
|
+
throw contractViolation("object");
|
|
782
|
+
exactKeys(value, ["revision", "secret_configuration"]);
|
|
783
|
+
if (typeof value.revision !== "number" || !Number.isSafeInteger(value.revision) || value.revision < 1)
|
|
784
|
+
throw contractViolation("positive_safe_integer", "revision");
|
|
785
|
+
return Object.freeze({ revision: value.revision, secret_configuration: injectionArray(value.secret_configuration, "secret_configuration", (entry) => {
|
|
786
|
+
if (!isObject(entry))
|
|
787
|
+
throw contractViolation("object");
|
|
788
|
+
exactKeys(entry, ["secret_id", "environment", "egress_rules", "files"]);
|
|
789
|
+
return Object.freeze({
|
|
790
|
+
secret_id: canonicalUuid(entry, "secret_id"),
|
|
791
|
+
environment: injectionArray(entry.environment, "environment", (item) => {
|
|
792
|
+
if (!isObject(item))
|
|
793
|
+
throw contractViolation("object");
|
|
794
|
+
exactKeys(item, ["name", "value_template"]);
|
|
795
|
+
return Object.freeze({ name: injectionName(item.name, "name", 256), value_template: injectionTemplate(item.value_template) });
|
|
796
|
+
}),
|
|
797
|
+
egress_rules: injectionArray(entry.egress_rules, "egress_rules", (item) => {
|
|
798
|
+
if (!isObject(item))
|
|
799
|
+
throw contractViolation("object");
|
|
800
|
+
exactKeys(item, ["host_pattern", "action", "name", "value_template", ...(Object.hasOwn(item, "path_pattern") ? ["path_pattern"] : [])]);
|
|
801
|
+
if (item.action !== "header" && item.action !== "query")
|
|
802
|
+
throw contractViolation("known_injection_action", "action");
|
|
803
|
+
return Object.freeze({ host_pattern: injectionName(item.host_pattern, "host_pattern", 253), action: item.action,
|
|
804
|
+
name: injectionName(item.name, "name", 256), value_template: injectionTemplate(item.value_template),
|
|
805
|
+
...(Object.hasOwn(item, "path_pattern") ? { path_pattern: item.path_pattern === null ? null : safePublicString(item.path_pattern, "path_pattern", 4096) } : {}) });
|
|
806
|
+
}),
|
|
807
|
+
files: injectionArray(entry.files, "files", (item) => {
|
|
808
|
+
if (!isObject(item))
|
|
809
|
+
throw contractViolation("object");
|
|
810
|
+
exactKeys(item, ["path", "value_template"]);
|
|
811
|
+
return Object.freeze({ path: injectionName(item.path, "path", 4096), value_template: injectionTemplate(item.value_template) });
|
|
812
|
+
}),
|
|
813
|
+
});
|
|
814
|
+
}) });
|
|
815
|
+
}
|
|
816
|
+
function optionalTimestamp(value, label) {
|
|
817
|
+
if (value === null)
|
|
818
|
+
return null;
|
|
819
|
+
const decoded = safePublicString(value, label, 64);
|
|
820
|
+
if (!Number.isFinite(Date.parse(decoded)))
|
|
821
|
+
throw contractViolation("parsable_timestamp", label);
|
|
822
|
+
return decoded;
|
|
823
|
+
}
|
|
824
|
+
function decodeApiKeyMetadata(value) {
|
|
825
|
+
if (!isObject(value))
|
|
826
|
+
throw contractViolation("object");
|
|
827
|
+
exactKeys(value, [
|
|
828
|
+
"id", "name", "prefix", "last_four", "created_at", "expires_at", "last_used_at", "revoked_at",
|
|
829
|
+
]);
|
|
830
|
+
const prefix = safePublicString(value.prefix, "prefix", 32);
|
|
831
|
+
const lastFour = safePublicString(value.last_four, "last_four", 4);
|
|
832
|
+
if (!isApiKeyDisplayPrefix(prefix) || !/^[A-Za-z0-9_-]{4}$/u.test(lastFour)) {
|
|
833
|
+
throw contractViolation("api_key_display_metadata");
|
|
834
|
+
}
|
|
835
|
+
const createdAt = optionalTimestamp(value.created_at, "created_at");
|
|
836
|
+
if (createdAt === null)
|
|
837
|
+
throw contractViolation("parsable_timestamp", "created_at");
|
|
838
|
+
return Object.freeze({
|
|
839
|
+
id: canonicalUuid(value, "id"),
|
|
840
|
+
name: safePublicString(value.name, "name", 80),
|
|
841
|
+
prefix,
|
|
842
|
+
lastFour,
|
|
843
|
+
createdAt,
|
|
844
|
+
expiresAt: optionalTimestamp(value.expires_at, "expires_at"),
|
|
845
|
+
lastUsedAt: optionalTimestamp(value.last_used_at, "last_used_at"),
|
|
846
|
+
revokedAt: optionalTimestamp(value.revoked_at, "revoked_at"),
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
export function decodeApiKeyList(value) {
|
|
850
|
+
if (!Array.isArray(value) || value.length > 100)
|
|
851
|
+
throw contractViolation("bounded_array_length");
|
|
852
|
+
return Object.freeze(value.map((item, index) => underField(`[${index}]`, () => decodeApiKeyMetadata(item))));
|
|
853
|
+
}
|
|
854
|
+
export function decodeApiKeyCreation(value) {
|
|
855
|
+
if (!isObject(value))
|
|
856
|
+
throw contractViolation("object");
|
|
857
|
+
if (typeof value.idempotency_replayed !== "boolean") {
|
|
858
|
+
throw contractViolation("boolean", "idempotency_replayed");
|
|
859
|
+
}
|
|
860
|
+
exactKeys(value, [
|
|
861
|
+
"id", "name", "prefix", "last_four", "created_at", "expires_at", "last_used_at", "revoked_at",
|
|
862
|
+
"idempotency_replayed", ...(value.idempotency_replayed ? [] : ["key"]),
|
|
863
|
+
]);
|
|
864
|
+
if (!value.idempotency_replayed && (typeof value.key !== "string" || !isSecretApiKey(value.key))) {
|
|
865
|
+
throw contractViolation("one_time_api_key");
|
|
866
|
+
}
|
|
867
|
+
const { key, idempotency_replayed: idempotencyReplayed, ...metadataValue } = value;
|
|
868
|
+
const metadata = decodeApiKeyMetadata(metadataValue);
|
|
869
|
+
if (typeof key === "string" && (!key.startsWith(metadata.prefix) || !key.endsWith(metadata.lastFour))) {
|
|
870
|
+
throw contractViolation("api_key_secret_metadata_binding");
|
|
871
|
+
}
|
|
872
|
+
return idempotencyReplayed
|
|
873
|
+
? Object.freeze({ ...metadata, idempotencyReplayed: true })
|
|
874
|
+
: Object.freeze({ ...metadata, idempotencyReplayed: false, key: key });
|
|
875
|
+
}
|
|
876
|
+
export function decodeTerminalWriterState(value) {
|
|
877
|
+
if (!isObject(value))
|
|
878
|
+
throw contractViolation("object");
|
|
879
|
+
exactKeys(value, ["agent_session_id", "process_epoch", "writer_epoch", "writer_client_instance_id", "transfer_pending", "operation_id", "operation_state"]);
|
|
880
|
+
const agentSessionId = canonicalUuid(value, "agent_session_id");
|
|
881
|
+
const processEpoch = canonicalUuid(value, "process_epoch");
|
|
882
|
+
const operationId = canonicalUuid(value, "operation_id");
|
|
883
|
+
if (value.operation_state !== "committed")
|
|
884
|
+
throw contractViolation("terminal_writer_operation_state");
|
|
885
|
+
if (!Number.isSafeInteger(value.writer_epoch) || Number(value.writer_epoch) < 1 ||
|
|
886
|
+
typeof value.writer_client_instance_id !== "string" ||
|
|
887
|
+
!/^[A-Za-z0-9._:-]{1,256}$/u.test(value.writer_client_instance_id) ||
|
|
888
|
+
typeof value.transfer_pending !== "boolean")
|
|
889
|
+
throw contractViolation("terminal_writer_state_shape");
|
|
890
|
+
return Object.freeze({
|
|
891
|
+
operationId,
|
|
892
|
+
operationState: "committed",
|
|
893
|
+
agentSessionId,
|
|
894
|
+
processEpoch,
|
|
895
|
+
writerEpoch: Number(value.writer_epoch),
|
|
896
|
+
writerClientInstanceId: value.writer_client_instance_id,
|
|
897
|
+
transferPending: value.transfer_pending,
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
const TERMINAL_SEAT_STATES = new Set([
|
|
901
|
+
"available",
|
|
902
|
+
"owner_unrecoverable",
|
|
903
|
+
"none",
|
|
904
|
+
]);
|
|
905
|
+
const CLIENT_INSTANCE_ID = /^[A-Za-z0-9._:-]{1,256}$/u;
|
|
906
|
+
export function decodeAgentSessionTerminalSeat(value) {
|
|
907
|
+
if (!isObject(value))
|
|
908
|
+
throw contractViolation("object");
|
|
909
|
+
exactKeys(value, [
|
|
910
|
+
"agent_session_id",
|
|
911
|
+
"process_epoch",
|
|
912
|
+
"state",
|
|
913
|
+
"unavailable_reason",
|
|
914
|
+
"writer_epoch",
|
|
915
|
+
"writer_client_instance_id",
|
|
916
|
+
"writer_attached",
|
|
917
|
+
"writer_attached_at",
|
|
918
|
+
"writer_detached_at",
|
|
919
|
+
"observed_at",
|
|
920
|
+
]);
|
|
921
|
+
const agentSessionId = canonicalUuid(value, "agent_session_id");
|
|
922
|
+
if (value.process_epoch !== null && (typeof value.process_epoch !== "string" || !UUID.test(value.process_epoch))) {
|
|
923
|
+
throw contractViolation("canonical_uuid_or_null", "process_epoch");
|
|
924
|
+
}
|
|
925
|
+
const state = enumField(value, "state", TERMINAL_SEAT_STATES);
|
|
926
|
+
if (value.unavailable_reason !== null &&
|
|
927
|
+
(typeof value.unavailable_reason !== "string" || value.unavailable_reason.length > 4096)) {
|
|
928
|
+
throw contractViolation("string_or_null", "unavailable_reason");
|
|
929
|
+
}
|
|
930
|
+
if (!Number.isSafeInteger(value.writer_epoch) || Number(value.writer_epoch) < 0) {
|
|
931
|
+
throw contractViolation("non_negative_integer", "writer_epoch");
|
|
932
|
+
}
|
|
933
|
+
if (value.writer_client_instance_id !== null &&
|
|
934
|
+
(typeof value.writer_client_instance_id !== "string" || !CLIENT_INSTANCE_ID.test(value.writer_client_instance_id))) {
|
|
935
|
+
throw contractViolation("client_instance_id_or_null", "writer_client_instance_id");
|
|
936
|
+
}
|
|
937
|
+
if (typeof value.writer_attached !== "boolean") {
|
|
938
|
+
throw contractViolation("boolean", "writer_attached");
|
|
939
|
+
}
|
|
940
|
+
// An unheld seat cannot have an attached writer, and a seat nobody holds
|
|
941
|
+
// must not carry attachment timestamps: the two facts come from different
|
|
942
|
+
// rows, so their disagreement is a producer defect, not a state.
|
|
943
|
+
if (value.writer_client_instance_id === null && value.writer_attached === true) {
|
|
944
|
+
throw contractViolation("writer_attached_without_writer", "writer_attached");
|
|
945
|
+
}
|
|
946
|
+
for (const key of ["writer_attached_at", "writer_detached_at"]) {
|
|
947
|
+
const at = value[key];
|
|
948
|
+
if (at !== null && (typeof at !== "string" || !Number.isFinite(Date.parse(at)))) {
|
|
949
|
+
throw contractViolation("timestamp_or_null", key);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
const observedAt = requiredString(value, "observed_at");
|
|
953
|
+
if (!Number.isFinite(Date.parse(observedAt)))
|
|
954
|
+
throw contractViolation("timestamp", "observed_at");
|
|
955
|
+
return Object.freeze({
|
|
956
|
+
agentSessionId,
|
|
957
|
+
processEpoch: value.process_epoch,
|
|
958
|
+
state,
|
|
959
|
+
unavailableReason: value.unavailable_reason,
|
|
960
|
+
writerEpoch: Number(value.writer_epoch),
|
|
961
|
+
writerClientInstanceId: value.writer_client_instance_id,
|
|
962
|
+
writerAttached: value.writer_attached,
|
|
963
|
+
writerAttachedAt: value.writer_attached_at,
|
|
964
|
+
writerDetachedAt: value.writer_detached_at,
|
|
965
|
+
observedAt,
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
export function decodeOk(value) {
|
|
969
|
+
if (!isObject(value))
|
|
970
|
+
throw contractViolation("object");
|
|
971
|
+
exactKeys(value, ["ok"]);
|
|
972
|
+
if (value.ok !== true)
|
|
973
|
+
throw contractViolation("acknowledgement_is_true", "ok");
|
|
974
|
+
return true;
|
|
975
|
+
}
|
|
976
|
+
//# sourceMappingURL=contracts.js.map
|