@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,937 @@
|
|
|
1
|
+
import { providerSessionBody, decodeProviderPresets, decodeProviderObservation, decodeProviderSession } from "./provider-v2.js";
|
|
2
|
+
import { EXIT_CODES, CunaError, usageError } from "../core/errors.js";
|
|
3
|
+
import { MACHINE_CREATE_REQUEST_BUDGET_MS, MACHINE_LIFECYCLE_REQUEST_BUDGET_MS, SUPERVISOR_LIVE_UPDATE_REQUEST_BUDGET_MS, } from "../core/observation-budget.js";
|
|
4
|
+
import { OFF_CONTRACT_RESPONSE_HINT } from "../core/product-web.js";
|
|
5
|
+
import { ContractViolation, assertCanonicalUuid, assertIdempotencyKey, assertSafeDisplayText, contractViolation, encodeCanonicalUuid, encodeMachineId, } from "../core/validation.js";
|
|
6
|
+
import { decodeAuditRecords, decodeAgentSessionAuth, decodeAgentSessionAuthLogout, decodeAgentSessionItem, decodeAgentSessionPage, decodeAgentSessionTerminalSeat, decodeApiKeyList, decodeApiKeyCreation, decodeCapabilitySnapshot, decodeMachineAuthorizations, decodeMachineItem, decodeMachineCreateRequest, decodeMachinePage, decodeOk, decodeCunaIdentity, decodeTerminalConnectionGrant, decodeTerminalConnectionCancellation, decodeTerminalWriterState, decodeWorkspaceBindingAuthority, TERMINAL_PROTOCOL, } from "./contracts.js";
|
|
7
|
+
import { decodeSupervisorLiveUpdate, decodeSupervisorLiveUpdateOperation, } from "./supervisor-live-update.js";
|
|
8
|
+
import { decodeExecutionWorkspacePage } from "./execution-workspaces.js";
|
|
9
|
+
import { decodeManagedExecution, decodeManagedExecutionPage } from "./managed-executions.js";
|
|
10
|
+
import { decodeManagedCommandResult } from "./managed-executions.js";
|
|
11
|
+
import { decodeMachineDefaultWorkspace, decodeAgentSessionWorkspaceContext, decodeAgentSessionWorkspaceEnvelope } from "./remote-workspace.js";
|
|
12
|
+
import { classifyCapabilitySnapshot, isPermanentSnapshotFault } from "./capability-evidence.js";
|
|
13
|
+
/**
|
|
14
|
+
* `${method} ${path}` for the request that produced a body.
|
|
15
|
+
*
|
|
16
|
+
* Derived from the request object that was actually dispatched, never written
|
|
17
|
+
* beside it, so the operation the error names and the operation the transport
|
|
18
|
+
* sent cannot disagree. The path may carry identifiers, but only ones the caller
|
|
19
|
+
* supplied in this same invocation — no response value ever reaches here.
|
|
20
|
+
*/
|
|
21
|
+
function operationLabel(request) {
|
|
22
|
+
return `${request.method} ${request.path}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build the malformed-response error, preserving what the decoder knew.
|
|
26
|
+
*
|
|
27
|
+
* WHAT `details` MAY CARRY. `operation`, `field` and `predicate` — a request
|
|
28
|
+
* label the CLI built, a key path the CLI asked for, and a token from this
|
|
29
|
+
* source tree. No response value, no fragment of one, and not its length: a
|
|
30
|
+
* `/v1/me` body holds an email address and an `/v1/api-keys` body holds key
|
|
31
|
+
* metadata, so echoing "what we got" would turn a diagnostic into a disclosure.
|
|
32
|
+
* That is why the decoders report a PREDICATE and not a comparison.
|
|
33
|
+
*/
|
|
34
|
+
function malformed(cause, operation) {
|
|
35
|
+
const violation = cause instanceof ContractViolation ? cause : undefined;
|
|
36
|
+
return new CunaError({
|
|
37
|
+
code: "cuna.remote.malformed_response",
|
|
38
|
+
message: "Cuna returned a response that does not match the public contract.",
|
|
39
|
+
exitCode: EXIT_CODES.remote,
|
|
40
|
+
hint: OFF_CONTRACT_RESPONSE_HINT,
|
|
41
|
+
details: {
|
|
42
|
+
operation,
|
|
43
|
+
...(violation?.field === undefined ? {} : { field: violation.field }),
|
|
44
|
+
// A non-`ContractViolation` cause is a decoder that has not been converted
|
|
45
|
+
// or a genuine bug; it is reported as such rather than guessed at.
|
|
46
|
+
predicate: violation?.predicate ?? "contract_decode_failed",
|
|
47
|
+
},
|
|
48
|
+
cause,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function decode(decoder, value, operation) {
|
|
52
|
+
try {
|
|
53
|
+
return decoder(value);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (error instanceof CunaError)
|
|
57
|
+
throw error;
|
|
58
|
+
throw malformed(error, operation);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function assertAgentSessionBinding(session, expected, operation) {
|
|
62
|
+
const mismatch = expected.id !== undefined && session.id !== expected.id
|
|
63
|
+
? "id"
|
|
64
|
+
: expected.machineId !== undefined && session.machineId !== expected.machineId
|
|
65
|
+
? "machine_id"
|
|
66
|
+
: expected.workspaceBindingId !== undefined &&
|
|
67
|
+
session.workspaceBindingId !== expected.workspaceBindingId
|
|
68
|
+
? "workspace_binding_id"
|
|
69
|
+
: expected.workspaceGeneration !== undefined &&
|
|
70
|
+
session.workspaceGeneration !== expected.workspaceGeneration
|
|
71
|
+
? "workspace_generation"
|
|
72
|
+
: undefined;
|
|
73
|
+
if (mismatch !== undefined) {
|
|
74
|
+
throw malformed(contractViolation("matches_requested_resource", mismatch), operation);
|
|
75
|
+
}
|
|
76
|
+
return session;
|
|
77
|
+
}
|
|
78
|
+
function containsAsciiControl(value) {
|
|
79
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
80
|
+
const code = value.charCodeAt(index);
|
|
81
|
+
if (code <= 0x1f || code === 0x7f)
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function validatePageOptions(options, resource = "AgentSession") {
|
|
87
|
+
if (options.limit !== undefined &&
|
|
88
|
+
(!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100)) {
|
|
89
|
+
throw new CunaError({
|
|
90
|
+
code: "cuna.usage.invalid",
|
|
91
|
+
message: `${resource} page limit must be an integer from 1 through 100.`,
|
|
92
|
+
exitCode: EXIT_CODES.usage,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (options.cursor !== undefined &&
|
|
96
|
+
(options.cursor.length < 1 || options.cursor.length > 512 || containsAsciiControl(options.cursor))) {
|
|
97
|
+
throw new CunaError({
|
|
98
|
+
code: "cuna.usage.invalid",
|
|
99
|
+
message: `${resource} cursor is malformed.`,
|
|
100
|
+
exitCode: EXIT_CODES.usage,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return Object.freeze({
|
|
104
|
+
...(options.limit === undefined ? {} : { limit: String(options.limit) }),
|
|
105
|
+
...(options.cursor === undefined ? {} : { cursor: options.cursor }),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function validateAgentSessionCreate(input) {
|
|
109
|
+
if (!Number.isSafeInteger(input.workspaceGeneration) || input.workspaceGeneration < 1) {
|
|
110
|
+
throw new CunaError({
|
|
111
|
+
code: "cuna.usage.invalid",
|
|
112
|
+
message: "AgentSession workspace generation must be a positive safe integer.",
|
|
113
|
+
exitCode: EXIT_CODES.usage,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (input.name !== undefined && (input.name.length < 1 || input.name.length > 80)) {
|
|
117
|
+
throw new CunaError({
|
|
118
|
+
code: "cuna.usage.invalid",
|
|
119
|
+
message: "AgentSession name must contain 1 through 80 characters.",
|
|
120
|
+
exitCode: EXIT_CODES.usage,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (!input.cwd.startsWith("/workspace") ||
|
|
124
|
+
(input.cwd !== "/workspace" && !input.cwd.startsWith("/workspace/")) ||
|
|
125
|
+
input.cwd.length > 1024 ||
|
|
126
|
+
input.cwd.split("/").includes("..")) {
|
|
127
|
+
throw new CunaError({
|
|
128
|
+
code: "cuna.usage.invalid",
|
|
129
|
+
message: "AgentSession cwd must be a safe absolute path inside /workspace.",
|
|
130
|
+
exitCode: EXIT_CODES.usage,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (input.agent === "opencode" &&
|
|
134
|
+
(input.authMode !== "interactive_login" || input.credentialBindingId !== undefined)) {
|
|
135
|
+
throw new CunaError({
|
|
136
|
+
code: "cuna.usage.invalid",
|
|
137
|
+
message: "OpenCode AgentSessions require interactive_login and do not accept a credential binding.",
|
|
138
|
+
exitCode: EXIT_CODES.usage,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (input.authMode === "credential_binding" && input.credentialBindingId === undefined) {
|
|
142
|
+
throw new CunaError({
|
|
143
|
+
code: "cuna.usage.invalid",
|
|
144
|
+
message: "credential_binding auth mode requires a credential binding ID.",
|
|
145
|
+
exitCode: EXIT_CODES.usage,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (input.authMode !== "credential_binding" && input.credentialBindingId !== undefined) {
|
|
149
|
+
throw new CunaError({
|
|
150
|
+
code: "cuna.usage.invalid",
|
|
151
|
+
message: "A credential binding ID requires credential_binding auth mode.",
|
|
152
|
+
exitCode: EXIT_CODES.usage,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (input.credentialBindingId !== undefined) {
|
|
156
|
+
assertCanonicalUuid(input.credentialBindingId, "credential binding ID");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function validateMachineCreate(input, idempotencyKey) {
|
|
160
|
+
assertIdempotencyKey(idempotencyKey);
|
|
161
|
+
assertSafeDisplayText(input.name, "machine name");
|
|
162
|
+
if (input.name.length < 1 || input.name.length > 80) {
|
|
163
|
+
throw new CunaError({
|
|
164
|
+
code: "cuna.usage.invalid",
|
|
165
|
+
message: "Machine name must contain 1 through 80 characters.",
|
|
166
|
+
exitCode: EXIT_CODES.usage,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (input.vcpus !== undefined && (!Number.isInteger(input.vcpus) || input.vcpus < 1 || input.vcpus > 8)) {
|
|
170
|
+
throw new CunaError({
|
|
171
|
+
code: "cuna.usage.invalid",
|
|
172
|
+
message: "Machine vcpus must be an integer from 1 through 8.",
|
|
173
|
+
exitCode: EXIT_CODES.usage,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (input.memoryMiB !== undefined &&
|
|
177
|
+
(!Number.isInteger(input.memoryMiB) || input.memoryMiB < 512 || input.memoryMiB > 16_384)) {
|
|
178
|
+
throw new CunaError({
|
|
179
|
+
code: "cuna.usage.invalid",
|
|
180
|
+
message: "Machine memoryMiB must be an integer from 512 through 16384.",
|
|
181
|
+
exitCode: EXIT_CODES.usage,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function validateWorkspaceBindingIdentity(input) {
|
|
186
|
+
if (input.executionWorkspaceId !== undefined)
|
|
187
|
+
assertCanonicalUuid(input.executionWorkspaceId, "execution workspace ID");
|
|
188
|
+
assertCanonicalUuid(input.workspaceId, "workspace ID");
|
|
189
|
+
assertCanonicalUuid(input.projectId, "project ID");
|
|
190
|
+
assertCanonicalUuid(input.localInstanceId, "local instance ID");
|
|
191
|
+
assertCanonicalUuid(input.machineId, "machine ID");
|
|
192
|
+
if (!/^[0-9a-f]{64}$/u.test(input.exclusionPolicyDigest)) {
|
|
193
|
+
throw new CunaError({
|
|
194
|
+
code: "cuna.usage.invalid",
|
|
195
|
+
message: "Workspace exclusion policy digest must be a lowercase SHA-256 digest.",
|
|
196
|
+
exitCode: EXIT_CODES.usage,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function workspaceBindingIdentityMatches(actual, expected) {
|
|
201
|
+
return actual.workspaceId === expected.workspaceId &&
|
|
202
|
+
(expected.executionWorkspaceId === undefined || actual.executionWorkspaceId === expected.executionWorkspaceId) &&
|
|
203
|
+
actual.projectId === expected.projectId &&
|
|
204
|
+
actual.localInstanceId === expected.localInstanceId &&
|
|
205
|
+
actual.machineId === expected.machineId &&
|
|
206
|
+
actual.exclusionPolicyDigest === expected.exclusionPolicyDigest;
|
|
207
|
+
}
|
|
208
|
+
export function createCunaApiClient(transport) {
|
|
209
|
+
/**
|
|
210
|
+
* Dispatch one request and decode its body under that request's identity.
|
|
211
|
+
*
|
|
212
|
+
* Every decode in this client goes through here, so an off-contract body can
|
|
213
|
+
* no longer produce an error that fails to say which operation produced it.
|
|
214
|
+
* Passing the operation as a second literal beside each call was the obvious
|
|
215
|
+
* alternative and was rejected: it is a second authority for a fact the
|
|
216
|
+
* request object already holds, and it would drift on the first path edit.
|
|
217
|
+
*/
|
|
218
|
+
async function fetchDecoded(request, decoder) {
|
|
219
|
+
return decode(decoder, await transport.request(request), operationLabel(request));
|
|
220
|
+
}
|
|
221
|
+
const client = {
|
|
222
|
+
async getIdentity(signal) {
|
|
223
|
+
return fetchDecoded({ method: "GET", path: "/v1/me", ...(signal === undefined ? {} : { signal }) }, decodeCunaIdentity);
|
|
224
|
+
},
|
|
225
|
+
async discoverCapabilities(scope, resourceId, signal) {
|
|
226
|
+
return fetchDecoded({
|
|
227
|
+
method: "GET",
|
|
228
|
+
path: "/v1/capabilities",
|
|
229
|
+
query: { scope, resource_id: resourceId },
|
|
230
|
+
...(signal === undefined ? {} : { signal }),
|
|
231
|
+
}, decodeCapabilitySnapshot);
|
|
232
|
+
},
|
|
233
|
+
async listMachines(signal) {
|
|
234
|
+
return fetchDecoded({
|
|
235
|
+
method: "GET",
|
|
236
|
+
path: "/v1/sessions",
|
|
237
|
+
...(signal === undefined ? {} : { signal }),
|
|
238
|
+
}, decodeMachinePage);
|
|
239
|
+
},
|
|
240
|
+
async getMachine(id, signal) {
|
|
241
|
+
const safeId = encodeMachineId(id);
|
|
242
|
+
const request = {
|
|
243
|
+
method: "GET",
|
|
244
|
+
path: `/v1/sessions/${safeId}`,
|
|
245
|
+
...(signal === undefined ? {} : { signal }),
|
|
246
|
+
};
|
|
247
|
+
const machine = await fetchDecoded(request, decodeMachineItem);
|
|
248
|
+
if (machine.id !== id) {
|
|
249
|
+
throw malformed(contractViolation("matches_requested_resource", "id"), operationLabel(request));
|
|
250
|
+
}
|
|
251
|
+
return machine;
|
|
252
|
+
},
|
|
253
|
+
async listRecords() {
|
|
254
|
+
return fetchDecoded({ method: "GET", path: "/v1/records" }, decodeAuditRecords);
|
|
255
|
+
},
|
|
256
|
+
async listAuthorizations(machineId) {
|
|
257
|
+
const safeId = encodeMachineId(machineId);
|
|
258
|
+
return fetchDecoded({ method: "GET", path: `/v1/sessions/${safeId}/authorizations` }, decodeMachineAuthorizations);
|
|
259
|
+
},
|
|
260
|
+
async listApiKeys() {
|
|
261
|
+
return fetchDecoded({ method: "GET", path: "/v1/api-keys" }, decodeApiKeyList);
|
|
262
|
+
},
|
|
263
|
+
async createApiKey(input, idempotencyKey, signal) {
|
|
264
|
+
assertIdempotencyKey(idempotencyKey);
|
|
265
|
+
return fetchDecoded({
|
|
266
|
+
method: "POST",
|
|
267
|
+
path: "/v1/api-keys",
|
|
268
|
+
idempotencyKey,
|
|
269
|
+
settleWith: "cuna api-keys list",
|
|
270
|
+
body: {
|
|
271
|
+
name: input.name,
|
|
272
|
+
...(input.expiresAt === undefined ? {} : { expires_at: input.expiresAt }),
|
|
273
|
+
},
|
|
274
|
+
...(signal === undefined ? {} : { signal }),
|
|
275
|
+
}, decodeApiKeyCreation);
|
|
276
|
+
},
|
|
277
|
+
async revokeApiKey(id) {
|
|
278
|
+
const safeId = encodeCanonicalUuid(id, "API key ID");
|
|
279
|
+
return fetchDecoded({ method: "DELETE", path: `/v1/api-keys/${safeId}`, settleWith: "cuna api-keys list" }, decodeOk);
|
|
280
|
+
},
|
|
281
|
+
async createMachine(input, idempotencyKey, requestId, signal) {
|
|
282
|
+
validateMachineCreate(input, idempotencyKey);
|
|
283
|
+
if (requestId !== undefined)
|
|
284
|
+
assertCanonicalUuid(requestId, "machine create request ID");
|
|
285
|
+
const body = {
|
|
286
|
+
name: input.name,
|
|
287
|
+
...(input.agent === undefined ? {} : { agent: input.agent }),
|
|
288
|
+
...(input.vcpus === undefined ? {} : { vcpus: input.vcpus }),
|
|
289
|
+
...(input.memoryMiB === undefined ? {} : { memory_mib: input.memoryMiB }),
|
|
290
|
+
...(input.background === undefined ? {} : { background: input.background }),
|
|
291
|
+
};
|
|
292
|
+
return fetchDecoded({
|
|
293
|
+
method: "POST",
|
|
294
|
+
path: "/v1/sessions",
|
|
295
|
+
body,
|
|
296
|
+
idempotencyKey,
|
|
297
|
+
// The producer provisions a real machine inside this request, so the
|
|
298
|
+
// budget that suits a list is not the budget that suits this. D1: the
|
|
299
|
+
// value is a named constant, not a literal repeated here.
|
|
300
|
+
budgetMs: MACHINE_CREATE_REQUEST_BUDGET_MS,
|
|
301
|
+
settleWith: "cuna machines list",
|
|
302
|
+
...(requestId === undefined ? {} : { machineCreateRequestId: requestId }),
|
|
303
|
+
...(signal === undefined ? {} : { signal }),
|
|
304
|
+
}, decodeMachineItem);
|
|
305
|
+
},
|
|
306
|
+
async getMachineCreateRequest(id, signal) {
|
|
307
|
+
const safeId = encodeCanonicalUuid(id, "machine create request ID");
|
|
308
|
+
const httpRequest = {
|
|
309
|
+
method: "GET",
|
|
310
|
+
path: `/v1/machine-creates/${safeId}`,
|
|
311
|
+
...(signal === undefined ? {} : { signal }),
|
|
312
|
+
};
|
|
313
|
+
const request = await fetchDecoded(httpRequest, decodeMachineCreateRequest);
|
|
314
|
+
if (request.id !== id) {
|
|
315
|
+
throw malformed(contractViolation("matches_requested_resource", "id"), operationLabel(httpRequest));
|
|
316
|
+
}
|
|
317
|
+
return request;
|
|
318
|
+
},
|
|
319
|
+
async reconcileMachineCreateRequest(id, signal) {
|
|
320
|
+
const safeId = encodeCanonicalUuid(id, "machine create request ID");
|
|
321
|
+
const httpRequest = {
|
|
322
|
+
method: "POST",
|
|
323
|
+
path: `/v1/machine-creates/${safeId}/reconcile`,
|
|
324
|
+
...(signal === undefined ? {} : { signal }),
|
|
325
|
+
};
|
|
326
|
+
const request = await fetchDecoded(httpRequest, decodeMachineCreateRequest);
|
|
327
|
+
if (request.id !== id) {
|
|
328
|
+
throw malformed(contractViolation("matches_requested_resource", "id"), operationLabel(httpRequest));
|
|
329
|
+
}
|
|
330
|
+
return request;
|
|
331
|
+
},
|
|
332
|
+
async transitionMachine(id, action, signal) {
|
|
333
|
+
const safeId = encodeMachineId(id);
|
|
334
|
+
const request = {
|
|
335
|
+
method: "POST",
|
|
336
|
+
path: `/v1/sessions/${safeId}/${action}`,
|
|
337
|
+
settleWith: "cuna machines list",
|
|
338
|
+
// A start boots a VM and waits for its supervisor; the list budget
|
|
339
|
+
// aborted the journey's own step at 15 s and told the caller the
|
|
340
|
+
// operation "may have completed".
|
|
341
|
+
budgetMs: MACHINE_LIFECYCLE_REQUEST_BUDGET_MS,
|
|
342
|
+
...(signal === undefined ? {} : { signal }),
|
|
343
|
+
};
|
|
344
|
+
const machine = await fetchDecoded(request, decodeMachineItem);
|
|
345
|
+
if (machine.id !== id) {
|
|
346
|
+
throw malformed(contractViolation("matches_requested_resource", "id"), operationLabel(request));
|
|
347
|
+
}
|
|
348
|
+
return machine;
|
|
349
|
+
},
|
|
350
|
+
async replaceMachineSupervisor(id, signal) {
|
|
351
|
+
const safeId = encodeMachineId(id);
|
|
352
|
+
const request = {
|
|
353
|
+
method: "POST",
|
|
354
|
+
path: `/v1/sessions/${safeId}/supervisor/replace`,
|
|
355
|
+
settleWith: "cuna machines list",
|
|
356
|
+
budgetMs: MACHINE_LIFECYCLE_REQUEST_BUDGET_MS,
|
|
357
|
+
...(signal === undefined ? {} : { signal }),
|
|
358
|
+
};
|
|
359
|
+
const machine = await fetchDecoded(request, decodeMachineItem);
|
|
360
|
+
if (machine.id !== id) {
|
|
361
|
+
throw malformed(contractViolation("matches_requested_resource", "id"), operationLabel(request));
|
|
362
|
+
}
|
|
363
|
+
return machine;
|
|
364
|
+
},
|
|
365
|
+
async updateMachineSupervisorInPlace(id, operationId, signal) {
|
|
366
|
+
const safeId = encodeMachineId(id);
|
|
367
|
+
assertCanonicalUuid(operationId, "supervisor update operation ID");
|
|
368
|
+
const request = {
|
|
369
|
+
method: "POST",
|
|
370
|
+
path: `/v1/sessions/${safeId}/supervisor/live-update`,
|
|
371
|
+
// Chosen by the caller before this line, recorded durably before this
|
|
372
|
+
// line, and the reason a lost answer is recoverable at all. The producer
|
|
373
|
+
// journals it before it issues any enrollment, so the same value never
|
|
374
|
+
// rotates control twice.
|
|
375
|
+
body: { operation_id: operationId },
|
|
376
|
+
// The read that settles this operation's outcome without spending
|
|
377
|
+
// anything, and the only one that answers what this update did.
|
|
378
|
+
settleWith: `cuna machines live-update-status ${id} --operation ${operationId}`,
|
|
379
|
+
budgetMs: SUPERVISOR_LIVE_UPDATE_REQUEST_BUDGET_MS,
|
|
380
|
+
// Still off, and now for a sharper reason than before. The identity
|
|
381
|
+
// above makes a repeat SAFE on the producer's side, but it must remain
|
|
382
|
+
// a DECISION: `machines live-update-supervisor --resume` is that
|
|
383
|
+
// decision, taken by a person who has read the operation. A transport
|
|
384
|
+
// re-dispatch happens below the command, below the local record and
|
|
385
|
+
// below the person, so it would be the one repetition nobody chose.
|
|
386
|
+
automaticRedispatch: false,
|
|
387
|
+
...(signal === undefined ? {} : { signal }),
|
|
388
|
+
};
|
|
389
|
+
const result = await fetchDecoded(request, decodeSupervisorLiveUpdate);
|
|
390
|
+
// The path id is the Machine, so the Machine in the body must be the one
|
|
391
|
+
// that was asked about. Without this, a producer answering about a sibling
|
|
392
|
+
// would have its control generation and artifact digest reported as this
|
|
393
|
+
// Machine's. The operation identity is checked for the same reason: an
|
|
394
|
+
// answer about another operation is not an answer about this one, and the
|
|
395
|
+
// caller is about to settle a durable record against it.
|
|
396
|
+
if (result.machine.id !== id) {
|
|
397
|
+
throw malformed(contractViolation("matches_requested_resource", "machine.id"), operationLabel(request));
|
|
398
|
+
}
|
|
399
|
+
if (result.operationId !== operationId) {
|
|
400
|
+
throw malformed(contractViolation("matches_requested_operation", "operation_id"), operationLabel(request));
|
|
401
|
+
}
|
|
402
|
+
return result;
|
|
403
|
+
},
|
|
404
|
+
async readMachineSupervisorInPlaceUpdate(id, operationId, signal) {
|
|
405
|
+
const safeId = encodeMachineId(id);
|
|
406
|
+
const safeOperationId = encodeCanonicalUuid(operationId, "supervisor update operation ID");
|
|
407
|
+
const request = {
|
|
408
|
+
method: "GET",
|
|
409
|
+
path: `/v1/sessions/${safeId}/supervisor/live-update/${safeOperationId}`,
|
|
410
|
+
// A database read scoped to the owner and this Machine. It dispatches no
|
|
411
|
+
// installer and writes nothing, so the ordinary read budget applies and
|
|
412
|
+
// an automatic re-dispatch of it costs nothing.
|
|
413
|
+
settleWith: `cuna machines live-update-status ${id} --operation ${operationId}`,
|
|
414
|
+
...(signal === undefined ? {} : { signal }),
|
|
415
|
+
};
|
|
416
|
+
const operation = await fetchDecoded(request, decodeSupervisorLiveUpdateOperation);
|
|
417
|
+
if (operation.machineId !== id || operation.operationId !== operationId) {
|
|
418
|
+
throw malformed(contractViolation("matches_requested_operation", "operation_id"), operationLabel(request));
|
|
419
|
+
}
|
|
420
|
+
return operation;
|
|
421
|
+
},
|
|
422
|
+
async deleteMachine(id) {
|
|
423
|
+
const safeId = encodeMachineId(id);
|
|
424
|
+
return transport.request({
|
|
425
|
+
method: "DELETE",
|
|
426
|
+
path: `/v1/sessions/${safeId}`,
|
|
427
|
+
settleWith: "cuna machines list",
|
|
428
|
+
});
|
|
429
|
+
},
|
|
430
|
+
async executeManagedCommand(machineId, operationId, input, signal) {
|
|
431
|
+
const safeId = encodeMachineId(machineId);
|
|
432
|
+
assertCanonicalUuid(operationId, "execution ID");
|
|
433
|
+
if (typeof input.command !== "string" || input.command.length === 0 || input.command.includes("\0") ||
|
|
434
|
+
(input.args !== undefined && (!Array.isArray(input.args) || input.args.some(arg => typeof arg !== "string" || arg.includes("\0")))) ||
|
|
435
|
+
typeof input.cwd !== "string" ||
|
|
436
|
+
!/^\/workspace\/workspaces\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:\/|$)/u.test(input.cwd) ||
|
|
437
|
+
input.cwd.includes("\\") || input.cwd.split("/").some(part => part === "." || part === "..") || /[\p{Cc}\p{Cf}]/u.test(input.cwd) ||
|
|
438
|
+
(input.timeoutSecs !== undefined && (!Number.isSafeInteger(input.timeoutSecs) || input.timeoutSecs < 1 || input.timeoutSecs > 600))) {
|
|
439
|
+
throw usageError("Invalid managed command request.", "Choose an exact remote Workspace path and a timeout from 1 to 600 seconds.");
|
|
440
|
+
}
|
|
441
|
+
const body = { operation_id: operationId, command: input.command,
|
|
442
|
+
...(input.args === undefined ? {} : { args: [...input.args] }), cwd: input.cwd,
|
|
443
|
+
...(input.timeoutSecs === undefined ? {} : { timeout_secs: input.timeoutSecs }) };
|
|
444
|
+
if (Buffer.byteLength(JSON.stringify(body)) > 8 * 1024 * 1024)
|
|
445
|
+
throw usageError("Managed command request exceeds 8 MiB.");
|
|
446
|
+
const request = { method: "POST", path: `/v1/sessions/${safeId}/exec`, body,
|
|
447
|
+
budgetMs: (input.timeoutSecs ?? 120) * 1000 + 5000,
|
|
448
|
+
settleWith: `cuna executions get ${operationId} --machine ${machineId}`,
|
|
449
|
+
...(signal === undefined ? {} : { signal }) };
|
|
450
|
+
return fetchDecoded(request, decodeManagedCommandResult);
|
|
451
|
+
},
|
|
452
|
+
async listManagedExecutions(machineId, input = {}, signal) {
|
|
453
|
+
const safeId = encodeMachineId(machineId);
|
|
454
|
+
const query = new URLSearchParams();
|
|
455
|
+
if (input.executionWorkspaceId !== undefined)
|
|
456
|
+
query.set("execution_workspace_id", assertCanonicalUuid(input.executionWorkspaceId, "execution Workspace ID"));
|
|
457
|
+
if (input.after !== undefined)
|
|
458
|
+
query.set("after", assertCanonicalUuid(input.after, "execution cursor"));
|
|
459
|
+
const request = { method: "GET", path: `/v1/sessions/${safeId}/executions${query.size ? `?${query}` : ""}`,
|
|
460
|
+
...(signal === undefined ? {} : { signal }) };
|
|
461
|
+
const page = await fetchDecoded(request, decodeManagedExecutionPage);
|
|
462
|
+
if (page.machineId !== machineId || page.items.some(item => (input.executionWorkspaceId !== undefined && item.executionWorkspaceId !== input.executionWorkspaceId) ||
|
|
463
|
+
(input.after !== undefined && item.operationId <= input.after))) {
|
|
464
|
+
throw malformed(contractViolation("managed_execution_scope"), operationLabel(request));
|
|
465
|
+
}
|
|
466
|
+
return page;
|
|
467
|
+
},
|
|
468
|
+
async getManagedExecution(machineId, operationId, signal) {
|
|
469
|
+
const path = `/v1/sessions/${encodeMachineId(machineId)}/executions/${encodeCanonicalUuid(operationId, "execution ID")}`;
|
|
470
|
+
const request = { method: "GET", path, ...(signal === undefined ? {} : { signal }) };
|
|
471
|
+
const result = await fetchDecoded(request, decodeManagedExecution);
|
|
472
|
+
if (result.machineId !== machineId || result.operationId !== operationId)
|
|
473
|
+
throw malformed(contractViolation("managed_execution_scope"), operationLabel(request));
|
|
474
|
+
return result;
|
|
475
|
+
},
|
|
476
|
+
async cancelManagedExecution(machineId, operationId, signal) {
|
|
477
|
+
const path = `/v1/sessions/${encodeMachineId(machineId)}/executions/${encodeCanonicalUuid(operationId, "execution ID")}/cancel`;
|
|
478
|
+
const request = { method: "POST", path, body: {},
|
|
479
|
+
settleWith: `cuna executions get ${operationId} --machine ${machineId}`, ...(signal === undefined ? {} : { signal }) };
|
|
480
|
+
const result = await fetchDecoded(request, decodeManagedExecution);
|
|
481
|
+
if (result.machineId !== machineId || result.operationId !== operationId || !result.cancelRequested) {
|
|
482
|
+
throw malformed(contractViolation("managed_execution_cancellation"), operationLabel(request));
|
|
483
|
+
}
|
|
484
|
+
return result;
|
|
485
|
+
},
|
|
486
|
+
async listExecutionWorkspaces(input, signal) {
|
|
487
|
+
assertCanonicalUuid(input.workspaceId, "workspace ID");
|
|
488
|
+
assertCanonicalUuid(input.projectId, "project ID");
|
|
489
|
+
assertCanonicalUuid(input.machineId, "machine ID");
|
|
490
|
+
if (input.after !== undefined)
|
|
491
|
+
assertCanonicalUuid(input.after, "execution workspace cursor");
|
|
492
|
+
const query = new URLSearchParams({ workspace_id: input.workspaceId, project_id: input.projectId, machine_id: input.machineId });
|
|
493
|
+
if (input.after !== undefined)
|
|
494
|
+
query.set("after", input.after);
|
|
495
|
+
const request = { method: "GET", path: `/v1/execution-workspaces?${query}`, ...(signal === undefined ? {} : { signal }) };
|
|
496
|
+
const page = await fetchDecoded(request, decodeExecutionWorkspacePage);
|
|
497
|
+
if (page.items.some(row => row.workspaceId !== input.workspaceId || row.projectId !== input.projectId || row.machineId !== input.machineId ||
|
|
498
|
+
(input.after !== undefined && row.executionWorkspaceId <= input.after))) {
|
|
499
|
+
throw malformed(contractViolation("execution_workspace_scope"), operationLabel(request));
|
|
500
|
+
}
|
|
501
|
+
return page;
|
|
502
|
+
},
|
|
503
|
+
async createWorkspaceBinding(input, idempotencyKey, signal) {
|
|
504
|
+
validateWorkspaceBindingIdentity(input);
|
|
505
|
+
assertIdempotencyKey(idempotencyKey);
|
|
506
|
+
if (!Array.isArray(input.excludedPrefixes) || input.excludedPrefixes.length > 10_000) {
|
|
507
|
+
throw new CunaError({ code: "cuna.usage.invalid", message: "Workspace excluded prefixes are invalid.", exitCode: EXIT_CODES.usage });
|
|
508
|
+
}
|
|
509
|
+
const prefixes = input.excludedPrefixes.map((prefix) => {
|
|
510
|
+
if (typeof prefix !== "string" || prefix.length < 1 || prefix.length > 4_096 ||
|
|
511
|
+
prefix.startsWith("/") || prefix.startsWith("\\") || prefix.includes("\\") ||
|
|
512
|
+
containsAsciiControl(prefix) || /^[A-Za-z]:/u.test(prefix) ||
|
|
513
|
+
prefix.split("/").some((part) => part === "" || part === "." || part === "..")) {
|
|
514
|
+
throw new CunaError({ code: "cuna.usage.invalid", message: "Workspace excluded prefixes are invalid.", exitCode: EXIT_CODES.usage });
|
|
515
|
+
}
|
|
516
|
+
return prefix;
|
|
517
|
+
});
|
|
518
|
+
if (new Set(prefixes).size !== prefixes.length) {
|
|
519
|
+
throw new CunaError({ code: "cuna.usage.invalid", message: "Workspace excluded prefixes must be unique.", exitCode: EXIT_CODES.usage });
|
|
520
|
+
}
|
|
521
|
+
const request = {
|
|
522
|
+
method: "POST",
|
|
523
|
+
path: "/v1/workspace-bindings",
|
|
524
|
+
idempotencyKey,
|
|
525
|
+
body: {
|
|
526
|
+
workspace_id: input.workspaceId,
|
|
527
|
+
project_id: input.projectId,
|
|
528
|
+
local_instance_id: input.localInstanceId,
|
|
529
|
+
machine_id: input.machineId,
|
|
530
|
+
...(input.executionWorkspaceId === undefined ? {} : { execution_workspace_id: input.executionWorkspaceId }),
|
|
531
|
+
exclusion_policy_digest: input.exclusionPolicyDigest,
|
|
532
|
+
excluded_prefixes: prefixes,
|
|
533
|
+
},
|
|
534
|
+
...(signal === undefined ? {} : { signal }),
|
|
535
|
+
};
|
|
536
|
+
const authority = await fetchDecoded(request, decodeWorkspaceBindingAuthority);
|
|
537
|
+
if (!workspaceBindingIdentityMatches(authority, input)) {
|
|
538
|
+
throw malformed(contractViolation("matches_requested_resource", "workspace_id"), operationLabel(request));
|
|
539
|
+
}
|
|
540
|
+
return authority;
|
|
541
|
+
},
|
|
542
|
+
async getWorkspaceBinding(bindingId, identity, signal) {
|
|
543
|
+
const safeId = encodeCanonicalUuid(bindingId, "workspace binding ID");
|
|
544
|
+
validateWorkspaceBindingIdentity(identity);
|
|
545
|
+
const request = {
|
|
546
|
+
method: "GET",
|
|
547
|
+
path: `/v1/workspace-bindings/${safeId}`,
|
|
548
|
+
query: {
|
|
549
|
+
workspace_id: identity.workspaceId,
|
|
550
|
+
project_id: identity.projectId,
|
|
551
|
+
local_instance_id: identity.localInstanceId,
|
|
552
|
+
machine_id: identity.machineId,
|
|
553
|
+
exclusion_policy_digest: identity.exclusionPolicyDigest,
|
|
554
|
+
},
|
|
555
|
+
...(signal === undefined ? {} : { signal }),
|
|
556
|
+
};
|
|
557
|
+
const authority = await fetchDecoded(request, decodeWorkspaceBindingAuthority);
|
|
558
|
+
if (authority.bindingId !== bindingId) {
|
|
559
|
+
throw malformed(contractViolation("matches_requested_resource", "binding_id"), operationLabel(request));
|
|
560
|
+
}
|
|
561
|
+
if (!workspaceBindingIdentityMatches(authority, identity)) {
|
|
562
|
+
throw malformed(contractViolation("matches_requested_resource", "workspace_id"), operationLabel(request));
|
|
563
|
+
}
|
|
564
|
+
return authority;
|
|
565
|
+
},
|
|
566
|
+
async listAgentSessions(machineId, options = {}, signal) {
|
|
567
|
+
const safeId = encodeMachineId(machineId);
|
|
568
|
+
const query = validatePageOptions(options);
|
|
569
|
+
const request = {
|
|
570
|
+
method: "GET",
|
|
571
|
+
path: `/v1/sessions/${safeId}/agent-sessions`,
|
|
572
|
+
query,
|
|
573
|
+
...(signal === undefined ? {} : { signal }),
|
|
574
|
+
};
|
|
575
|
+
const page = await fetchDecoded(request, decodeAgentSessionPage);
|
|
576
|
+
for (const session of page.items) {
|
|
577
|
+
assertAgentSessionBinding(session, { machineId }, operationLabel(request));
|
|
578
|
+
}
|
|
579
|
+
return page;
|
|
580
|
+
},
|
|
581
|
+
async createAgentSession(machineId, input, idempotencyKey, signal) {
|
|
582
|
+
const safeId = encodeMachineId(machineId);
|
|
583
|
+
assertCanonicalUuid(input.workspaceBindingId, "workspace binding ID");
|
|
584
|
+
validateAgentSessionCreate(input);
|
|
585
|
+
const request = {
|
|
586
|
+
method: "POST",
|
|
587
|
+
path: `/v1/sessions/${safeId}/agent-sessions`,
|
|
588
|
+
settleWith: `cuna agent-sessions list --machine ${machineId}`,
|
|
589
|
+
body: {
|
|
590
|
+
...(input.name === undefined ? {} : { name: input.name }),
|
|
591
|
+
agent: input.agent,
|
|
592
|
+
cwd: input.cwd,
|
|
593
|
+
workspace_binding_id: input.workspaceBindingId,
|
|
594
|
+
workspace_generation: input.workspaceGeneration,
|
|
595
|
+
...(input.authMode === undefined ? {} : { auth_mode: input.authMode }),
|
|
596
|
+
...(input.credentialBindingId === undefined
|
|
597
|
+
? {}
|
|
598
|
+
: { credential_binding_id: input.credentialBindingId }),
|
|
599
|
+
},
|
|
600
|
+
idempotencyKey,
|
|
601
|
+
...(signal === undefined ? {} : { signal }),
|
|
602
|
+
};
|
|
603
|
+
return assertAgentSessionBinding(await fetchDecoded(request, decodeAgentSessionItem), {
|
|
604
|
+
machineId,
|
|
605
|
+
workspaceBindingId: input.workspaceBindingId,
|
|
606
|
+
workspaceGeneration: input.workspaceGeneration,
|
|
607
|
+
}, operationLabel(request));
|
|
608
|
+
},
|
|
609
|
+
async getProviderPresetsV2(signal) {
|
|
610
|
+
return fetchDecoded({ method: "POST", path: "/v1/collaboration/2/provider-profiles/catalog", body: { version: "2" }, ...(signal === undefined ? {} : { signal }) }, decodeProviderPresets);
|
|
611
|
+
},
|
|
612
|
+
async createProviderSessionV2(machineId, input, signal) {
|
|
613
|
+
assertCanonicalUuid(input.operation_id, "operation ID");
|
|
614
|
+
assertCanonicalUuid(input.profile_id, "profile ID");
|
|
615
|
+
return fetchDecoded({ method: "POST", path: `/v1/collaboration/2/sessions/${encodeMachineId(machineId)}/workspace-agent-sessions`, body: providerSessionBody(input), ...(signal === undefined ? {} : { signal }) }, value => decodeProviderSession(value, machineId, input));
|
|
616
|
+
},
|
|
617
|
+
async checkProviderV2(sessionId, epoch, signal) {
|
|
618
|
+
return fetchDecoded({ method: "POST", path: `/v1/collaboration/2/agent-sessions/${encodeCanonicalUuid(sessionId, "AgentSession ID")}/provider-observations`, body: { version: "2" }, ...(signal === undefined ? {} : { signal }) }, value => decodeProviderObservation(value, sessionId, epoch));
|
|
619
|
+
},
|
|
620
|
+
async getMachineDefaultWorkspace(machineId, signal) {
|
|
621
|
+
const request = { method: "GET", path: `/v1/sessions/${encodeMachineId(machineId)}/default-workspace`, ...(signal === undefined ? {} : { signal }) };
|
|
622
|
+
const workspace = await fetchDecoded(request, decodeMachineDefaultWorkspace);
|
|
623
|
+
if (workspace.machineId !== machineId)
|
|
624
|
+
throw malformed(contractViolation("matches_requested_resource", "machine_id"), operationLabel(request));
|
|
625
|
+
return workspace;
|
|
626
|
+
},
|
|
627
|
+
async getAgentSessionWorkspaceContext(id, signal) {
|
|
628
|
+
const request = { method: "GET", path: `/v1/agent-sessions/${encodeCanonicalUuid(id, "AgentSession ID")}/workspace-context`, ...(signal === undefined ? {} : { signal }) };
|
|
629
|
+
const context = await fetchDecoded(request, decodeAgentSessionWorkspaceContext);
|
|
630
|
+
if (context.agentSessionId !== id)
|
|
631
|
+
throw malformed(contractViolation("matches_requested_resource", "agent_session_id"), operationLabel(request));
|
|
632
|
+
return context;
|
|
633
|
+
},
|
|
634
|
+
async createAgentSessionInWorkspace(machineId, input, idempotencyKey, signal) {
|
|
635
|
+
const safeId = encodeMachineId(machineId);
|
|
636
|
+
assertCanonicalUuid(input.executionWorkspaceId, "execution Workspace ID");
|
|
637
|
+
assertIdempotencyKey(idempotencyKey);
|
|
638
|
+
validateAgentSessionCreate(input);
|
|
639
|
+
const root = `/workspace/workspaces/${input.executionWorkspaceId}`;
|
|
640
|
+
if ((input.cwd !== root && !input.cwd.startsWith(`${root}/`)) || input.cwd.includes("\\") || input.cwd.split("/").includes(".") ||
|
|
641
|
+
input.agent === "openclaw" || input.authMode !== "interactive_login" || input.credentialBindingId !== undefined) {
|
|
642
|
+
throw new CunaError({ code: "cuna.usage.invalid", message: "Remote Workspace sessions require their exact remote path and interactive agent login.", exitCode: EXIT_CODES.usage });
|
|
643
|
+
}
|
|
644
|
+
const request = { method: "POST", path: `/v1/sessions/${safeId}/workspace-agent-sessions`, idempotencyKey,
|
|
645
|
+
settleWith: `cuna agent-sessions list --machine ${machineId}`, body: { ...(input.name === undefined ? {} : { name: input.name }), agent: input.agent, cwd: input.cwd,
|
|
646
|
+
execution_workspace_id: input.executionWorkspaceId, workspace_generation: input.workspaceGeneration, auth_mode: input.authMode }, ...(signal === undefined ? {} : { signal }) };
|
|
647
|
+
const result = await fetchDecoded(request, decodeAgentSessionWorkspaceEnvelope);
|
|
648
|
+
if (result.agentSession.machineId !== machineId || result.executionWorkspaceId !== input.executionWorkspaceId || result.workspaceGeneration !== input.workspaceGeneration ||
|
|
649
|
+
result.agentSession.cwd !== input.cwd || result.agentSession.agent !== input.agent || result.agentSession.authMode !== input.authMode) {
|
|
650
|
+
throw malformed(contractViolation("matches_requested_resource", "execution_workspace_id"), operationLabel(request));
|
|
651
|
+
}
|
|
652
|
+
return result;
|
|
653
|
+
},
|
|
654
|
+
async inspectAgentSessionCreate(idempotencyKey, signal) {
|
|
655
|
+
assertIdempotencyKey(idempotencyKey);
|
|
656
|
+
return fetchDecoded({
|
|
657
|
+
method: "GET",
|
|
658
|
+
path: "/v1/agent-session-creates",
|
|
659
|
+
idempotencyKey,
|
|
660
|
+
...(signal === undefined ? {} : { signal }),
|
|
661
|
+
}, decodeAgentSessionItem);
|
|
662
|
+
},
|
|
663
|
+
async getAgentSession(id, signal) {
|
|
664
|
+
const safeId = encodeCanonicalUuid(id, "AgentSession ID");
|
|
665
|
+
const request = {
|
|
666
|
+
method: "GET",
|
|
667
|
+
path: `/v1/agent-sessions/${safeId}`,
|
|
668
|
+
...(signal === undefined ? {} : { signal }),
|
|
669
|
+
};
|
|
670
|
+
return assertAgentSessionBinding(await fetchDecoded(request, decodeAgentSessionItem), { id }, operationLabel(request));
|
|
671
|
+
},
|
|
672
|
+
async getAgentSessionAuth(id, signal) {
|
|
673
|
+
const safeId = encodeCanonicalUuid(id, "AgentSession ID");
|
|
674
|
+
const request = {
|
|
675
|
+
method: "GET",
|
|
676
|
+
path: `/v1/agent-sessions/${safeId}/agent-auth`,
|
|
677
|
+
...(signal === undefined ? {} : { signal }),
|
|
678
|
+
};
|
|
679
|
+
const status = await fetchDecoded(request, decodeAgentSessionAuth);
|
|
680
|
+
if (status.agentSessionId !== id) {
|
|
681
|
+
throw malformed(contractViolation("matches_requested_resource", "agent_session_id"), operationLabel(request));
|
|
682
|
+
}
|
|
683
|
+
return status;
|
|
684
|
+
},
|
|
685
|
+
async getAgentSessionTerminalSeat(id, signal) {
|
|
686
|
+
const safeId = encodeCanonicalUuid(id, "AgentSession ID");
|
|
687
|
+
const request = {
|
|
688
|
+
method: "GET",
|
|
689
|
+
path: `/v1/agent-sessions/${safeId}/terminal`,
|
|
690
|
+
...(signal === undefined ? {} : { signal }),
|
|
691
|
+
};
|
|
692
|
+
const seat = await fetchDecoded(request, decodeAgentSessionTerminalSeat);
|
|
693
|
+
if (seat.agentSessionId !== id) {
|
|
694
|
+
throw malformed(contractViolation("matches_requested_resource", "agent_session_id"), operationLabel(request));
|
|
695
|
+
}
|
|
696
|
+
return seat;
|
|
697
|
+
},
|
|
698
|
+
async logoutAgentSessionAuth(id, expectedProcessEpoch, signal) {
|
|
699
|
+
const safeId = encodeCanonicalUuid(id, "AgentSession ID");
|
|
700
|
+
const safeEpoch = assertCanonicalUuid(expectedProcessEpoch, "AgentSession process epoch");
|
|
701
|
+
const request = {
|
|
702
|
+
method: "POST",
|
|
703
|
+
path: `/v1/agent-sessions/${safeId}/agent-auth/logout`,
|
|
704
|
+
body: { process_epoch: safeEpoch },
|
|
705
|
+
...(signal === undefined ? {} : { signal }),
|
|
706
|
+
};
|
|
707
|
+
const result = await fetchDecoded(request, decodeAgentSessionAuthLogout);
|
|
708
|
+
if (result.agentSessionId !== id) {
|
|
709
|
+
throw malformed(contractViolation("matches_requested_resource", "agent_session_id"), operationLabel(request));
|
|
710
|
+
}
|
|
711
|
+
if (result.processEpoch !== expectedProcessEpoch) {
|
|
712
|
+
throw malformed(contractViolation("matches_requested_resource", "process_epoch"), operationLabel(request));
|
|
713
|
+
}
|
|
714
|
+
return result;
|
|
715
|
+
},
|
|
716
|
+
async renameAgentSession(id, name) {
|
|
717
|
+
const safeId = encodeCanonicalUuid(id, "AgentSession ID");
|
|
718
|
+
if (name.length < 1 || name.length > 80) {
|
|
719
|
+
throw new CunaError({
|
|
720
|
+
code: "cuna.usage.invalid",
|
|
721
|
+
message: "AgentSession name must contain 1 through 80 characters.",
|
|
722
|
+
exitCode: EXIT_CODES.usage,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
const request = {
|
|
726
|
+
method: "PATCH",
|
|
727
|
+
path: `/v1/agent-sessions/${safeId}`,
|
|
728
|
+
settleWith: `cuna agent-sessions get ${id}`,
|
|
729
|
+
body: { name },
|
|
730
|
+
};
|
|
731
|
+
return assertAgentSessionBinding(await fetchDecoded(request, decodeAgentSessionItem), { id }, operationLabel(request));
|
|
732
|
+
},
|
|
733
|
+
async terminateAgentSession(id) {
|
|
734
|
+
const safeId = encodeCanonicalUuid(id, "AgentSession ID");
|
|
735
|
+
const request = {
|
|
736
|
+
method: "POST",
|
|
737
|
+
path: `/v1/agent-sessions/${safeId}/terminate`,
|
|
738
|
+
settleWith: `cuna agent-sessions get ${id}`,
|
|
739
|
+
};
|
|
740
|
+
return assertAgentSessionBinding(await fetchDecoded(request, decodeAgentSessionItem), { id }, operationLabel(request));
|
|
741
|
+
},
|
|
742
|
+
async createTerminalConnection(agentSessionId, input, idempotencyKey, signal) {
|
|
743
|
+
const safeId = encodeCanonicalUuid(agentSessionId, "AgentSession ID");
|
|
744
|
+
assertIdempotencyKey(idempotencyKey);
|
|
745
|
+
if (!/^[A-Za-z0-9._:-]{1,256}$/u.test(input.clientInstanceId)) {
|
|
746
|
+
throw new CunaError({
|
|
747
|
+
code: "cuna.usage.invalid",
|
|
748
|
+
message: "Terminal client instance ID is malformed.",
|
|
749
|
+
exitCode: EXIT_CODES.usage,
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
if (input.resumeHandle !== undefined &&
|
|
753
|
+
!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.test(input.resumeHandle)) {
|
|
754
|
+
throw new CunaError({
|
|
755
|
+
code: "cuna.usage.invalid",
|
|
756
|
+
message: "Terminal resume handle must be a canonical Cuna UUID.",
|
|
757
|
+
exitCode: EXIT_CODES.usage,
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
return fetchDecoded({
|
|
761
|
+
method: "POST",
|
|
762
|
+
path: `/v1/agent-sessions/${safeId}/terminal-connections`,
|
|
763
|
+
body: {
|
|
764
|
+
protocol: input.protocol,
|
|
765
|
+
client_instance_id: input.clientInstanceId,
|
|
766
|
+
...(input.resumeHandle === undefined ? {} : { resume_handle: input.resumeHandle }),
|
|
767
|
+
...(input.accessMode === undefined ? {} : { access_mode: input.accessMode }),
|
|
768
|
+
...(input.expectedWriterEpoch === undefined ? {} : { expected_writer_epoch: input.expectedWriterEpoch }),
|
|
769
|
+
},
|
|
770
|
+
idempotencyKey,
|
|
771
|
+
...(signal === undefined ? {} : { signal }),
|
|
772
|
+
}, decodeTerminalConnectionGrant);
|
|
773
|
+
},
|
|
774
|
+
async cancelTerminalConnection(agentSessionId, input, idempotencyKey, signal) {
|
|
775
|
+
const safeId = encodeCanonicalUuid(agentSessionId, "AgentSession ID");
|
|
776
|
+
assertIdempotencyKey(idempotencyKey);
|
|
777
|
+
if (input.protocol !== TERMINAL_PROTOCOL || !/^[A-Za-z0-9._:-]{1,256}$/u.test(input.clientInstanceId) ||
|
|
778
|
+
(input.accessMode !== undefined && !["writer", "observer"].includes(input.accessMode)) ||
|
|
779
|
+
(input.expectedWriterEpoch !== undefined && (!Number.isSafeInteger(input.expectedWriterEpoch) || input.expectedWriterEpoch < 0))) {
|
|
780
|
+
throw contractViolation("terminal_connection_cancellation_request");
|
|
781
|
+
}
|
|
782
|
+
if (input.resumeHandle !== undefined)
|
|
783
|
+
assertCanonicalUuid(input.resumeHandle, "Terminal resume handle");
|
|
784
|
+
return fetchDecoded({ method: "POST", path: `/v1/agent-sessions/${safeId}/terminal-connections/cancel`,
|
|
785
|
+
body: { protocol: input.protocol, client_instance_id: input.clientInstanceId,
|
|
786
|
+
...(input.resumeHandle === undefined ? {} : { resume_handle: input.resumeHandle }),
|
|
787
|
+
...(input.accessMode === undefined ? {} : { access_mode: input.accessMode }),
|
|
788
|
+
...(input.expectedWriterEpoch === undefined ? {} : { expected_writer_epoch: input.expectedWriterEpoch }) },
|
|
789
|
+
idempotencyKey, ...(signal === undefined ? {} : { signal }) }, decodeTerminalConnectionCancellation);
|
|
790
|
+
},
|
|
791
|
+
async transferTerminalWriter(agentSessionId, input, signal) {
|
|
792
|
+
const safeId = encodeCanonicalUuid(agentSessionId, "AgentSession ID");
|
|
793
|
+
if (!/^[A-Za-z0-9._:-]{1,256}$/u.test(input.clientInstanceId)) {
|
|
794
|
+
throw new CunaError({
|
|
795
|
+
code: "cuna.usage.invalid",
|
|
796
|
+
message: "Terminal client instance ID is malformed.",
|
|
797
|
+
exitCode: EXIT_CODES.usage,
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
if (input.expectedWriterEpoch !== undefined &&
|
|
801
|
+
(!Number.isSafeInteger(input.expectedWriterEpoch) || input.expectedWriterEpoch < 0)) {
|
|
802
|
+
throw new CunaError({
|
|
803
|
+
code: "cuna.usage.invalid",
|
|
804
|
+
message: "The expected terminal writer epoch must be a non-negative integer.",
|
|
805
|
+
exitCode: EXIT_CODES.usage,
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
if (input.operationId !== undefined)
|
|
809
|
+
assertCanonicalUuid(input.operationId, "writer operation ID");
|
|
810
|
+
const state = await fetchDecoded({
|
|
811
|
+
method: "POST",
|
|
812
|
+
path: `/v1/agent-sessions/${safeId}/terminal-writer`,
|
|
813
|
+
body: {
|
|
814
|
+
client_instance_id: input.clientInstanceId,
|
|
815
|
+
...(input.operationId === undefined ? {} : { operation_id: input.operationId }),
|
|
816
|
+
...(input.expectedWriterEpoch === undefined ? {} : { expected_writer_epoch: input.expectedWriterEpoch }),
|
|
817
|
+
},
|
|
818
|
+
...(signal === undefined ? {} : { signal }),
|
|
819
|
+
}, decodeTerminalWriterState);
|
|
820
|
+
if (state.agentSessionId !== agentSessionId || state.writerClientInstanceId !== input.clientInstanceId ||
|
|
821
|
+
(input.operationId !== undefined && state.operationId !== input.operationId)) {
|
|
822
|
+
throw malformed(contractViolation("matches_requested_resource", "operation_id"), `POST /v1/agent-sessions/${safeId}/terminal-writer`);
|
|
823
|
+
}
|
|
824
|
+
return state;
|
|
825
|
+
},
|
|
826
|
+
};
|
|
827
|
+
return Object.freeze(client);
|
|
828
|
+
}
|
|
829
|
+
export function decideCapability(snapshot, capabilityId, now = Date.now(), allowedInteractions = ["native"]) {
|
|
830
|
+
// The classifier's own verdict, verbatim. Collapsing all five outcomes into
|
|
831
|
+
// "snapshot_expired" told a user whose server sent an unsupported schema or an
|
|
832
|
+
// over-long TTL to retry a request that can only ever produce the same answer.
|
|
833
|
+
const validity = classifyCapabilitySnapshot(snapshot, now);
|
|
834
|
+
if (validity !== "valid") {
|
|
835
|
+
return Object.freeze({ status: "unknown", capabilityId, reason: validity });
|
|
836
|
+
}
|
|
837
|
+
const matches = snapshot.capabilities.filter((capability) => capability.id === capabilityId);
|
|
838
|
+
if (matches.length !== 1) {
|
|
839
|
+
return Object.freeze({
|
|
840
|
+
status: "unknown",
|
|
841
|
+
capabilityId,
|
|
842
|
+
reason: matches.length === 0 ? "capability_absent" : "capability_ambiguous",
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
const capability = matches[0];
|
|
846
|
+
if (capability === undefined || capability.availability !== "supported") {
|
|
847
|
+
return Object.freeze({
|
|
848
|
+
status: capability?.availability ?? "unknown",
|
|
849
|
+
capabilityId,
|
|
850
|
+
...(capability?.reasonCode === undefined ? {} : { reason: capability.reasonCode }),
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
if (!capability.surfaces.includes("cli") || !allowedInteractions.includes(capability.interaction)) {
|
|
854
|
+
return Object.freeze({ status: "unsupported", capabilityId, reason: "cli_interaction_mismatch" });
|
|
855
|
+
}
|
|
856
|
+
return Object.freeze({ status: "supported", capabilityId });
|
|
857
|
+
}
|
|
858
|
+
export async function requireCapability(input) {
|
|
859
|
+
let snapshot;
|
|
860
|
+
try {
|
|
861
|
+
snapshot = await input.client.discoverCapabilities(input.scope, input.resourceId, input.signal);
|
|
862
|
+
}
|
|
863
|
+
catch (error) {
|
|
864
|
+
// `cuna.remote.operation_not_served` is the code a deployment without the
|
|
865
|
+
// route now produces. Before the transport read the status before the body,
|
|
866
|
+
// that case arrived as `cuna.remote.malformed_response` and this branch was
|
|
867
|
+
// unreachable against the one deployment that exists.
|
|
868
|
+
// A 404 means two different things here. On a resource scope it is the
|
|
869
|
+
// resource saying it is unavailable to this account; on account scope it is the route
|
|
870
|
+
// saying discovery is not served, because the account always exists.
|
|
871
|
+
if (error instanceof CunaError &&
|
|
872
|
+
error.code === "cuna.remote.not_found" &&
|
|
873
|
+
input.scope !== "account" &&
|
|
874
|
+
input.resourceId !== undefined) {
|
|
875
|
+
const subject = input.scope === "machine" ? "Machine" : "AgentSession";
|
|
876
|
+
throw new CunaError({
|
|
877
|
+
code: "cuna.remote.not_found",
|
|
878
|
+
message: `${subject} ${input.resourceId} is not available to this account.`,
|
|
879
|
+
exitCode: EXIT_CODES.remote,
|
|
880
|
+
hint: input.scope === "machine"
|
|
881
|
+
? "Nothing was attempted. Run `cuna machines list` to see the Machines on this account."
|
|
882
|
+
: "Nothing was attempted. Run `cuna agent-sessions list --machine <id>` to see the AgentSessions on a Machine.",
|
|
883
|
+
details: { capability_id: input.capabilityId, scope: input.scope, resource_id: input.resourceId },
|
|
884
|
+
cause: error,
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
if (error instanceof CunaError &&
|
|
888
|
+
(error.code === "cuna.remote.not_found" || error.code === "cuna.remote.operation_not_served")) {
|
|
889
|
+
throw new CunaError({
|
|
890
|
+
code: "cuna.capability.discovery_unavailable",
|
|
891
|
+
message: "This Cuna deployment does not expose capability discovery.",
|
|
892
|
+
exitCode: EXIT_CODES.unsupported,
|
|
893
|
+
hint: "No mutation was attempted. Update the Cuna server contract before retrying.",
|
|
894
|
+
details: { capability_id: input.capabilityId },
|
|
895
|
+
cause: error,
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
throw error;
|
|
899
|
+
}
|
|
900
|
+
if (snapshot.subjectScope !== input.scope ||
|
|
901
|
+
(input.scope !== "account" && snapshot.subjectId !== input.resourceId)) {
|
|
902
|
+
throw new CunaError({
|
|
903
|
+
code: "cuna.capability.unknown",
|
|
904
|
+
message: `Cuna cannot currently authorize the ${input.capabilityId} capability.`,
|
|
905
|
+
exitCode: EXIT_CODES.unsupported,
|
|
906
|
+
hint: "The capability snapshot describes a different subject than the one requested. Nothing was attempted; run `cuna capabilities` to see what this deployment advertises.",
|
|
907
|
+
details: {
|
|
908
|
+
capability_id: input.capabilityId,
|
|
909
|
+
availability: "unknown",
|
|
910
|
+
reason: "subject_scope_mismatch",
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
const receivedAt = typeof input.now === "function" ? input.now() : input.now;
|
|
915
|
+
const decision = decideCapability(snapshot, input.capabilityId, receivedAt, input.allowedInteractions);
|
|
916
|
+
if (decision.status === "supported")
|
|
917
|
+
return;
|
|
918
|
+
throw new CunaError({
|
|
919
|
+
code: decision.status === "temporarily_unavailable"
|
|
920
|
+
? "cuna.capability.temporarily_unavailable"
|
|
921
|
+
: decision.status === "unsupported"
|
|
922
|
+
? "cuna.capability.unsupported"
|
|
923
|
+
: "cuna.capability.unknown",
|
|
924
|
+
message: `Cuna cannot currently authorize the ${input.capabilityId} capability.`,
|
|
925
|
+
exitCode: decision.status === "temporarily_unavailable" ? EXIT_CODES.network : EXIT_CODES.unsupported,
|
|
926
|
+
retryable: decision.status === "temporarily_unavailable" && !isPermanentSnapshotFault(decision.reason),
|
|
927
|
+
hint: isPermanentSnapshotFault(decision.reason)
|
|
928
|
+
? "The server sent capability evidence this CLI cannot accept. Retrying cannot help; update the Cuna server contract or this CLI."
|
|
929
|
+
: "Run `cuna capabilities` to inspect current server support.",
|
|
930
|
+
details: {
|
|
931
|
+
capability_id: input.capabilityId,
|
|
932
|
+
availability: decision.status,
|
|
933
|
+
...(decision.reason === undefined ? {} : { reason: decision.reason }),
|
|
934
|
+
},
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
//# sourceMappingURL=client.js.map
|