@paperclipai/server 2026.824.0 → 2026.825.0-beta.1
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/dist/adapters/builtin-adapter-types.d.ts.map +1 -1
- package/dist/adapters/builtin-adapter-types.js +1 -0
- package/dist/adapters/builtin-adapter-types.js.map +1 -1
- package/dist/adapters/plugin-loader.d.ts +1 -0
- package/dist/adapters/plugin-loader.d.ts.map +1 -1
- package/dist/adapters/plugin-loader.js +12 -1
- package/dist/adapters/plugin-loader.js.map +1 -1
- package/dist/adapters/plugin-loader.test.d.ts +2 -0
- package/dist/adapters/plugin-loader.test.d.ts.map +1 -0
- package/dist/adapters/plugin-loader.test.js +37 -0
- package/dist/adapters/plugin-loader.test.js.map +1 -0
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +68 -5
- package/dist/adapters/registry.js.map +1 -1
- package/dist/adapters/registry.test.d.ts +2 -0
- package/dist/adapters/registry.test.d.ts.map +1 -0
- package/dist/adapters/registry.test.js +35 -0
- package/dist/adapters/registry.test.js.map +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +5 -7
- package/dist/app.js.map +1 -1
- package/dist/auth/better-auth.d.ts +10 -0
- package/dist/auth/better-auth.d.ts.map +1 -1
- package/dist/auth/better-auth.js +47 -0
- package/dist/auth/better-auth.js.map +1 -1
- package/dist/auth/workspace-login-handoff-exchange.d.ts +75 -0
- package/dist/auth/workspace-login-handoff-exchange.d.ts.map +1 -0
- package/dist/auth/workspace-login-handoff-exchange.js +73 -0
- package/dist/auth/workspace-login-handoff-exchange.js.map +1 -0
- package/dist/auth/workspace-login-handoff-plugin.d.ts +40 -0
- package/dist/auth/workspace-login-handoff-plugin.d.ts.map +1 -0
- package/dist/auth/workspace-login-handoff-plugin.js +140 -0
- package/dist/auth/workspace-login-handoff-plugin.js.map +1 -0
- package/dist/auth/workspace-login-handoff.d.ts +189 -0
- package/dist/auth/workspace-login-handoff.d.ts.map +1 -0
- package/dist/auth/workspace-login-handoff.js +319 -0
- package/dist/auth/workspace-login-handoff.js.map +1 -0
- package/dist/build-info.json +3 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -0
- package/dist/config.js.map +1 -1
- package/dist/dev-runner-worktree.d.ts.map +1 -1
- package/dist/dev-runner-worktree.js +5 -0
- package/dist/dev-runner-worktree.js.map +1 -1
- package/dist/duplex-aggregate-ceiling-env.d.ts +21 -0
- package/dist/duplex-aggregate-ceiling-env.d.ts.map +1 -0
- package/dist/duplex-aggregate-ceiling-env.js +23 -0
- package/dist/duplex-aggregate-ceiling-env.js.map +1 -0
- package/dist/embedded-postgres-supervisor.d.ts +27 -0
- package/dist/embedded-postgres-supervisor.d.ts.map +1 -0
- package/dist/embedded-postgres-supervisor.js +72 -0
- package/dist/embedded-postgres-supervisor.js.map +1 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +115 -7
- package/dist/index.js.map +1 -1
- package/dist/instrumentation.d.ts +33 -0
- package/dist/instrumentation.d.ts.map +1 -1
- package/dist/instrumentation.js +68 -1
- package/dist/instrumentation.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +35 -10
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +8 -1
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +5 -2
- package/dist/middleware/logger.js.map +1 -1
- package/dist/middleware/redact-sensitive.d.ts.map +1 -1
- package/dist/middleware/redact-sensitive.js +4 -0
- package/dist/middleware/redact-sensitive.js.map +1 -1
- package/dist/middleware/validate.d.ts +3 -1
- package/dist/middleware/validate.d.ts.map +1 -1
- package/dist/middleware/validate.js +37 -0
- package/dist/middleware/validate.js.map +1 -1
- package/dist/routes/access.d.ts.map +1 -1
- package/dist/routes/access.js +20 -0
- package/dist/routes/access.js.map +1 -1
- package/dist/routes/activity.js +4 -4
- package/dist/routes/activity.js.map +1 -1
- package/dist/routes/adapter-login-route-spine.d.ts +81 -0
- package/dist/routes/adapter-login-route-spine.d.ts.map +1 -0
- package/dist/routes/adapter-login-route-spine.js +40 -0
- package/dist/routes/adapter-login-route-spine.js.map +1 -0
- package/dist/routes/adapters.d.ts +33 -0
- package/dist/routes/adapters.d.ts.map +1 -1
- package/dist/routes/adapters.js +35 -1
- package/dist/routes/adapters.js.map +1 -1
- package/dist/routes/adapters.test.d.ts +2 -0
- package/dist/routes/adapters.test.d.ts.map +1 -0
- package/dist/routes/adapters.test.js +58 -0
- package/dist/routes/adapters.test.js.map +1 -0
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +281 -91
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/cases.d.ts +11 -22
- package/dist/routes/cases.d.ts.map +1 -1
- package/dist/routes/cases.js +13 -13
- package/dist/routes/companies.js +3 -3
- package/dist/routes/decision-training.js +6 -6
- package/dist/routes/decisions.js +4 -4
- package/dist/routes/decisions.js.map +1 -1
- package/dist/routes/environments.d.ts.map +1 -1
- package/dist/routes/environments.js +79 -6
- package/dist/routes/environments.js.map +1 -1
- package/dist/routes/execution-workspaces.d.ts.map +1 -1
- package/dist/routes/execution-workspaces.js +384 -16
- package/dist/routes/execution-workspaces.js.map +1 -1
- package/dist/routes/file-resources.js +2 -2
- package/dist/routes/health.d.ts.map +1 -1
- package/dist/routes/health.js +58 -4
- package/dist/routes/health.js.map +1 -1
- package/dist/routes/instance-settings.d.ts.map +1 -1
- package/dist/routes/instance-settings.js +40 -0
- package/dist/routes/instance-settings.js.map +1 -1
- package/dist/routes/issues.d.ts +10 -0
- package/dist/routes/issues.d.ts.map +1 -1
- package/dist/routes/issues.js +495 -65
- package/dist/routes/issues.js.map +1 -1
- package/dist/routes/openapi.d.ts.map +1 -1
- package/dist/routes/openapi.js +241 -122
- package/dist/routes/openapi.js.map +1 -1
- package/dist/routes/pipelines.js +19 -19
- package/dist/routes/plugins.d.ts.map +1 -1
- package/dist/routes/plugins.js +22 -0
- package/dist/routes/plugins.js.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +2 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/routines.js +2 -2
- package/dist/routes/routines.js.map +1 -1
- package/dist/routes/secrets.d.ts +1 -1
- package/dist/routes/secrets.d.ts.map +1 -1
- package/dist/routes/secrets.js +39 -50
- package/dist/routes/secrets.js.map +1 -1
- package/dist/routes/setup-token-route.test.js +50 -3
- package/dist/routes/setup-token-route.test.js.map +1 -1
- package/dist/services/adapter-login-lease.d.ts +50 -0
- package/dist/services/adapter-login-lease.d.ts.map +1 -0
- package/dist/services/adapter-login-lease.js +26 -0
- package/dist/services/adapter-login-lease.js.map +1 -0
- package/dist/services/adapter-login-lease.test.d.ts +2 -0
- package/dist/services/adapter-login-lease.test.d.ts.map +1 -0
- package/dist/services/adapter-login-lease.test.js +68 -0
- package/dist/services/adapter-login-lease.test.js.map +1 -0
- package/dist/services/agent-action-audit.js +1 -1
- package/dist/services/agent-secret-bindings.d.ts +15 -0
- package/dist/services/agent-secret-bindings.d.ts.map +1 -1
- package/dist/services/agent-secret-bindings.js +2 -2
- package/dist/services/agent-secret-bindings.js.map +1 -1
- package/dist/services/agents.d.ts +13 -13
- package/dist/services/agents.d.ts.map +1 -1
- package/dist/services/agents.js +46 -5
- package/dist/services/agents.js.map +1 -1
- package/dist/services/artifact-review-documents.d.ts +34 -0
- package/dist/services/artifact-review-documents.d.ts.map +1 -0
- package/dist/services/artifact-review-documents.js +196 -0
- package/dist/services/artifact-review-documents.js.map +1 -0
- package/dist/services/assets.d.ts +1 -1
- package/dist/services/codex-device-login-credential-read.d.ts +58 -0
- package/dist/services/codex-device-login-credential-read.d.ts.map +1 -0
- package/dist/services/codex-device-login-credential-read.js +118 -0
- package/dist/services/codex-device-login-credential-read.js.map +1 -0
- package/dist/services/codex-device-login-reaper.d.ts.map +1 -1
- package/dist/services/codex-device-login-reaper.js +8 -5
- package/dist/services/codex-device-login-reaper.js.map +1 -1
- package/dist/services/codex-device-login-service.d.ts +127 -36
- package/dist/services/codex-device-login-service.d.ts.map +1 -1
- package/dist/services/codex-device-login-service.js +204 -84
- package/dist/services/codex-device-login-service.js.map +1 -1
- package/dist/services/company-portability.d.ts +3 -1
- package/dist/services/company-portability.d.ts.map +1 -1
- package/dist/services/company-portability.js +76 -20
- package/dist/services/company-portability.js.map +1 -1
- package/dist/services/company-skill-policy.d.ts +1 -1
- package/dist/services/costs.d.ts +1 -1
- package/dist/services/decisions.d.ts +6 -6
- package/dist/services/duplex-observability-recorder.d.ts +62 -0
- package/dist/services/duplex-observability-recorder.d.ts.map +1 -0
- package/dist/services/duplex-observability-recorder.js +54 -0
- package/dist/services/duplex-observability-recorder.js.map +1 -0
- package/dist/services/environment-config.js +5 -5
- package/dist/services/environment-config.js.map +1 -1
- package/dist/services/environment-custom-image-runtime.d.ts +116 -0
- package/dist/services/environment-custom-image-runtime.d.ts.map +1 -1
- package/dist/services/environment-custom-image-runtime.js +255 -1
- package/dist/services/environment-custom-image-runtime.js.map +1 -1
- package/dist/services/environment-custom-images.d.ts +39 -0
- package/dist/services/environment-custom-images.d.ts.map +1 -1
- package/dist/services/environment-custom-images.js +219 -17
- package/dist/services/environment-custom-images.js.map +1 -1
- package/dist/services/environment-driver-traits.d.ts +109 -0
- package/dist/services/environment-driver-traits.d.ts.map +1 -0
- package/dist/services/environment-driver-traits.js +102 -0
- package/dist/services/environment-driver-traits.js.map +1 -0
- package/dist/services/environment-execution-target.d.ts +4 -0
- package/dist/services/environment-execution-target.d.ts.map +1 -1
- package/dist/services/environment-execution-target.js +63 -7
- package/dist/services/environment-execution-target.js.map +1 -1
- package/dist/services/environment-run-orchestrator.d.ts +27 -1
- package/dist/services/environment-run-orchestrator.d.ts.map +1 -1
- package/dist/services/environment-run-orchestrator.js +24 -4
- package/dist/services/environment-run-orchestrator.js.map +1 -1
- package/dist/services/environment-runtime.d.ts +118 -20
- package/dist/services/environment-runtime.d.ts.map +1 -1
- package/dist/services/environment-runtime.js +436 -91
- package/dist/services/environment-runtime.js.map +1 -1
- package/dist/services/environments.d.ts.map +1 -1
- package/dist/services/environments.js +20 -2
- package/dist/services/environments.js.map +1 -1
- package/dist/services/execution-workspace-branch-ownership.d.ts +4 -0
- package/dist/services/execution-workspace-branch-ownership.d.ts.map +1 -0
- package/dist/services/execution-workspace-branch-ownership.js +9 -0
- package/dist/services/execution-workspace-branch-ownership.js.map +1 -0
- package/dist/services/execution-workspace-policy.d.ts.map +1 -1
- package/dist/services/execution-workspace-policy.js +3 -0
- package/dist/services/execution-workspace-policy.js.map +1 -1
- package/dist/services/execution-workspaces.d.ts +2 -0
- package/dist/services/execution-workspaces.d.ts.map +1 -1
- package/dist/services/execution-workspaces.js +90 -2
- package/dist/services/execution-workspaces.js.map +1 -1
- package/dist/services/external-objects.d.ts +19 -19
- package/dist/services/finance.d.ts +1 -1
- package/dist/services/goals.d.ts +2 -2
- package/dist/services/heartbeat-policy.d.ts +3 -0
- package/dist/services/heartbeat-policy.d.ts.map +1 -0
- package/dist/services/heartbeat-policy.js +10 -0
- package/dist/services/heartbeat-policy.js.map +1 -0
- package/dist/services/heartbeat-run-runtime-status.test.js +1 -1
- package/dist/services/heartbeat-run-runtime-status.test.js.map +1 -1
- package/dist/services/heartbeat.d.ts +23 -1
- package/dist/services/heartbeat.d.ts.map +1 -1
- package/dist/services/heartbeat.js +192 -11
- package/dist/services/heartbeat.js.map +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/instance-settings.d.ts.map +1 -1
- package/dist/services/instance-settings.js +2 -0
- package/dist/services/instance-settings.js.map +1 -1
- package/dist/services/issue-dependency-wakeups.d.ts +57 -9
- package/dist/services/issue-dependency-wakeups.d.ts.map +1 -1
- package/dist/services/issue-dependency-wakeups.js +146 -14
- package/dist/services/issue-dependency-wakeups.js.map +1 -1
- package/dist/services/issue-dependency-wakeups.test.d.ts +2 -0
- package/dist/services/issue-dependency-wakeups.test.d.ts.map +1 -0
- package/dist/services/issue-dependency-wakeups.test.js +183 -0
- package/dist/services/issue-dependency-wakeups.test.js.map +1 -0
- package/dist/services/issue-recovery-actions.d.ts +6 -1
- package/dist/services/issue-recovery-actions.d.ts.map +1 -1
- package/dist/services/issue-recovery-actions.js +123 -44
- package/dist/services/issue-recovery-actions.js.map +1 -1
- package/dist/services/issue-thread-interactions.d.ts +8 -0
- package/dist/services/issue-thread-interactions.d.ts.map +1 -1
- package/dist/services/issue-thread-interactions.js +220 -10
- package/dist/services/issue-thread-interactions.js.map +1 -1
- package/dist/services/issues.d.ts +8 -7
- package/dist/services/issues.d.ts.map +1 -1
- package/dist/services/issues.js +84 -12
- package/dist/services/issues.js.map +1 -1
- package/dist/services/local-service-supervisor.d.ts +61 -1
- package/dist/services/local-service-supervisor.d.ts.map +1 -1
- package/dist/services/local-service-supervisor.js +221 -25
- package/dist/services/local-service-supervisor.js.map +1 -1
- package/dist/services/login-command.d.ts +46 -0
- package/dist/services/login-command.d.ts.map +1 -0
- package/dist/services/login-command.js +87 -0
- package/dist/services/login-command.js.map +1 -0
- package/dist/services/login-command.test.d.ts +2 -0
- package/dist/services/login-command.test.d.ts.map +1 -0
- package/dist/services/login-command.test.js +71 -0
- package/dist/services/login-command.test.js.map +1 -0
- package/dist/services/managed-workspace-identity.d.ts +140 -0
- package/dist/services/managed-workspace-identity.d.ts.map +1 -0
- package/dist/services/managed-workspace-identity.js +277 -0
- package/dist/services/managed-workspace-identity.js.map +1 -0
- package/dist/services/plugin-environment-driver.d.ts +15 -1
- package/dist/services/plugin-environment-driver.d.ts.map +1 -1
- package/dist/services/plugin-environment-driver.js +23 -1
- package/dist/services/plugin-environment-driver.js.map +1 -1
- package/dist/services/plugin-host-services.d.ts +3 -2
- package/dist/services/plugin-host-services.d.ts.map +1 -1
- package/dist/services/plugin-host-services.js +11 -2
- package/dist/services/plugin-host-services.js.map +1 -1
- package/dist/services/plugin-loader.d.ts.map +1 -1
- package/dist/services/plugin-loader.js +39 -8
- package/dist/services/plugin-loader.js.map +1 -1
- package/dist/services/plugin-managed-agents.d.ts.map +1 -1
- package/dist/services/plugin-managed-agents.js +50 -5
- package/dist/services/plugin-managed-agents.js.map +1 -1
- package/dist/services/plugin-manifest-validator.d.ts.map +1 -1
- package/dist/services/plugin-manifest-validator.js +5 -2
- package/dist/services/plugin-manifest-validator.js.map +1 -1
- package/dist/services/plugin-registry.d.ts +5 -5
- package/dist/services/plugin-worker-manager.d.ts +158 -11
- package/dist/services/plugin-worker-manager.d.ts.map +1 -1
- package/dist/services/plugin-worker-manager.js +1139 -79
- package/dist/services/plugin-worker-manager.js.map +1 -1
- package/dist/services/projects.d.ts +1 -1
- package/dist/services/recovery/disposition-repair.d.ts +24 -0
- package/dist/services/recovery/disposition-repair.d.ts.map +1 -0
- package/dist/services/recovery/disposition-repair.js +125 -0
- package/dist/services/recovery/disposition-repair.js.map +1 -0
- package/dist/services/recovery/service.d.ts +6 -6
- package/dist/services/recovery/service.d.ts.map +1 -1
- package/dist/services/recovery/service.js +856 -384
- package/dist/services/recovery/service.js.map +1 -1
- package/dist/services/recovery/stranded-notice.js +4 -4
- package/dist/services/recovery/stranded-notice.js.map +1 -1
- package/dist/services/recovery/stranded-notice.test.js +1 -1
- package/dist/services/recovery/stranded-notice.test.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.d.ts +1 -1
- package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
- package/dist/services/recovery/successful-run-handoff.js +6 -4
- package/dist/services/recovery/successful-run-handoff.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.test.js +1 -1
- package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
- package/dist/services/recovery-observability.d.ts +1 -1
- package/dist/services/recovery-observability.d.ts.map +1 -1
- package/dist/services/recovery-observability.js +4 -1
- package/dist/services/recovery-observability.js.map +1 -1
- package/dist/services/routines.d.ts.map +1 -1
- package/dist/services/routines.js +86 -1
- package/dist/services/routines.js.map +1 -1
- package/dist/services/runtime-exposure/loopback-listener.js +1 -1
- package/dist/services/runtime-exposure/loopback-listener.js.map +1 -1
- package/dist/services/runtime-exposure/loopback-listener.test.js +1 -1
- package/dist/services/runtime-exposure/loopback-listener.test.js.map +1 -1
- package/dist/services/scripts/codex-auth-read.cjs +93 -0
- package/dist/services/secret-proposal-authorization.d.ts +15 -0
- package/dist/services/secret-proposal-authorization.d.ts.map +1 -0
- package/dist/services/secret-proposal-authorization.js +29 -0
- package/dist/services/secret-proposal-authorization.js.map +1 -0
- package/dist/services/secret-proposal-notifications.d.ts +18 -0
- package/dist/services/secret-proposal-notifications.d.ts.map +1 -0
- package/dist/services/secret-proposal-notifications.js +37 -0
- package/dist/services/secret-proposal-notifications.js.map +1 -0
- package/dist/services/secret-proposals.d.ts +20 -10
- package/dist/services/secret-proposals.d.ts.map +1 -1
- package/dist/services/secret-proposals.js +205 -14
- package/dist/services/secret-proposals.js.map +1 -1
- package/dist/services/secrets.d.ts +3 -3
- package/dist/services/settings-visibility.d.ts +17 -0
- package/dist/services/settings-visibility.d.ts.map +1 -0
- package/dist/services/settings-visibility.js +29 -0
- package/dist/services/settings-visibility.js.map +1 -0
- package/dist/services/setup-token-reaper.d.ts +36 -0
- package/dist/services/setup-token-reaper.d.ts.map +1 -0
- package/dist/services/setup-token-reaper.js +38 -0
- package/dist/services/setup-token-reaper.js.map +1 -0
- package/dist/services/setup-token-reaper.test.d.ts +2 -0
- package/dist/services/setup-token-reaper.test.d.ts.map +1 -0
- package/dist/services/setup-token-reaper.test.js +123 -0
- package/dist/services/setup-token-reaper.test.js.map +1 -0
- package/dist/services/setup-token-session.d.ts +57 -45
- package/dist/services/setup-token-session.d.ts.map +1 -1
- package/dist/services/setup-token-session.js +118 -110
- package/dist/services/setup-token-session.js.map +1 -1
- package/dist/services/setup-token-session.test.js +88 -47
- package/dist/services/setup-token-session.test.js.map +1 -1
- package/dist/services/setup-token-transport-binding.d.ts +20 -12
- package/dist/services/setup-token-transport-binding.d.ts.map +1 -1
- package/dist/services/setup-token-transport-binding.js +59 -32
- package/dist/services/setup-token-transport-binding.js.map +1 -1
- package/dist/services/setup-token-transport-binding.test.js +50 -17
- package/dist/services/setup-token-transport-binding.test.js.map +1 -1
- package/dist/services/smoke-lab.d.ts +1 -1
- package/dist/services/stalled-review-decisions.d.ts +1 -1
- package/dist/services/status-cards.d.ts +168 -168
- package/dist/services/tool-access-policy.d.ts +2 -2
- package/dist/services/tool-gateway.d.ts +1 -1
- package/dist/services/work-products.d.ts +19 -0
- package/dist/services/work-products.d.ts.map +1 -1
- package/dist/services/work-products.js +50 -3
- package/dist/services/work-products.js.map +1 -1
- package/dist/services/workspace-git-operation-scheduler.test.js +10 -3
- package/dist/services/workspace-git-operation-scheduler.test.js.map +1 -1
- package/dist/services/workspace-instance-cleanup.d.ts +9 -0
- package/dist/services/workspace-instance-cleanup.d.ts.map +1 -1
- package/dist/services/workspace-instance-cleanup.js +29 -3
- package/dist/services/workspace-instance-cleanup.js.map +1 -1
- package/dist/services/workspace-login-handoff-issuer.d.ts +95 -0
- package/dist/services/workspace-login-handoff-issuer.d.ts.map +1 -0
- package/dist/services/workspace-login-handoff-issuer.js +147 -0
- package/dist/services/workspace-login-handoff-issuer.js.map +1 -0
- package/dist/services/workspace-operations.d.ts +4 -1
- package/dist/services/workspace-operations.d.ts.map +1 -1
- package/dist/services/workspace-operations.js +29 -15
- package/dist/services/workspace-operations.js.map +1 -1
- package/dist/services/workspace-readiness.d.ts +56 -0
- package/dist/services/workspace-readiness.d.ts.map +1 -0
- package/dist/services/workspace-readiness.js +250 -0
- package/dist/services/workspace-readiness.js.map +1 -0
- package/dist/services/workspace-realization.d.ts.map +1 -1
- package/dist/services/workspace-realization.js +5 -33
- package/dist/services/workspace-realization.js.map +1 -1
- package/dist/services/workspace-runtime-exposure.test.js +321 -12
- package/dist/services/workspace-runtime-exposure.test.js.map +1 -1
- package/dist/services/workspace-runtime-leases.d.ts.map +1 -1
- package/dist/services/workspace-runtime-leases.js +1 -1
- package/dist/services/workspace-runtime-leases.js.map +1 -1
- package/dist/services/workspace-runtime-read-model.d.ts +8 -8
- package/dist/services/workspace-runtime-read-model.test.js +20 -0
- package/dist/services/workspace-runtime-read-model.test.js.map +1 -1
- package/dist/services/workspace-runtime-ready-comment.test.js +1 -0
- package/dist/services/workspace-runtime-ready-comment.test.js.map +1 -1
- package/dist/services/workspace-runtime.d.ts +77 -4
- package/dist/services/workspace-runtime.d.ts.map +1 -1
- package/dist/services/workspace-runtime.js +1020 -126
- package/dist/services/workspace-runtime.js.map +1 -1
- package/dist/worktree-config.d.ts.map +1 -1
- package/dist/worktree-config.js +3 -76
- package/dist/worktree-config.js.map +1 -1
- package/dist/worktree-seed-manifest.d.ts +8 -0
- package/dist/worktree-seed-manifest.d.ts.map +1 -0
- package/dist/worktree-seed-manifest.js +47 -0
- package/dist/worktree-seed-manifest.js.map +1 -0
- package/package.json +34 -30
- package/skills/paperclip/SKILL.md +2 -0
- package/skills/paperclip/references/api-reference.md +44 -2
- package/ui-dist/assets/CompanyExport-DnEsO-St.js +4 -0
- package/ui-dist/assets/{abnfDiagram-N423BO3Z-BvgoV-u5.js → abnfDiagram-N423BO3Z-2ff8TsQ0.js} +1 -1
- package/ui-dist/assets/{arc-BInnUBUU.js → arc-B2AXsH34.js} +1 -1
- package/ui-dist/assets/architectureDiagram-T3A2C74G-BDxtKMxk.js +36 -0
- package/ui-dist/assets/{blockDiagram-VBNYF7ZC-D9kzAkLN.js → blockDiagram-VBNYF7ZC-BB8T5Mj5.js} +1 -1
- package/ui-dist/assets/{c4Diagram-5PPSVZJV-BwzsgV_0.js → c4Diagram-5PPSVZJV-lMo8qk-x.js} +1 -1
- package/ui-dist/assets/channel-DCTVZpyq.js +1 -0
- package/ui-dist/assets/{chunk-2GRJ4B5K-D2EQ9vrl.js → chunk-2GRJ4B5K-CsS7EB3G.js} +1 -1
- package/ui-dist/assets/{chunk-2Q5K7J3B-DOA_8fSd.js → chunk-2Q5K7J3B-DFyQPjoR.js} +1 -1
- package/ui-dist/assets/{chunk-5RXB4S5H-CT5ukRiT.js → chunk-5RXB4S5H-No2SHOQR.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-D2gOlkyB.js → chunk-5VM5RSS4-DdxQO7V9.js} +1 -1
- package/ui-dist/assets/{chunk-6Q2QTUOP-DUb6aG8c.js → chunk-6Q2QTUOP-gbHjh-aK.js} +1 -1
- package/ui-dist/assets/{chunk-GF5L2VYU-BPabG3Cx.js → chunk-GF5L2VYU-h-BBl6NY.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-scNfhlZz.js → chunk-JWPE2WC7-Q3pJdTz5.js} +1 -1
- package/ui-dist/assets/{chunk-KBJHAD2P-BcRAzRpq.js → chunk-KBJHAD2P-Ba8LGLSx.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-BiZ0-EGh.js → chunk-RYQCIY6F-9VcvykBo.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-lJULxFIE.js → chunk-XXDRQBXY-NVbjDH4W.js} +1 -1
- package/ui-dist/assets/classDiagram-JCYQIIEL-CzJ88u6h.js +1 -0
- package/ui-dist/assets/classDiagram-v2-OCEON4UE-CzJ88u6h.js +1 -0
- package/ui-dist/assets/cose-bilkent-JH36ORCC-Cdz4wtUh.js +1 -0
- package/ui-dist/assets/{cynefin-VYW2F7L2-B34jJY1x.js → cynefin-VYW2F7L2-MpzJkW5s.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-MW4NZA55-DQ8QK8JK.js → cynefinDiagram-MW4NZA55-_Nx8av7i.js} +1 -1
- package/ui-dist/assets/{dagre-VZM6K2ZE-B7lSKgxH.js → dagre-VZM6K2ZE-DcZTQ4Oh.js} +1 -1
- package/ui-dist/assets/{diagram-7IWD3JNH-B3hLAFGE.js → diagram-7IWD3JNH-UyLi2mee.js} +1 -1
- package/ui-dist/assets/{diagram-B4RE2ZJO-CH9Ro9e0.js → diagram-B4RE2ZJO-B6p0Ivqg.js} +1 -1
- package/ui-dist/assets/{diagram-LBJQPF4R-DdPVMii7.js → diagram-LBJQPF4R-C8u6pa97.js} +1 -1
- package/ui-dist/assets/{diagram-Q27KOJAE-f5VXswjc.js → diagram-Q27KOJAE-DbwyagW0.js} +1 -1
- package/ui-dist/assets/{diagram-UB23O5K3-DGqxixsR.js → diagram-UB23O5K3-Cn5BMEH7.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-BXEA7PRR-C-1klg_w.js → ebnfDiagram-BXEA7PRR-vE0IZma9.js} +1 -1
- package/ui-dist/assets/{erDiagram-JOGREHBK-Dt4qK4gv.js → erDiagram-JOGREHBK-3OZVIlVG.js} +1 -1
- package/ui-dist/assets/{flowDiagram-UKHOOZJN-9ZlrTuET.js → flowDiagram-UKHOOZJN-C94FiPyr.js} +1 -1
- package/ui-dist/assets/ganttDiagram-PKOTCBZU-DMVaPmF-.js +292 -0
- package/ui-dist/assets/{gitGraphDiagram-DS77QQ5N-HH2fSgad.js → gitGraphDiagram-DS77QQ5N-yeFtJ689.js} +1 -1
- package/ui-dist/assets/{index-Cm6iEYPt.js → index-B4ZF3vY8.js} +288 -224
- package/ui-dist/assets/{index-CHXG4GPL.js → index-Bi_vqkcQ.js} +1 -1
- package/ui-dist/assets/{index-Bc9g6q63.js → index-BjDGQg9-.js} +1 -1
- package/ui-dist/assets/{index-FHzrJ7iQ.js → index-BnpyUMTb.js} +1 -1
- package/ui-dist/assets/{index-C1mpWCcn.js → index-BoqQTVMA.js} +1 -1
- package/ui-dist/assets/index-Bq-Mr-4x.js +1 -0
- package/ui-dist/assets/{index-DceuCrr8.js → index-Brb2U7N4.js} +1 -1
- package/ui-dist/assets/{index-DQIrrn2L.js → index-BsBybVwH.js} +1 -1
- package/ui-dist/assets/{index-CQhaM6qd.js → index-C2iv4Wgu.js} +1 -1
- package/ui-dist/assets/{index-DV2FOgyD.js → index-CKxIu7uO.js} +1 -1
- package/ui-dist/assets/{index-DU4U1fuv.js → index-Cb4VGIwp.js} +1 -1
- package/ui-dist/assets/{index-B61ORkIb.js → index-ChpszwcO.js} +1 -1
- package/ui-dist/assets/{index-DlVBBF8o.js → index-CoQFdT8N.js} +1 -1
- package/ui-dist/assets/index-D6P8_f0W.css +1 -0
- package/ui-dist/assets/index-DKdmghUG.js +1 -0
- package/ui-dist/assets/{index-CVTL3aAL.js → index-DaBci7Bx.js} +1 -1
- package/ui-dist/assets/{index-diFs0CNC.js → index-DjYaNiXZ.js} +1 -1
- package/ui-dist/assets/{index-Bf7tyGxE.js → index-DxTBJl4h.js} +1 -1
- package/ui-dist/assets/{index-DsdVneqe.js → index-Dz3E8nn0.js} +1 -1
- package/ui-dist/assets/{index-DvFUXI-Q.js → index-J7dz_hap.js} +1 -1
- package/ui-dist/assets/{index-CLu3Tfpv.js → index-JMp2Gpnz.js} +1 -1
- package/ui-dist/assets/{index-CcRTJ93J.js → index-Kp6wavQt.js} +1 -1
- package/ui-dist/assets/{index-BvFx-4KW.js → index-LBhYZ0L4.js} +1 -1
- package/ui-dist/assets/{index-BbAhzCq8.js → index-c3C0P6l8.js} +4 -4
- package/ui-dist/assets/{index-BY5ITKmG.js → index-pBEPheTW.js} +1 -1
- package/ui-dist/assets/{infoDiagram-6WML65LV-2jai2fw-.js → infoDiagram-6WML65LV-BiL7jKLA.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-WSZJBQD7-CUmGhmEb.js → ishikawaDiagram-WSZJBQD7-DYcQy41D.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-NVQOT4AX-CGQuPDO1.js → journeyDiagram-NVQOT4AX-Bxva6JgA.js} +1 -1
- package/ui-dist/assets/{kanban-definition-27J2QSJJ-zgEPcbHl.js → kanban-definition-27J2QSJJ-B2HpN34Q.js} +1 -1
- package/ui-dist/assets/{linear-BVf5VtLS.js → linear-Dq8qSESw.js} +1 -1
- package/ui-dist/assets/{mermaid.core-D2TFkGfI.js → mermaid.core-Ikay8Cpl.js} +35 -35
- package/ui-dist/assets/{mindmap-definition-FAOFIHXS-xoAQ0Lb_.js → mindmap-definition-FAOFIHXS-C-SIdYSY.js} +1 -1
- package/ui-dist/assets/{pegDiagram-VL7TDLO6-CBR1PWLr.js → pegDiagram-VL7TDLO6-C7rIJ_13.js} +1 -1
- package/ui-dist/assets/{pieDiagram-7S7Q4E2Y-BMPnzK_e.js → pieDiagram-7S7Q4E2Y-3gx0a0ve.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-CIZ2JOQS-CPtVUPkR.js → quadrantDiagram-CIZ2JOQS-BiwM9QGv.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-AXF67PYL-DC0lsZV1.js → railroadDiagram-AXF67PYL-rFS8XcFA.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-LRYGKXZP-BF6k05SB.js → requirementDiagram-LRYGKXZP-CEAUDUTQ.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-W5VNT64P-CRN0ibiP.js → sankeyDiagram-W5VNT64P-B7anpjlM.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-SI44F4Z6-CQtTiPWm.js → sequenceDiagram-SI44F4Z6-CJEdJvm_.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-BdjuGZd1.js → sizeCapture-X5ZJPWSS-CU1Vm6c1.js} +1 -1
- package/ui-dist/assets/{stateDiagram-OKZ733FA-B99onxyh.js → stateDiagram-OKZ733FA-wxVV9WIi.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-UEYNNEHI-BIFLqlqR.js +1 -0
- package/ui-dist/assets/{swimlanes-SLNWSIFB-BIByPbrL.js → swimlanes-SLNWSIFB-Cd-C1Z_k.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-ULZ7WXOC-CoBROkkd.js +8 -0
- package/ui-dist/assets/{timeline-definition-Z64GVDOM-I1NgOcn9.js → timeline-definition-Z64GVDOM-SWngk4aR.js} +1 -1
- package/ui-dist/assets/{vennDiagram-T6HMQDX7-D6t2Njcl.js → vennDiagram-T6HMQDX7-DFdPUr36.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-T6FBY63Y-BiYKm9gh.js → wardleyDiagram-T6FBY63Y-C6IlrZ7t.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-ELKLHX3M-BhwXKWIa.js → xychartDiagram-ELKLHX3M-BNm6hHGl.js} +1 -1
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/architectureDiagram-T3A2C74G-Dg4MziOm.js +0 -36
- package/ui-dist/assets/channel-qoSYbCn0.js +0 -1
- package/ui-dist/assets/classDiagram-JCYQIIEL-B24u1REs.js +0 -1
- package/ui-dist/assets/classDiagram-v2-OCEON4UE-B24u1REs.js +0 -1
- package/ui-dist/assets/cose-bilkent-JH36ORCC-Do8pe8JB.js +0 -1
- package/ui-dist/assets/ganttDiagram-PKOTCBZU-CE3lyvFq.js +0 -292
- package/ui-dist/assets/index-BHiUiToL.css +0 -1
- package/ui-dist/assets/index-hkanj4t6.js +0 -1
- package/ui-dist/assets/index-yRJnh4vx.js +0 -1
- package/ui-dist/assets/stateDiagram-v2-UEYNNEHI-bzFlYBZ1.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-ULZ7WXOC-DgdkBnuK.js +0 -8
package/dist/routes/agents.js
CHANGED
|
@@ -3,7 +3,7 @@ import { generateKeyPairSync, randomUUID } from "node:crypto";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { agents as agentsTable, companies, heartbeatRuns, issues as issuesTable, projects as projectsTable } from "@paperclipai/db";
|
|
5
5
|
import { and, desc, eq, inArray, not, sql } from "drizzle-orm";
|
|
6
|
-
import { agentSkillSyncSchema, agentMineInboxQuerySchema, ADAPTER_AGNOSTIC_KEYS, AGENT_DEFAULT_MAX_CONCURRENT_RUNS, createAgentKeySchema, createAgentHireSchema, createAgentSchema, deriveAgentUrlKey, isUuidLike, normalizeIssueIdentifier, resetAgentSessionSchema, testAdapterEnvironmentSchema, upsertAgentInstructionsFileSchema, updateAgentInstructionsBundleSchema, updateAgentPermissionsSchema, updateAgentInstructionsPathSchema, wakeAgentSchema, updateAgentSchema, supportedEnvironmentDriversForAdapter, LOW_TRUST_REVIEW_PRESET, startClaudeSetupTokenSessionRequestSchema, submitBrowserCodeRequestSchema, } from "@paperclipai/shared";
|
|
6
|
+
import { agentSkillSyncSchema, agentMineInboxQuerySchema, ADAPTER_AGNOSTIC_KEYS, AGENT_DEFAULT_MAX_CONCURRENT_RUNS, createAgentKeySchema, createAgentHireSchema, createAgentSchema, deriveAgentUrlKey, isUuidLike, normalizeIssueIdentifier, resetAgentSessionSchema, testAdapterEnvironmentSchema, upsertAgentInstructionsFileSchema, updateAgentInstructionsBundleSchema, updateAgentPermissionsSchema, updateAgentInstructionsPathSchema, wakeAgentSchema, updateAgentSchema, supportedEnvironmentDriversForAdapter, LOW_TRUST_REVIEW_PRESET, startAdapterAuthSessionRequestSchema, startClaudeSetupTokenSessionRequestSchema, submitBrowserCodeRequestSchema, } from "@paperclipai/shared";
|
|
7
7
|
import { isForbiddenConfigEnvKey, parseObject, resolvePaperclipInstanceRootForAdapter, readPaperclipSkillSyncPreference, writePaperclipSkillSyncPreference, } from "@paperclipai/adapter-utils/server-utils";
|
|
8
8
|
import { trackAgentCreated } from "@paperclipai/shared/telemetry";
|
|
9
9
|
import { validate } from "../middleware/validate.js";
|
|
@@ -11,6 +11,8 @@ import { agentService, agentInstructionsService, accessService, approvalService,
|
|
|
11
11
|
import { badRequest, conflict, forbidden, HttpError, notFound, unprocessable } from "../errors.js";
|
|
12
12
|
import { createRunSecretRedactionRegistry } from "../services/run-secret-redaction.js";
|
|
13
13
|
import { assertAuthenticated, assertBoard, assertCompanyAccess, assertInstanceAdmin, buildActorSecretContext, getAccessibleResource, getActorInfo, hasCompanyAccess } from "./authz.js";
|
|
14
|
+
import { runAdapterLoginStartSpine } from "./adapter-login-route-spine.js";
|
|
15
|
+
import { isLoginCommandSupportedAdapterType } from "../services/login-command.js";
|
|
14
16
|
import { assertNoAgentHostWorkspaceCommandMutation, collectAgentAdapterWorkspaceCommandPaths, } from "./workspace-command-authz.js";
|
|
15
17
|
import { environmentService } from "../services/environments.js";
|
|
16
18
|
import { resolveEnvironmentExecutionTarget } from "../services/environment-execution-target.js";
|
|
@@ -31,9 +33,10 @@ import { SetupTokenSessionService, SetupTokenSessionError, assessConfidentialSta
|
|
|
31
33
|
import { SETUP_TOKEN_TRANSPORT_ADVISORY_CODE } from "@paperclipai/shared";
|
|
32
34
|
import { DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX } from "@paperclipai/adapter-codex-local";
|
|
33
35
|
import { checkStagedCredentialReadiness, promoteDeviceLoginCredential, } from "@paperclipai/adapter-codex-local/server";
|
|
34
|
-
import { AdapterAuthSessionConflictError,
|
|
36
|
+
import { AdapterAuthSessionConflictError, createCodexDeviceLoginService, createCodexWorkerBoundLoginPtyOpener, createDbAdapterAuthSessionStore, createProductionLoginSessionRuntime, CODEX_DEVICE_LOGIN_PROVIDER_UNSUPPORTED, CODEX_DEVICE_LOGIN_PROVIDER_UNSUPPORTED_CODE, } from "../services/codex-device-login-service.js";
|
|
35
37
|
import { DEFAULT_CURSOR_LOCAL_MODEL } from "@paperclipai/adapter-cursor-local";
|
|
36
38
|
import { DEFAULT_GEMINI_LOCAL_MODEL } from "@paperclipai/adapter-gemini-local";
|
|
39
|
+
import { DEFAULT_KIMI_LOCAL_MODEL } from "@paperclipai/adapter-kimi-local";
|
|
37
40
|
import { DEFAULT_OPENCODE_LOCAL_MODEL } from "@paperclipai/adapter-opencode-local";
|
|
38
41
|
import { requireOpenCodeModelId } from "@paperclipai/adapter-opencode-local/server";
|
|
39
42
|
import { loadDefaultAgentInstructionsBundle, resolveDefaultAgentInstructionsBundleRole, } from "../services/default-agent-instructions.js";
|
|
@@ -97,6 +100,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
97
100
|
codex_local: "instructionsFilePath",
|
|
98
101
|
droid_local: "instructionsFilePath",
|
|
99
102
|
gemini_local: "instructionsFilePath",
|
|
103
|
+
kimi_local: "instructionsFilePath",
|
|
100
104
|
opencode_local: "instructionsFilePath",
|
|
101
105
|
cursor: "instructionsFilePath",
|
|
102
106
|
pi_local: "instructionsFilePath",
|
|
@@ -178,8 +182,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
178
182
|
const setupTokenCleanupRows = new Map();
|
|
179
183
|
const scopeMatchesRow = (row, identity) => row.companyId === identity.companyId &&
|
|
180
184
|
row.ownerUserId === identity.ownerUserId &&
|
|
181
|
-
row.adapterType === identity.adapterType
|
|
182
|
-
row.environmentId === identity.environmentId;
|
|
185
|
+
row.adapterType === identity.adapterType;
|
|
183
186
|
const inMemorySetupTokenCleanupStore = {
|
|
184
187
|
async record(record) {
|
|
185
188
|
setupTokenCleanupRows.set(record.sessionId, { ...record });
|
|
@@ -285,7 +288,27 @@ export function agentRoutes(db, options = {}) {
|
|
|
285
288
|
const adapterLoginStore = createDbAdapterAuthSessionStore(db);
|
|
286
289
|
const adapterLoginService = createCodexDeviceLoginService({
|
|
287
290
|
store: adapterLoginStore,
|
|
288
|
-
runtime: createProductionLoginSessionRuntime({
|
|
291
|
+
runtime: createProductionLoginSessionRuntime({
|
|
292
|
+
db,
|
|
293
|
+
environmentRuntime,
|
|
294
|
+
// Re-check the provider login pseudo-terminal capability from current
|
|
295
|
+
// runtime state immediately before the provider lease. The route gate ran
|
|
296
|
+
// earlier, so a managed reconciliation can rebind the environment to an
|
|
297
|
+
// unsupported provider between the gate and the acquire; this fails closed
|
|
298
|
+
// before the lease and the pseudo-terminal.
|
|
299
|
+
assertProviderSupportsLoginPty: (environmentId) => assertCodexLoginProviderCapability(environmentId),
|
|
300
|
+
// Wire the live Codex pseudo-terminal opener through the plugin worker
|
|
301
|
+
// manager route. The opener sets the sandbox `CODEX_HOME` to the same
|
|
302
|
+
// server-controlled session home the descriptor-bound credential read
|
|
303
|
+
// opens. When no worker manager is bound, the runtime keeps its fail-closed
|
|
304
|
+
// opener and the login fails closed.
|
|
305
|
+
openLivePtySession: options.pluginWorkerManager
|
|
306
|
+
? createCodexWorkerBoundLoginPtyOpener({
|
|
307
|
+
workerManager: options.pluginWorkerManager,
|
|
308
|
+
log: (line) => logger.info(line),
|
|
309
|
+
})
|
|
310
|
+
: undefined,
|
|
311
|
+
}),
|
|
289
312
|
// The mandatory credential promotion. A successful login authenticates only
|
|
290
313
|
// after this promotion validates the exact staged credential, runs an
|
|
291
314
|
// independent readiness check, confirms the session still holds the sole
|
|
@@ -301,7 +324,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
301
324
|
// first under the lock and the reaper reclaims only after it completes. A
|
|
302
325
|
// read-only fence is not enough, because the filesystem write can start
|
|
303
326
|
// after the fence; the lock spans the whole section.
|
|
304
|
-
const outcome = await adapterLoginStore.withCompanyAdapterPromotionLock(context.companyId, context.adapterType, () => promoteDeviceLoginCredential({
|
|
327
|
+
const outcome = await adapterLoginStore.withCompanyAdapterPromotionLock(context.companyId, context.startedByUserId, context.adapterType, () => promoteDeviceLoginCredential({
|
|
305
328
|
authBytes,
|
|
306
329
|
companyId: context.companyId,
|
|
307
330
|
userInitiated: true,
|
|
@@ -404,8 +427,8 @@ export function agentRoutes(db, options = {}) {
|
|
|
404
427
|
release: noopRelease,
|
|
405
428
|
};
|
|
406
429
|
}
|
|
407
|
-
const
|
|
408
|
-
if (!
|
|
430
|
+
const requestedEnvironment = await environmentsSvc.getById(input.environmentId);
|
|
431
|
+
if (!requestedEnvironment) {
|
|
409
432
|
return {
|
|
410
433
|
executionTarget: null,
|
|
411
434
|
environmentName: null,
|
|
@@ -419,6 +442,35 @@ export function agentRoutes(db, options = {}) {
|
|
|
419
442
|
release: noopRelease,
|
|
420
443
|
};
|
|
421
444
|
}
|
|
445
|
+
// Managed-sandbox-only policy: redirect a Test that would run on the local
|
|
446
|
+
// host onto the platform-managed sandbox, the same as a real run does
|
|
447
|
+
// (resolveExecutionWorkspaceEnvironmentId in heartbeat). Without this
|
|
448
|
+
// redirect the Test probes the local host while the run executes in the
|
|
449
|
+
// managed sandbox, so a passing Test validates the wrong execution target.
|
|
450
|
+
// With no active managed sandbox the Test fails closed — never local.
|
|
451
|
+
let environment = requestedEnvironment;
|
|
452
|
+
if (requestedEnvironment.driver === "local") {
|
|
453
|
+
const managedSandboxOnly = (await instanceSettings.getExperimental()).enableManagedSandboxOnly === true;
|
|
454
|
+
if (managedSandboxOnly) {
|
|
455
|
+
const managedSandboxEnvironment = await environmentsSvc.findManagedSandboxEnvironment(input.companyId);
|
|
456
|
+
if (!managedSandboxEnvironment) {
|
|
457
|
+
return {
|
|
458
|
+
executionTarget: null,
|
|
459
|
+
environmentName: requestedEnvironment.name,
|
|
460
|
+
fallbackChecks: [
|
|
461
|
+
{
|
|
462
|
+
code: "managed_sandbox_unavailable",
|
|
463
|
+
level: "error",
|
|
464
|
+
message: "This instance runs agents only in its platform-managed sandbox, but no active managed sandbox environment exists. The test did not run.",
|
|
465
|
+
hint: "Restore the managed sandbox environment, then test again.",
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
release: noopRelease,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
environment = managedSandboxEnvironment;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
422
474
|
if (environment.driver === "local") {
|
|
423
475
|
return {
|
|
424
476
|
executionTarget: null,
|
|
@@ -509,6 +561,11 @@ export function agentRoutes(db, options = {}) {
|
|
|
509
561
|
issueId: null,
|
|
510
562
|
heartbeatRunId: null,
|
|
511
563
|
persistedExecutionWorkspace: null,
|
|
564
|
+
// Re-check the company binding atomically at lease time. The route
|
|
565
|
+
// guard already rejected a foreign environment, but the binding could
|
|
566
|
+
// change between the guard check and the lease acquire. This closes
|
|
567
|
+
// that check-to-lease race so a foreign sandbox never gets a lease.
|
|
568
|
+
assertCompanyBinding: true,
|
|
512
569
|
// Apply the active custom-image template so the Test boots with the
|
|
513
570
|
// operator's captured sandbox customizations and prepared image state,
|
|
514
571
|
// matching what real agent runs use. Without this the test would
|
|
@@ -613,7 +670,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
613
670
|
{
|
|
614
671
|
code: "environment_target_failed",
|
|
615
672
|
level: "error",
|
|
616
|
-
message: `Could not resolve
|
|
673
|
+
message: `Could not resolve an execution target for "${environment.name}".`,
|
|
617
674
|
detail: err instanceof Error ? err.message : String(err),
|
|
618
675
|
},
|
|
619
676
|
],
|
|
@@ -692,9 +749,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
692
749
|
return {
|
|
693
750
|
code: "sandbox_test_identity",
|
|
694
751
|
level: "info",
|
|
695
|
-
message: `
|
|
752
|
+
message: `Environment test identity for "${input.environmentName}".`,
|
|
696
753
|
detail: detailParts.join("; "),
|
|
697
|
-
hint: "Use these provider-neutral IDs when comparing model-test output with provider logs or refreshed
|
|
754
|
+
hint: "Use these provider-neutral IDs when comparing model-test output with provider logs or refreshed environment snapshots.",
|
|
698
755
|
};
|
|
699
756
|
}
|
|
700
757
|
async function getCurrentUserRedactionOptions() {
|
|
@@ -881,9 +938,31 @@ export function agentRoutes(db, options = {}) {
|
|
|
881
938
|
}
|
|
882
939
|
return userId;
|
|
883
940
|
}
|
|
884
|
-
//
|
|
885
|
-
|
|
886
|
-
|
|
941
|
+
// Read the interactive login capability the registry declares for an adapter
|
|
942
|
+
// type. Return null when the adapter declares no capability, so a guard fails
|
|
943
|
+
// closed on the absent case.
|
|
944
|
+
function getRegistryLoginCapability(type) {
|
|
945
|
+
return findActiveServerAdapter(type)?.loginCapability ?? null;
|
|
946
|
+
}
|
|
947
|
+
// The device-login route drives a login that shows a one-time code on a real
|
|
948
|
+
// pseudo-terminal. It serves an adapter whose registry login capability
|
|
949
|
+
// declares the displayed-code panel mode and whose trusted adapter type maps
|
|
950
|
+
// to a login command key. The guard reads the panel mode and the command map,
|
|
951
|
+
// not the adapter name, so a new adapter that satisfies both passes with no
|
|
952
|
+
// guard code change. It rejects an adapter with no matching capability, and an
|
|
953
|
+
// adapter with no mapped command key, with the same fixed 400.
|
|
954
|
+
//
|
|
955
|
+
// The command-map check keeps admission consistent with the closed command
|
|
956
|
+
// map. The login opener resolves the command key from the same map. An adapter
|
|
957
|
+
// that declares the displayed-code capability but has no mapped key would pass
|
|
958
|
+
// the panel-mode check, then fail at command resolution after the route
|
|
959
|
+
// creates session state. The guard rejects it before any session or lease side
|
|
960
|
+
// effect.
|
|
961
|
+
function assertDeviceLoginAdapter(type) {
|
|
962
|
+
if (getRegistryLoginCapability(type)?.panelMode !== "displayed_code") {
|
|
963
|
+
throw badRequest(`Adapter "${type}" does not support a device login.`);
|
|
964
|
+
}
|
|
965
|
+
if (!isLoginCommandSupportedAdapterType(type)) {
|
|
887
966
|
throw badRequest(`Adapter "${type}" does not support a device login.`);
|
|
888
967
|
}
|
|
889
968
|
}
|
|
@@ -927,14 +1006,15 @@ export function agentRoutes(db, options = {}) {
|
|
|
927
1006
|
}
|
|
928
1007
|
}
|
|
929
1008
|
/**
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
*
|
|
933
|
-
*
|
|
934
|
-
* non-plugin provider, and a provider without the flag all
|
|
935
|
-
*
|
|
1009
|
+
* Reports whether the environment provider advertises the login pseudo-terminal
|
|
1010
|
+
* capability. It resolves the effective provider from the current environment
|
|
1011
|
+
* config, then reads the static capability from the provider plugin manifest. It
|
|
1012
|
+
* never checks the provider by name. A missing provider, a missing plugin, a
|
|
1013
|
+
* non-plugin provider, and a provider without the flag all return false. Both
|
|
1014
|
+
* login flows share this resolver, so both gates read the same current
|
|
1015
|
+
* capability.
|
|
936
1016
|
*/
|
|
937
|
-
async function
|
|
1017
|
+
async function resolveProviderSupportsLoginPty(environmentId) {
|
|
938
1018
|
const environment = await environmentsSvc.getById(environmentId);
|
|
939
1019
|
const config = environment?.config && typeof environment.config === "object"
|
|
940
1020
|
? environment.config
|
|
@@ -943,26 +1023,50 @@ export function agentRoutes(db, options = {}) {
|
|
|
943
1023
|
const resolved = provider
|
|
944
1024
|
? await resolvePluginSandboxProviderDriverByKey({ db, driverKey: provider })
|
|
945
1025
|
: null;
|
|
946
|
-
|
|
1026
|
+
return resolved?.driver.supportsLoginPty === true;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Fails closed when the environment provider does not advertise the login
|
|
1030
|
+
* pseudo-terminal capability that the Claude setup-token login needs. It reads
|
|
1031
|
+
* the current provider capability. It fails closed with the fixed, typed error,
|
|
1032
|
+
* so no session row, lease, or pseudo-terminal starts.
|
|
1033
|
+
*/
|
|
1034
|
+
async function assertSetupTokenLoginProviderCapability(environmentId) {
|
|
1035
|
+
if (!(await resolveProviderSupportsLoginPty(environmentId))) {
|
|
947
1036
|
throw unprocessable(SETUP_TOKEN_PROVIDER_UNSUPPORTED, {
|
|
948
1037
|
code: SETUP_TOKEN_PROVIDER_UNSUPPORTED_CODE,
|
|
949
1038
|
});
|
|
950
1039
|
}
|
|
951
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Fails closed when the environment provider does not advertise the login
|
|
1043
|
+
* pseudo-terminal capability that the Codex device login needs. It reads the
|
|
1044
|
+
* current provider capability. The Codex route runs it before any session or
|
|
1045
|
+
* lease state, and the lease-acquisition path runs it again from current runtime
|
|
1046
|
+
* state before the provider lease. It fails closed with the fixed, typed error,
|
|
1047
|
+
* so no session row, lease, or pseudo-terminal starts.
|
|
1048
|
+
*/
|
|
1049
|
+
async function assertCodexLoginProviderCapability(environmentId) {
|
|
1050
|
+
if (!(await resolveProviderSupportsLoginPty(environmentId))) {
|
|
1051
|
+
throw unprocessable(CODEX_DEVICE_LOGIN_PROVIDER_UNSUPPORTED, {
|
|
1052
|
+
code: CODEX_DEVICE_LOGIN_PROVIDER_UNSUPPORTED_CODE,
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
952
1056
|
// Read a login session for its owner. The durable row is the authority for the
|
|
953
1057
|
// company and the owner. This returns null when the row is absent, when it
|
|
954
1058
|
// belongs to another company or adapter, or when the requesting user is not the
|
|
955
1059
|
// owner. So a non-owner and a cross-company caller both receive a 404 and cannot
|
|
956
1060
|
// enumerate a session. Only the owner path reads the one-time prompt.
|
|
957
|
-
async function readOwnerLoginSession(companyId, adapterType,
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1061
|
+
async function readOwnerLoginSession(companyId, adapterType, publicSessionId, requestingUserId) {
|
|
1062
|
+
// Read by the public session id, scoped to the company. The store predicate
|
|
1063
|
+
// already carries the company id, so a foreign-company caller reads nothing
|
|
1064
|
+
// and the internal row id never matches. Keep the adapter and owner checks.
|
|
1065
|
+
const row = await adapterLoginStore.getByPublicId(publicSessionId, companyId);
|
|
1066
|
+
if (!row || row.adapterType !== adapterType || row.startedByUserId !== requestingUserId) {
|
|
963
1067
|
return null;
|
|
964
1068
|
}
|
|
965
|
-
return adapterLoginService.readOwnerSession(
|
|
1069
|
+
return adapterLoginService.readOwnerSession(publicSessionId, companyId, requestingUserId);
|
|
966
1070
|
}
|
|
967
1071
|
async function assertCanReadConfigurations(req, companyId) {
|
|
968
1072
|
// Reading agent configurations, skills, and config revisions is a
|
|
@@ -1453,6 +1557,10 @@ export function agentRoutes(db, options = {}) {
|
|
|
1453
1557
|
next.model = DEFAULT_GEMINI_LOCAL_MODEL;
|
|
1454
1558
|
return ensureGatewayDeviceKey(adapterType, next);
|
|
1455
1559
|
}
|
|
1560
|
+
if (adapterType === "kimi_local" && !asNonEmptyString(next.model)) {
|
|
1561
|
+
next.model = DEFAULT_KIMI_LOCAL_MODEL;
|
|
1562
|
+
return ensureGatewayDeviceKey(adapterType, next);
|
|
1563
|
+
}
|
|
1456
1564
|
if (adapterType === "opencode_local" && !asNonEmptyString(next.model)) {
|
|
1457
1565
|
next.model = DEFAULT_OPENCODE_LOCAL_MODEL;
|
|
1458
1566
|
return ensureGatewayDeviceKey(adapterType, next);
|
|
@@ -1577,6 +1685,19 @@ export function agentRoutes(db, options = {}) {
|
|
|
1577
1685
|
async function assertCanApplyAgentProfileChange(req, targetAgent) {
|
|
1578
1686
|
await assertCanApplyProtectedAgentChange(req, targetAgent, [agentProfileChangeTargetKey(targetAgent.id)]);
|
|
1579
1687
|
}
|
|
1688
|
+
async function assertCanResumeAgent(req, targetAgent) {
|
|
1689
|
+
if (req.actor.type !== "agent")
|
|
1690
|
+
return;
|
|
1691
|
+
const decision = await access.decide({
|
|
1692
|
+
actor: req.actor,
|
|
1693
|
+
action: "agent_config:update",
|
|
1694
|
+
resource: { type: "agent", companyId: targetAgent.companyId, agentId: targetAgent.id },
|
|
1695
|
+
scope: { requiresChangeGrant: true },
|
|
1696
|
+
});
|
|
1697
|
+
if (decision.allowed)
|
|
1698
|
+
return;
|
|
1699
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
1700
|
+
}
|
|
1580
1701
|
function assertNoAgentInstructionsConfigMutation(req, adapterConfig, path = "adapterConfig") {
|
|
1581
1702
|
if (req.actor.type !== "agent" || !adapterConfig)
|
|
1582
1703
|
return;
|
|
@@ -1822,6 +1943,34 @@ export function agentRoutes(db, options = {}) {
|
|
|
1822
1943
|
const detected = await detectAdapterModel(type);
|
|
1823
1944
|
res.json(detected);
|
|
1824
1945
|
});
|
|
1946
|
+
// The environment drivers the adapter Test route accepts. A local, SSH, or
|
|
1947
|
+
// sandbox environment can host a probe; a plugin environment cannot.
|
|
1948
|
+
const ADAPTER_TEST_ALLOWED_ENVIRONMENT_DRIVERS = ["local", "ssh", "sandbox"];
|
|
1949
|
+
// The fail-closed tenant-binding guard for the adapter Test route. A caller
|
|
1950
|
+
// may name any instance environment by id, so the route must reject an
|
|
1951
|
+
// environment that binds to another company before it resolves secrets,
|
|
1952
|
+
// merges env, resolves the target, leases a sandbox, or runs the adapter
|
|
1953
|
+
// test. The guard checks the company binding BEFORE it validates the status
|
|
1954
|
+
// or the driver, so it never reveals the status or the driver of a foreign
|
|
1955
|
+
// environment. A same-company or an instance-global environment then gets the
|
|
1956
|
+
// shared driver and status validation.
|
|
1957
|
+
async function assertAdapterTestEnvironmentForCompany(companyId, environmentId) {
|
|
1958
|
+
const environment = await environmentsSvc.getById(environmentId);
|
|
1959
|
+
if (!environment) {
|
|
1960
|
+
// A missing environment leaks no tenant state. The execution-context
|
|
1961
|
+
// resolver surfaces the existing environment_not_found check.
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1964
|
+
const boundCompanyIds = await environmentsSvc.listBoundCompanyIds(environmentId);
|
|
1965
|
+
if (boundCompanyIds.length > 0 && !boundCompanyIds.includes(companyId)) {
|
|
1966
|
+
throw forbidden("The selected environment belongs to another company.", {
|
|
1967
|
+
code: "environment_company_mismatch",
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
await assertEnvironmentSelectionForCompany(environmentsSvc, companyId, environmentId, {
|
|
1971
|
+
allowedDrivers: ADAPTER_TEST_ALLOWED_ENVIRONMENT_DRIVERS,
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1825
1974
|
router.post("/companies/:companyId/adapters/:type/test-environment", validate(testAdapterEnvironmentSchema), async (req, res) => {
|
|
1826
1975
|
const companyId = req.params.companyId;
|
|
1827
1976
|
const type = assertKnownAdapterType(req.params.type);
|
|
@@ -1831,6 +1980,11 @@ export function agentRoutes(db, options = {}) {
|
|
|
1831
1980
|
const requestedEnvironmentId = typeof req.body?.environmentId === "string" && req.body.environmentId.trim().length > 0
|
|
1832
1981
|
? req.body.environmentId
|
|
1833
1982
|
: null;
|
|
1983
|
+
// Fail closed on a foreign environment before any secret resolution, env
|
|
1984
|
+
// merge, target resolution, sandbox lease, or adapter test runs.
|
|
1985
|
+
if (requestedEnvironmentId) {
|
|
1986
|
+
await assertAdapterTestEnvironmentForCompany(companyId, requestedEnvironmentId);
|
|
1987
|
+
}
|
|
1834
1988
|
const normalizedAdapterConfig = await secretsSvc.normalizeAdapterConfigForPersistence(companyId, inputAdapterConfig, { strictMode: strictSecretsMode, adapterType: type });
|
|
1835
1989
|
// Prospective, non-persisted config: resolve the acting user's own user
|
|
1836
1990
|
// secrets in owner_scoped mode (no declaration rows exist for this config).
|
|
@@ -1945,28 +2099,42 @@ export function agentRoutes(db, options = {}) {
|
|
|
1945
2099
|
router.post("/companies/:companyId/adapters/:type/login-sessions", async (req, res) => {
|
|
1946
2100
|
const companyId = req.params.companyId;
|
|
1947
2101
|
const type = req.params.type;
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
:
|
|
1959
|
-
|
|
1960
|
-
|
|
2102
|
+
// The shared start-route spine derives the owner, checks the path adapter
|
|
2103
|
+
// type, validates the strict request schema, and checks the sandbox
|
|
2104
|
+
// environment before any session or lease side effect. The client body
|
|
2105
|
+
// carries no adapter type, so the spine injects the path type into the
|
|
2106
|
+
// parse. The strict schema rejects an unknown field, a non-uuid
|
|
2107
|
+
// environment id, and an out-of-range time-to-live with a fixed 400.
|
|
2108
|
+
const resolved = await runAdapterLoginStartSpine({
|
|
2109
|
+
req,
|
|
2110
|
+
res,
|
|
2111
|
+
deriveOwner: () => assertCanManageAdapterLogin(req, companyId),
|
|
2112
|
+
guardBeforeValidate: () => assertDeviceLoginAdapter(type),
|
|
2113
|
+
requestSchema: startAdapterAuthSessionRequestSchema,
|
|
2114
|
+
invalidRequestError: "The device login start request is invalid.",
|
|
2115
|
+
requestOverrides: { adapterType: type },
|
|
2116
|
+
assertSandbox: async (data) => {
|
|
2117
|
+
// The device login runs on a real pseudo-terminal, so it needs a
|
|
2118
|
+
// provider that advertises the login pseudo-terminal capability. Gate
|
|
2119
|
+
// the route on the current provider capability before any session or
|
|
2120
|
+
// lease state. The lease-acquisition path re-checks it from current
|
|
2121
|
+
// runtime state before the provider lease.
|
|
2122
|
+
await assertSandboxLoginEnvironment(companyId, data.environmentId);
|
|
2123
|
+
await assertCodexLoginProviderCapability(data.environmentId);
|
|
2124
|
+
},
|
|
2125
|
+
});
|
|
2126
|
+
if (!resolved)
|
|
2127
|
+
return;
|
|
2128
|
+
const { ownerUserId: startedByUserId, data } = resolved;
|
|
1961
2129
|
const controller = new AbortController();
|
|
1962
2130
|
let result;
|
|
1963
2131
|
try {
|
|
1964
2132
|
result = await adapterLoginService.start({
|
|
1965
2133
|
companyId,
|
|
1966
|
-
environmentId,
|
|
2134
|
+
environmentId: data.environmentId,
|
|
1967
2135
|
adapterType: type,
|
|
1968
2136
|
startedByUserId,
|
|
1969
|
-
ttlSeconds,
|
|
2137
|
+
ttlSeconds: data.ttlSeconds,
|
|
1970
2138
|
signal: controller.signal,
|
|
1971
2139
|
});
|
|
1972
2140
|
}
|
|
@@ -1997,7 +2165,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
1997
2165
|
const type = req.params.type;
|
|
1998
2166
|
const sessionId = req.params.sessionId;
|
|
1999
2167
|
const ownerUserId = await assertCanManageAdapterLogin(req, companyId);
|
|
2000
|
-
|
|
2168
|
+
assertDeviceLoginAdapter(type);
|
|
2001
2169
|
const owner = await readOwnerLoginSession(companyId, type, sessionId, ownerUserId);
|
|
2002
2170
|
if (!owner) {
|
|
2003
2171
|
res.status(404).json({ error: "Adapter login session not found" });
|
|
@@ -2012,7 +2180,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
2012
2180
|
const type = req.params.type;
|
|
2013
2181
|
const sessionId = req.params.sessionId;
|
|
2014
2182
|
const ownerUserId = await assertCanManageAdapterLogin(req, companyId);
|
|
2015
|
-
|
|
2183
|
+
assertDeviceLoginAdapter(type);
|
|
2016
2184
|
// Scope the cancel to this company, adapter, and owner. A non-owner and a
|
|
2017
2185
|
// cross-company caller both receive a 404 and cannot cancel a session.
|
|
2018
2186
|
const owner = await readOwnerLoginSession(companyId, type, sessionId, ownerUserId);
|
|
@@ -2024,7 +2192,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
2024
2192
|
// even when this process does not own the in-flight run, so a cross-process
|
|
2025
2193
|
// cancel or a cancel after a restart does not leave the slot held until the
|
|
2026
2194
|
// expiry. The reaper deletes the sandbox and finalizes the terminal.
|
|
2027
|
-
const cancelled = await adapterLoginService.cancelOwnerSession(sessionId, ownerUserId);
|
|
2195
|
+
const cancelled = await adapterLoginService.cancelOwnerSession(sessionId, companyId, ownerUserId);
|
|
2028
2196
|
// Abort the in-flight run this process owns, so the local login stops at
|
|
2029
2197
|
// once instead of waiting for the reaper. A run in another process, or an
|
|
2030
2198
|
// already-terminal run, has no controller here.
|
|
@@ -3105,12 +3273,12 @@ export function agentRoutes(db, options = {}) {
|
|
|
3105
3273
|
res.json(agent);
|
|
3106
3274
|
});
|
|
3107
3275
|
router.post("/agents/:id/resume", async (req, res) => {
|
|
3108
|
-
assertBoard(req);
|
|
3109
3276
|
const id = req.params.id;
|
|
3110
3277
|
const existing = await getAccessibleAgent(req, res, id);
|
|
3111
3278
|
if (!existing) {
|
|
3112
3279
|
return;
|
|
3113
3280
|
}
|
|
3281
|
+
await assertCanResumeAgent(req, existing);
|
|
3114
3282
|
if (existing.orgChainHealth?.status === "invalid_org_chain") {
|
|
3115
3283
|
res.status(409).json({
|
|
3116
3284
|
error: existing.orgChainHealth?.repairGuidance ?? "Repair this agent's reporting chain before resuming it",
|
|
@@ -3122,10 +3290,14 @@ export function agentRoutes(db, options = {}) {
|
|
|
3122
3290
|
res.status(404).json({ error: "Agent not found" });
|
|
3123
3291
|
return;
|
|
3124
3292
|
}
|
|
3293
|
+
const actor = getActorInfo(req);
|
|
3125
3294
|
await logActivity(db, {
|
|
3126
3295
|
companyId: agent.companyId,
|
|
3127
|
-
actorType:
|
|
3128
|
-
actorId:
|
|
3296
|
+
actorType: actor.actorType,
|
|
3297
|
+
actorId: actor.actorId,
|
|
3298
|
+
agentId: actor.agentId,
|
|
3299
|
+
runId: actor.runId,
|
|
3300
|
+
agentApiKeyId: actor.agentApiKeyId,
|
|
3129
3301
|
action: "agent.resumed",
|
|
3130
3302
|
entityType: "agent",
|
|
3131
3303
|
entityId: agent.id,
|
|
@@ -3702,61 +3874,79 @@ export function agentRoutes(db, options = {}) {
|
|
|
3702
3874
|
});
|
|
3703
3875
|
router.post("/companies/:companyId/setup-token-login-sessions", async (req, res) => {
|
|
3704
3876
|
const companyId = req.params.companyId;
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
//
|
|
3709
|
-
//
|
|
3710
|
-
//
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
//
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
res
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3877
|
+
// The shared start-route spine derives the owner, validates the strict
|
|
3878
|
+
// request schema, runs the Claude-only guards, and checks the sandbox
|
|
3879
|
+
// environment before any session, lease, or pseudo-terminal side effect.
|
|
3880
|
+
//
|
|
3881
|
+
// The owner step runs the company access check, derives the owner, and then
|
|
3882
|
+
// sets `Cache-Control: no-store`, so a rejected member sees no cache header
|
|
3883
|
+
// and every other response carries it. The strict schema rejects an unknown
|
|
3884
|
+
// field, including a legacy `ttlSeconds`, with a fixed 400. The post-validate
|
|
3885
|
+
// guard rejects a non-Claude adapter with a fixed 400 and fails closed with
|
|
3886
|
+
// the fixed no-secret 503 until the live login transport binds. The sandbox
|
|
3887
|
+
// check fails closed on a missing, archived, non-sandbox, fake-provider, or
|
|
3888
|
+
// foreign environment, and on a provider without the setup-token login
|
|
3889
|
+
// capability, so no rejected environment reaches a session row, a lease, or a
|
|
3890
|
+
// pseudo-terminal.
|
|
3891
|
+
const resolved = await runAdapterLoginStartSpine({
|
|
3892
|
+
req,
|
|
3893
|
+
res,
|
|
3894
|
+
deriveOwner: () => {
|
|
3895
|
+
assertCompanyAccess(req, companyId);
|
|
3896
|
+
const ownerUserId = deriveSetupTokenOwnerUserId(req);
|
|
3897
|
+
res.setHeader("Cache-Control", "no-store");
|
|
3898
|
+
return ownerUserId;
|
|
3899
|
+
},
|
|
3900
|
+
requestSchema: startClaudeSetupTokenSessionRequestSchema,
|
|
3901
|
+
invalidRequestError: "The Claude login start request is invalid.",
|
|
3902
|
+
guardAfterValidate: (data) => {
|
|
3903
|
+
// The setup-token route drives a login on a pseudo-terminal and records a
|
|
3904
|
+
// stored session identifier on success. It serves any adapter whose
|
|
3905
|
+
// registry login capability records that completion claim. The guard reads
|
|
3906
|
+
// the capability, not the adapter name, so a new adapter with the same
|
|
3907
|
+
// claim passes with no code change. It rejects an adapter with no matching
|
|
3908
|
+
// capability with a fixed 400.
|
|
3909
|
+
const capability = getRegistryLoginCapability(data.adapterType);
|
|
3910
|
+
if (capability?.completionClaim !== "storedSessionId") {
|
|
3911
|
+
res.status(400).json({ error: "This adapter does not support a setup-token login." });
|
|
3912
|
+
return true;
|
|
3913
|
+
}
|
|
3914
|
+
if (!SETUP_TOKEN_LOGIN_TRANSPORT_READY) {
|
|
3915
|
+
res.status(503).json({ error: SETUP_TOKEN_START_FAILED });
|
|
3916
|
+
return true;
|
|
3917
|
+
}
|
|
3918
|
+
return false;
|
|
3919
|
+
},
|
|
3920
|
+
assertSandbox: (data) => assertSandboxLoginEnvironment(companyId, data.environmentId, {
|
|
3921
|
+
requireSetupTokenLoginProvider: true,
|
|
3922
|
+
}),
|
|
3741
3923
|
});
|
|
3924
|
+
if (!resolved)
|
|
3925
|
+
return;
|
|
3926
|
+
const { ownerUserId, data } = resolved;
|
|
3927
|
+
const { environmentId, adapterType } = data;
|
|
3928
|
+
const confirmedOverwrite = data.overwrite ?? null;
|
|
3742
3929
|
const scope = {
|
|
3743
3930
|
companyId,
|
|
3744
3931
|
ownerUserId,
|
|
3745
|
-
targetAgentId: null,
|
|
3746
3932
|
adapterType,
|
|
3747
3933
|
environmentId,
|
|
3748
3934
|
confirmedOverwrite,
|
|
3749
3935
|
};
|
|
3936
|
+
// Read the panel mode from the adapter capability. The guard already checked
|
|
3937
|
+
// the capability, so it is present here. The client renders the panel from
|
|
3938
|
+
// this value instead of a hard-coded mode.
|
|
3939
|
+
const panelMode = getRegistryLoginCapability(adapterType)?.panelMode ?? "submitted_browser_code";
|
|
3750
3940
|
try {
|
|
3751
3941
|
const started = await setupTokenLoginService.start(scope);
|
|
3752
3942
|
const descriptor = setupTokenLoginService.describeOwned(started.sessionId, scope);
|
|
3753
3943
|
// The start response carries the panel mode, so the client renders the
|
|
3754
|
-
//
|
|
3755
|
-
//
|
|
3756
|
-
//
|
|
3944
|
+
// correct panel. The full login URL rides only through the guarded prompt
|
|
3945
|
+
// read, not the start response, so the prompt is null here. The client
|
|
3946
|
+
// reads the prompt route for the login URL.
|
|
3757
3947
|
const body = {
|
|
3758
3948
|
...toClaudePublicResponse(descriptor),
|
|
3759
|
-
panelMode
|
|
3949
|
+
panelMode,
|
|
3760
3950
|
prompt: null,
|
|
3761
3951
|
};
|
|
3762
3952
|
res.status(201).json(body);
|