@capybara-hq/kernel 0.1.0-rc.4 → 0.1.0-rc.5
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/bootstrap.json +61 -5
- package/dist/admin/admin.controller.d.ts +39 -13
- package/dist/admin/admin.controller.js +33 -17
- package/dist/admin/extensions.controller.d.ts +16 -2
- package/dist/admin/extensions.controller.js +26 -6
- package/dist/admin/setup-lock.d.ts +1 -1
- package/dist/admin/setup-lock.js +1 -1
- package/dist/admin/setup.controller.d.ts +1 -1
- package/dist/admin/setup.controller.js +1 -1
- package/dist/admin/setup.service.d.ts +4 -4
- package/dist/admin/setup.service.js +8 -8
- package/dist/agents/agent-lookup.d.ts +16 -0
- package/dist/agents/agent-lookup.js +11 -0
- package/dist/agents/agents.controller.d.ts +76 -1
- package/dist/agents/agents.controller.js +90 -11
- package/dist/agents/agents.module.d.ts +4 -1
- package/dist/agents/agents.module.js +32 -6
- package/dist/agents/agents.service.d.ts +51 -22
- package/dist/agents/agents.service.js +172 -70
- package/dist/agents/definition.d.ts +49 -0
- package/dist/agents/definition.js +45 -0
- package/dist/agents/from-template.d.ts +106 -0
- package/dist/agents/from-template.js +649 -0
- package/dist/agents/from-template.service.d.ts +60 -0
- package/dist/agents/from-template.service.js +161 -0
- package/dist/agents/org-templates.d.ts +176 -0
- package/dist/agents/org-templates.js +827 -0
- package/dist/agents/pending-connector-requests.d.ts +77 -0
- package/dist/agents/pending-connector-requests.js +215 -0
- package/dist/agents/pending-connectors.controller.d.ts +39 -0
- package/dist/agents/pending-connectors.controller.js +91 -0
- package/dist/agents/pending-connectors.service.d.ts +62 -0
- package/dist/agents/pending-connectors.service.js +282 -0
- package/dist/agents/templates.controller.d.ts +86 -5
- package/dist/agents/templates.controller.js +171 -7
- package/dist/agents/templates.d.ts +127 -23
- package/dist/agents/templates.js +475 -52
- package/dist/background/background.module.js +8 -1
- package/dist/background/finish.d.ts +3 -2
- package/dist/background/launch-lock.d.ts +4 -3
- package/dist/background/launch-lock.js +4 -3
- package/dist/background/poll.job.d.ts +9 -6
- package/dist/background/poll.job.js +30 -22
- package/dist/background/session.d.ts +13 -2
- package/dist/background/session.js +13 -0
- package/dist/background/stop.d.ts +12 -6
- package/dist/background/stop.js +57 -39
- package/dist/background/store.d.ts +18 -6
- package/dist/background/store.js +12 -6
- package/dist/background/tasks.service.d.ts +15 -5
- package/dist/background/tasks.service.js +42 -17
- package/dist/background/wake-rules.d.ts +27 -18
- package/dist/background/wake-rules.js +52 -22
- package/dist/background/wake.d.ts +13 -11
- package/dist/background/wake.js +20 -14
- package/dist/catalog/admin-catalog.controller.d.ts +129 -30
- package/dist/catalog/admin-catalog.controller.js +213 -42
- package/dist/catalog/catalog-content.d.ts +58 -32
- package/dist/catalog/catalog-content.js +34 -8
- package/dist/catalog/catalog-import.module.d.ts +7 -0
- package/dist/catalog/catalog-import.module.js +60 -0
- package/dist/catalog/catalog-items.d.ts +111 -7
- package/dist/catalog/catalog-items.js +279 -13
- package/dist/catalog/catalog-scope.service.d.ts +260 -0
- package/dist/catalog/catalog-scope.service.js +1116 -0
- package/dist/catalog/catalog.module.d.ts +7 -9
- package/dist/catalog/catalog.module.js +41 -31
- package/dist/catalog/catalog.service.d.ts +101 -29
- package/dist/catalog/catalog.service.js +104 -106
- package/dist/catalog/cli.d.ts +11 -1
- package/dist/catalog/cli.js +26 -1
- package/dist/catalog/component-promotion.d.ts +96 -0
- package/dist/catalog/component-promotion.js +395 -0
- package/dist/catalog/component-scope.controller.d.ts +152 -0
- package/dist/catalog/component-scope.controller.js +287 -0
- package/dist/catalog/component-scope.service.d.ts +303 -0
- package/dist/catalog/component-scope.service.js +936 -0
- package/dist/catalog/component-state.d.ts +174 -0
- package/dist/catalog/component-state.js +437 -0
- package/dist/catalog/job-ids.d.ts +30 -0
- package/dist/catalog/job-ids.js +25 -0
- package/dist/catalog/marketplace-fetch.d.ts +1 -1
- package/dist/catalog/marketplaces.controller.d.ts +22 -5
- package/dist/catalog/marketplaces.controller.js +56 -7
- package/dist/catalog/marketplaces.service.d.ts +54 -14
- package/dist/catalog/marketplaces.service.js +71 -22
- package/dist/catalog/org-catalog.controller.d.ts +125 -34
- package/dist/catalog/org-catalog.controller.js +181 -65
- package/dist/catalog/org-catalog.service.d.ts +65 -33
- package/dist/catalog/org-catalog.service.js +324 -157
- package/dist/catalog/org-extension-switch.d.ts +41 -0
- package/dist/catalog/org-extension-switch.js +115 -0
- package/dist/catalog/org-extension.controller.d.ts +119 -0
- package/dist/catalog/org-extension.controller.js +266 -0
- package/dist/catalog/org-plugin-uploads.controller.d.ts +98 -0
- package/dist/catalog/org-plugin-uploads.controller.js +213 -0
- package/dist/catalog/org-plugin-uploads.d.ts +63 -0
- package/dist/catalog/org-plugin-uploads.js +116 -0
- package/dist/catalog/owned-items.d.ts +184 -0
- package/dist/catalog/owned-items.js +789 -0
- package/dist/catalog/owned-plugin-cleanup.d.ts +56 -0
- package/dist/catalog/owned-plugin-cleanup.js +194 -0
- package/dist/catalog/ownership.d.ts +172 -0
- package/dist/catalog/ownership.js +326 -0
- package/dist/catalog/platform-components.d.ts +221 -0
- package/dist/catalog/platform-components.js +761 -0
- package/dist/catalog/platform-migration.d.ts +115 -0
- package/dist/catalog/platform-migration.js +582 -0
- package/dist/catalog/plugin-import.d.ts +178 -34
- package/dist/catalog/plugin-import.js +622 -82
- package/dist/catalog/plugin-install.d.ts +185 -41
- package/dist/catalog/plugin-install.js +758 -126
- package/dist/catalog/plugin-upgrade.d.ts +260 -225
- package/dist/catalog/plugin-upgrade.js +1147 -1136
- package/dist/catalog/request-rules.d.ts +65 -0
- package/dist/catalog/request-rules.js +217 -0
- package/dist/catalog/requests.service.d.ts +193 -118
- package/dist/catalog/requests.service.js +526 -343
- package/dist/catalog/reserved-names.d.ts +8 -0
- package/dist/catalog/reserved-names.js +42 -0
- package/dist/catalog/scope-orgs.d.ts +21 -0
- package/dist/catalog/scope-orgs.js +67 -0
- package/dist/catalog/scope-state.d.ts +35 -0
- package/dist/catalog/scope-state.js +87 -0
- package/dist/catalog/scope-sync-workers.d.ts +7 -0
- package/dist/catalog/scope-sync-workers.js +29 -0
- package/dist/catalog/scope-sync.d.ts +176 -0
- package/dist/catalog/scope-sync.js +576 -0
- package/dist/catalog/scope.d.ts +42 -0
- package/dist/catalog/scope.js +42 -0
- package/dist/catalog/unshare.d.ts +22 -0
- package/dist/catalog/unshare.js +118 -0
- package/dist/channels/actions.js +1 -0
- package/dist/channels/cards.js +20 -2
- package/dist/channels/channels.module.js +2 -0
- package/dist/channels/inbound.d.ts +9 -1
- package/dist/channels/inbound.js +67 -5
- package/dist/channels/phrases.d.ts +35 -0
- package/dist/channels/phrases.js +29 -0
- package/dist/config/docs.js +3 -1
- package/dist/config/schema.d.ts +6 -2
- package/dist/config/schema.js +46 -22
- package/dist/conversations/access.d.ts +6 -4
- package/dist/conversations/access.js +27 -5
- package/dist/conversations/agent-tree.d.ts +46 -0
- package/dist/conversations/agent-tree.js +92 -0
- package/dist/conversations/conversations.controller.d.ts +43 -18
- package/dist/conversations/conversations.controller.js +79 -38
- package/dist/conversations/conversations.module.d.ts +1 -1
- package/dist/conversations/conversations.module.js +7 -7
- package/dist/conversations/conversations.service.d.ts +69 -12
- package/dist/conversations/conversations.service.js +106 -27
- package/dist/conversations/environment-status.d.ts +24 -0
- package/dist/conversations/environment-status.js +71 -0
- package/dist/conversations/event-log.d.ts +20 -5
- package/dist/conversations/event-log.js +60 -0
- package/dist/conversations/events.d.ts +84 -2
- package/dist/conversations/events.js +91 -17
- package/dist/conversations/queue.service.d.ts +1 -1
- package/dist/conversations/queue.service.js +5 -0
- package/dist/conversations/titles.d.ts +5 -3
- package/dist/conversations/titles.js +21 -8
- package/dist/conversations/tree.d.ts +17 -0
- package/dist/conversations/tree.js +42 -0
- package/dist/ctx/create-ctx.d.ts +5 -0
- package/dist/ctx/create-ctx.js +15 -5
- package/dist/db/kernel-schema.d.ts +362 -18
- package/dist/environments/access.d.ts +41 -0
- package/dist/environments/access.js +77 -0
- package/dist/environments/conversation-environments.d.ts +61 -0
- package/dist/environments/conversation-environments.js +170 -0
- package/dist/environments/dto.d.ts +25 -0
- package/dist/environments/dto.js +12 -0
- package/dist/environments/environments.controller.d.ts +33 -0
- package/dist/environments/environments.controller.js +110 -0
- package/dist/environments/environments.module.d.ts +8 -0
- package/dist/environments/environments.module.js +27 -0
- package/dist/environments/environments.service.d.ts +153 -0
- package/dist/environments/environments.service.js +541 -0
- package/dist/environments/legacy-cleanup.job.d.ts +34 -0
- package/dist/environments/legacy-cleanup.job.js +141 -0
- package/dist/errors.d.ts +82 -2
- package/dist/errors.js +82 -2
- package/dist/evals/reconstruct.d.ts +18 -9
- package/dist/evals/reconstruct.js +26 -7
- package/dist/evals/run-replay.d.ts +4 -2
- package/dist/evals/run-replay.js +16 -4
- package/dist/evals/step-replay.d.ts +2 -5
- package/dist/evals/step-replay.js +1 -1
- package/dist/evals/trajectory.service.d.ts +8 -3
- package/dist/evals/trajectory.service.js +26 -14
- package/dist/evals/worker.d.ts +5 -5
- package/dist/evals/worker.js +9 -3
- package/dist/extensions/admin-ops.d.ts +36 -10
- package/dist/extensions/admin-ops.js +65 -42
- package/dist/extensions/admin-view.d.ts +37 -10
- package/dist/extensions/admin-view.js +103 -20
- package/dist/extensions/bootstrap.d.ts +17 -4
- package/dist/extensions/bootstrap.js +70 -9
- package/dist/extensions/cli.d.ts +12 -0
- package/dist/extensions/cli.js +11 -2
- package/dist/extensions/deployment-config.d.ts +28 -5
- package/dist/extensions/deployment-config.js +48 -7
- package/dist/extensions/effective-config.d.ts +127 -0
- package/dist/extensions/effective-config.js +368 -0
- package/dist/extensions/extensions.module.js +8 -2
- package/dist/extensions/hooks.d.ts +37 -4
- package/dist/extensions/hooks.js +82 -16
- package/dist/extensions/host.d.ts +19 -1
- package/dist/extensions/host.js +30 -7
- package/dist/extensions/installs.d.ts +20 -8
- package/dist/extensions/installs.js +37 -15
- package/dist/extensions/org-config.d.ts +75 -6
- package/dist/extensions/org-config.js +184 -32
- package/dist/extensions/org-levels.d.ts +37 -0
- package/dist/extensions/org-levels.js +71 -0
- package/dist/extensions/org-overrides.d.ts +151 -0
- package/dist/extensions/org-overrides.js +524 -0
- package/dist/extensions/permission-view.d.ts +16 -4
- package/dist/extensions/permission-view.js +4 -4
- package/dist/extensions/plugin-items.d.ts +21 -0
- package/dist/extensions/plugin-items.js +42 -0
- package/dist/extensions/point-defaults.d.ts +12 -5
- package/dist/extensions/point-defaults.js +37 -9
- package/dist/extensions/resolve.d.ts +5 -1
- package/dist/extensions/resolve.js +15 -2
- package/dist/files/previewers.d.ts +8 -1
- package/dist/files/previewers.js +35 -6
- package/dist/http/api.module.js +23 -3
- package/dist/http/app.d.ts +11 -2
- package/dist/http/app.js +31 -5
- package/dist/identity/accounts.d.ts +29 -29
- package/dist/identity/accounts.js +47 -47
- package/dist/identity/audit.d.ts +2 -1
- package/dist/identity/auth.guard.d.ts +13 -5
- package/dist/identity/auth.guard.js +26 -9
- package/dist/identity/identity.module.d.ts +1 -1
- package/dist/identity/identity.module.js +4 -4
- package/dist/identity/me.controller.js +1 -1
- package/dist/identity/principal.d.ts +3 -3
- package/dist/identity/principal.js +3 -3
- package/dist/identity/settings.d.ts +22 -11
- package/dist/identity/settings.js +53 -18
- package/dist/identity/{enterprise-admin.d.ts → super-admin.d.ts} +5 -5
- package/dist/identity/{enterprise-admin.js → super-admin.js} +24 -24
- package/dist/inbox/inbox.module.d.ts +4 -1
- package/dist/inbox/inbox.module.js +7 -3
- package/dist/inbox/inbox.service.d.ts +62 -3
- package/dist/inbox/inbox.service.js +74 -4
- package/dist/inbox/org-notices.d.ts +63 -0
- package/dist/inbox/org-notices.js +91 -0
- package/dist/inbox/platform-inbox.controller.d.ts +23 -0
- package/dist/inbox/platform-inbox.controller.js +58 -0
- package/dist/inbox/platform-inbox.service.d.ts +151 -0
- package/dist/inbox/platform-inbox.service.js +263 -0
- package/dist/inbox/platform-notices.d.ts +19 -0
- package/dist/inbox/platform-notices.js +9 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/infra/cli/kernel-cli.module.js +9 -1
- package/dist/infra/config/kernel-config.service.js +21 -1
- package/dist/infra/database/xact-lock.d.ts +1 -1
- package/dist/infra/database/xact-lock.js +1 -1
- package/dist/infra/events/kernel-events.d.ts +11 -2
- package/dist/infra/queue/add-job-once.d.ts +14 -0
- package/dist/infra/queue/add-job-once.js +16 -0
- package/dist/kernel.module.js +6 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +1 -1
- package/dist/lifecycle/kernel-lifecycle.js +4 -4
- package/dist/models/prices.d.ts +5 -5
- package/dist/models/prices.js +4 -4
- package/dist/models/purposes.controller.d.ts +6 -4
- package/dist/models/purposes.controller.js +13 -7
- package/dist/models/purposes.d.ts +20 -9
- package/dist/models/purposes.js +17 -8
- package/dist/orgs/directory-sync.d.ts +14 -5
- package/dist/orgs/directory-sync.js +41 -17
- package/dist/orgs/offboarding.d.ts +9 -7
- package/dist/orgs/offboarding.js +28 -17
- package/dist/orgs/org-lock.d.ts +5 -0
- package/dist/orgs/org-lock.js +13 -0
- package/dist/orgs/org.guard.d.ts +10 -0
- package/dist/orgs/org.guard.js +43 -32
- package/dist/orgs/orgs.module.js +3 -0
- package/dist/orgs/orgs.service.d.ts +20 -7
- package/dist/orgs/orgs.service.js +32 -12
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +5 -1
- package/dist/orgs/settings.controller.d.ts +1 -1
- package/dist/orgs/settings.service.d.ts +15 -3
- package/dist/orgs/settings.service.js +6 -2
- package/dist/overrides.d.ts +3 -0
- package/dist/overrides.js +2 -0
- package/dist/platform/actor.d.ts +48 -0
- package/dist/platform/actor.js +100 -0
- package/dist/platform/agent-docs.d.ts +18 -0
- package/dist/platform/agent-docs.js +59 -0
- package/dist/platform/availability.d.ts +14 -0
- package/dist/platform/availability.js +43 -0
- package/dist/platform/errors.d.ts +11 -0
- package/dist/platform/errors.js +26 -0
- package/dist/platform/exclusions.d.ts +12 -0
- package/dist/platform/exclusions.js +1387 -0
- package/dist/platform/method.d.ts +6 -0
- package/dist/platform/method.js +15 -0
- package/dist/platform/operation.d.ts +92 -0
- package/dist/platform/operation.js +35 -0
- package/dist/platform/ops/agent-templates.ops.d.ts +14 -0
- package/dist/platform/ops/agent-templates.ops.js +92 -0
- package/dist/platform/ops/agents.ops.d.ts +19 -0
- package/dist/platform/ops/agents.ops.js +294 -0
- package/dist/platform/ops/connectors.ops.d.ts +15 -0
- package/dist/platform/ops/connectors.ops.js +126 -0
- package/dist/platform/ops/errors.d.ts +11 -0
- package/dist/platform/ops/errors.js +22 -0
- package/dist/platform/ops/extensions.ops.d.ts +19 -0
- package/dist/platform/ops/extensions.ops.js +116 -0
- package/dist/platform/ops/marketplaces.ops.d.ts +16 -0
- package/dist/platform/ops/marketplaces.ops.js +157 -0
- package/dist/platform/ops/paging.d.ts +14 -0
- package/dist/platform/ops/paging.js +20 -0
- package/dist/platform/ops/platform.ops.d.ts +23 -0
- package/dist/platform/ops/platform.ops.js +158 -0
- package/dist/platform/ops/plugins.ops.d.ts +33 -0
- package/dist/platform/ops/plugins.ops.js +377 -0
- package/dist/platform/ops/requests.ops.d.ts +14 -0
- package/dist/platform/ops/requests.ops.js +153 -0
- package/dist/platform/ops/role.d.ts +4 -0
- package/dist/platform/ops/role.js +10 -0
- package/dist/platform/ops/skills.ops.d.ts +13 -0
- package/dist/platform/ops/skills.ops.js +98 -0
- package/dist/platform/ops/summary.d.ts +10 -0
- package/dist/platform/ops/summary.js +18 -0
- package/dist/platform/platform-ops.module.d.ts +7 -0
- package/dist/platform/platform-ops.module.js +55 -0
- package/dist/platform/platform.module.d.ts +8 -0
- package/dist/platform/platform.module.js +25 -0
- package/dist/platform/redact-orgs.d.ts +7 -0
- package/dist/platform/redact-orgs.js +52 -0
- package/dist/platform/registry.d.ts +30 -0
- package/dist/platform/registry.js +111 -0
- package/dist/roles/worker-role.d.ts +6 -4
- package/dist/roles/worker-role.js +14 -7
- package/dist/roles/worker.module.d.ts +1 -1
- package/dist/roles/worker.module.js +9 -1
- package/dist/runtime/context/build.d.ts +6 -4
- package/dist/runtime/context/build.js +26 -7
- package/dist/runtime/context/claude-tools.d.ts +2 -1
- package/dist/runtime/context/claude-tools.js +5 -4
- package/dist/runtime/context/compaction.js +9 -0
- package/dist/runtime/context/reminders.d.ts +2 -0
- package/dist/runtime/context/reminders.js +2 -0
- package/dist/runtime/context/skills.js +9 -2
- package/dist/runtime/context/tool-changes.d.ts +27 -0
- package/dist/runtime/context/tool-changes.js +60 -0
- package/dist/runtime/hook-calls.js +2 -0
- package/dist/runtime/langgraph-loop.d.ts +3 -1
- package/dist/runtime/langgraph-loop.js +35 -17
- package/dist/runtime/loop.d.ts +32 -4
- package/dist/runtime/maintenance.d.ts +7 -4
- package/dist/runtime/maintenance.js +23 -8
- package/dist/runtime/model-call.d.ts +30 -8
- package/dist/runtime/model-call.js +69 -19
- package/dist/runtime/run-control.d.ts +11 -1
- package/dist/runtime/run-control.js +12 -0
- package/dist/runtime/run-drafts.d.ts +85 -0
- package/dist/runtime/run-drafts.js +230 -0
- package/dist/runtime/run-jobs.d.ts +3 -5
- package/dist/runtime/run-jobs.js +3 -7
- package/dist/runtime/run-queue.d.ts +37 -3
- package/dist/runtime/run-queue.js +188 -11
- package/dist/runtime/run-worker.d.ts +11 -5
- package/dist/runtime/run-worker.js +54 -31
- package/dist/runtime/runtime.module.js +3 -0
- package/dist/runtime/step-log.d.ts +9 -4
- package/dist/runtime/step-log.js +8 -5
- package/dist/runtime/stream.controller.d.ts +23 -1
- package/dist/runtime/stream.controller.js +60 -3
- package/dist/runtime/stream.d.ts +4 -1
- package/dist/runtime/stream.js +27 -3
- package/dist/runtime/subagents/child.d.ts +55 -7
- package/dist/runtime/subagents/child.js +105 -7
- package/dist/runtime/subagents/definition.d.ts +12 -3
- package/dist/runtime/subagents/definition.js +43 -29
- package/dist/runtime/subagents/deliveries.d.ts +71 -0
- package/dist/runtime/subagents/deliveries.js +228 -0
- package/dist/runtime/subagents/dispatch.d.ts +115 -26
- package/dist/runtime/subagents/dispatch.js +212 -141
- package/dist/runtime/subagents/limits.d.ts +24 -5
- package/dist/runtime/subagents/limits.js +40 -6
- package/dist/runtime/subagents/messages.d.ts +95 -0
- package/dist/runtime/subagents/messages.js +328 -0
- package/dist/runtime/subagents/preamble.d.ts +4 -4
- package/dist/runtime/subagents/preamble.js +9 -7
- package/dist/runtime/subagents/progress.d.ts +8 -6
- package/dist/runtime/subagents/progress.js +11 -6
- package/dist/runtime/subagents/render.d.ts +30 -0
- package/dist/runtime/subagents/render.js +53 -0
- package/dist/runtime/subagents/roster.d.ts +24 -7
- package/dist/runtime/subagents/roster.js +47 -11
- package/dist/runtime/subagents/skill-fork.d.ts +3 -2
- package/dist/runtime/subagents/skill-fork.js +8 -4
- package/dist/runtime/subagents/status.d.ts +14 -0
- package/dist/runtime/subagents/status.js +23 -0
- package/dist/runtime/subagents/subagents.service.d.ts +7 -4
- package/dist/runtime/subagents/subagents.service.js +11 -6
- package/dist/runtime/usage-report.js +17 -12
- package/dist/runtime/waits.d.ts +140 -37
- package/dist/runtime/waits.js +394 -106
- package/dist/sandbox/jobs.d.ts +40 -13
- package/dist/sandbox/jobs.js +57 -20
- package/dist/sandbox/leases.d.ts +37 -54
- package/dist/sandbox/leases.js +71 -115
- package/dist/sandbox/providers.d.ts +2 -2
- package/dist/sandbox/providers.js +1 -1
- package/dist/sandbox/sandbox.module.d.ts +3 -2
- package/dist/sandbox/sandbox.module.js +4 -3
- package/dist/sandbox/sandbox.service.d.ts +229 -134
- package/dist/sandbox/sandbox.service.js +630 -409
- package/dist/skills/catalog.d.ts +3 -2
- package/dist/skills/catalog.js +21 -43
- package/dist/skills/changes.controller.d.ts +7 -0
- package/dist/skills/changes.controller.js +19 -1
- package/dist/skills/invoke.js +8 -3
- package/dist/skills/package.d.ts +20 -1
- package/dist/skills/package.js +28 -1
- package/dist/skills/skills.controller.d.ts +39 -4
- package/dist/skills/skills.controller.js +88 -10
- package/dist/skills/skills.module.js +10 -1
- package/dist/skills/skills.service.d.ts +106 -26
- package/dist/skills/skills.service.js +421 -75
- package/dist/skills/usable.d.ts +81 -0
- package/dist/skills/usable.js +379 -0
- package/dist/tools/approvals.service.d.ts +20 -2
- package/dist/tools/approvals.service.js +23 -4
- package/dist/tools/builtin-names.d.ts +21 -5
- package/dist/tools/builtin-names.js +30 -5
- package/dist/tools/builtins/agent.d.ts +23 -21
- package/dist/tools/builtins/agent.js +62 -55
- package/dist/tools/builtins/builtin-tools.d.ts +6 -2
- package/dist/tools/builtins/builtin-tools.js +37 -12
- package/dist/tools/builtins/handback.d.ts +28 -0
- package/dist/tools/builtins/handback.js +53 -0
- package/dist/tools/builtins/platform.d.ts +34 -0
- package/dist/tools/builtins/platform.js +362 -0
- package/dist/tools/builtins/sandbox/bash.js +13 -3
- package/dist/tools/builtins/sandbox/common.d.ts +43 -24
- package/dist/tools/builtins/sandbox/common.js +80 -45
- package/dist/tools/builtins/sandbox/edit.js +2 -2
- package/dist/tools/builtins/sandbox/glob.js +2 -2
- package/dist/tools/builtins/sandbox/grep.js +2 -4
- package/dist/tools/builtins/sandbox/index.d.ts +1 -1
- package/dist/tools/builtins/sandbox/index.js +1 -1
- package/dist/tools/builtins/sandbox/read.js +1 -1
- package/dist/tools/builtins/sandbox/task-output.d.ts +14 -3
- package/dist/tools/builtins/sandbox/task-output.js +30 -5
- package/dist/tools/builtins/sandbox/task-stop.js +2 -1
- package/dist/tools/builtins/sandbox/write.js +2 -2
- package/dist/tools/builtins/send-message.d.ts +56 -0
- package/dist/tools/builtins/send-message.js +100 -0
- package/dist/tools/builtins/skill-load.d.ts +22 -14
- package/dist/tools/builtins/skill-load.js +86 -57
- package/dist/tools/builtins/skill-write.js +1 -1
- package/dist/tools/builtins/web/extract.js +5 -1
- package/dist/tools/builtins/web/fetch.js +1 -0
- package/dist/tools/builtins/web/search.js +1 -0
- package/dist/tools/connectors.controller.d.ts +10 -0
- package/dist/tools/connectors.controller.js +12 -0
- package/dist/tools/connectors.service.d.ts +46 -5
- package/dist/tools/connectors.service.js +94 -15
- package/dist/tools/extension-tools.controller.d.ts +14 -0
- package/dist/tools/extension-tools.controller.js +37 -0
- package/dist/tools/info.d.ts +42 -1
- package/dist/tools/info.js +64 -1
- package/dist/tools/org-tool-switches.d.ts +74 -0
- package/dist/tools/org-tool-switches.js +184 -0
- package/dist/tools/pipeline.d.ts +46 -40
- package/dist/tools/pipeline.js +187 -364
- package/dist/tools/policy.d.ts +1 -1
- package/dist/tools/policy.js +36 -16
- package/dist/tools/registry.d.ts +98 -5
- package/dist/tools/registry.js +87 -9
- package/dist/tools/tools.module.js +12 -2
- package/dist/ui/views.d.ts +2 -1
- package/dist/ui/views.js +17 -3
- package/package.json +3 -3
- package/src/migrations/0074_subagent_tree.sql +50 -0
- package/src/migrations/0075_plugin_scope.sql +61 -0
- package/src/migrations/0076_skills_created_by_nullable.sql +6 -0
- package/src/migrations/0077_scope_requests.sql +52 -0
- package/src/migrations/0078_scope_grant_switches.sql +18 -0
- package/src/migrations/0079_scope_live_install_switches.sql +19 -0
- package/src/migrations/0080_rename_enterprise_admin.sql +18 -0
- package/src/migrations/0081_platform_components.sql +129 -0
- package/src/migrations/0082_platform_migration.sql +33 -0
- package/src/migrations/0083_plugin_scope_sync_failures.sql +15 -0
- package/src/migrations/0084_org_owned_items.sql +85 -0
- package/src/migrations/0085_agent_templates_phase4.sql +45 -0
- package/src/migrations/0086_org_layering.sql +30 -0
- package/src/migrations/0087_approval_summary.sql +6 -0
- package/src/migrations/0088_environments.sql +80 -0
- package/dist/catalog/upgrade-targets.d.ts +0 -56
- package/dist/catalog/upgrade-targets.js +0 -90
- package/dist/conversations/sandbox-status.d.ts +0 -24
- package/dist/conversations/sandbox-status.js +0 -52
- package/dist/extensions/org-config.controller.d.ts +0 -32
- package/dist/extensions/org-config.controller.js +0 -70
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
import { sql } from "kysely";
|
|
13
|
+
import { ApiError } from "../errors.js";
|
|
14
|
+
import { audit } from "../identity/audit.js";
|
|
15
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
16
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
17
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
18
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
19
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
20
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
21
|
+
import { SandboxJobs } from "../sandbox/jobs.js";
|
|
22
|
+
import { SandboxProviders } from "../sandbox/providers.js";
|
|
23
|
+
import { environmentNotFound, SandboxService } from "../sandbox/sandbox.service.js";
|
|
24
|
+
import { EnvironmentAccess, environmentProvider, environmentUnavailable, } from "./access.js";
|
|
25
|
+
const isUniqueViolation = (e, constraint) => typeof e === "object" &&
|
|
26
|
+
e !== null &&
|
|
27
|
+
e.code === "23505" &&
|
|
28
|
+
e.constraint === constraint;
|
|
29
|
+
const nameTaken = () => new ApiError("environment.name_taken", "You already have an environment with this name");
|
|
30
|
+
/**
|
|
31
|
+
* Personal cloud environments (spec 2026-11-07-environments-design §4.2 items 7, 12, 13; §9): a
|
|
32
|
+
* person's environments in an org, visible and usable only by their owner (anyone else gets
|
|
33
|
+
* `environment.not_found`). Deleting one soft-deletes it and destroys its instance and files in a
|
|
34
|
+
* `sandbox-destroy-for` job after the commit.
|
|
35
|
+
*/
|
|
36
|
+
let EnvironmentsService = class EnvironmentsService {
|
|
37
|
+
db;
|
|
38
|
+
txHost;
|
|
39
|
+
config;
|
|
40
|
+
providers;
|
|
41
|
+
sandbox;
|
|
42
|
+
sandboxJobs;
|
|
43
|
+
access;
|
|
44
|
+
log;
|
|
45
|
+
constructor(db, txHost, config, providers, sandbox, sandboxJobs, access, log) {
|
|
46
|
+
this.db = db;
|
|
47
|
+
this.txHost = txHost;
|
|
48
|
+
this.config = config;
|
|
49
|
+
this.providers = providers;
|
|
50
|
+
this.sandbox = sandbox;
|
|
51
|
+
this.sandboxJobs = sandboxJobs;
|
|
52
|
+
this.access = access;
|
|
53
|
+
this.log = log;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The person's live environments in the org, the default first, then by creation. With a
|
|
57
|
+
* current sandbox provider the default environment is created first if missing (its first need,
|
|
58
|
+
* spec §4.2 item 7; an existing one is only read).
|
|
59
|
+
*/
|
|
60
|
+
async list(orgId, accountId) {
|
|
61
|
+
const cloudAvailable = this.providers.current() !== undefined;
|
|
62
|
+
const defaultId = cloudAvailable ? await this.ensureDefault(orgId, accountId) : null;
|
|
63
|
+
const items = await this.views(orgId, accountId);
|
|
64
|
+
const last = await this.db
|
|
65
|
+
.selectFrom("conversations as c")
|
|
66
|
+
.innerJoin("environments as e", "e.id", "c.environment_id")
|
|
67
|
+
.select("c.environment_id")
|
|
68
|
+
.where("c.org_id", "=", orgId)
|
|
69
|
+
.where("c.account_id", "=", accountId)
|
|
70
|
+
.where("e.org_id", "=", orgId)
|
|
71
|
+
.where("e.owner_kind", "=", "personal")
|
|
72
|
+
.where("e.owner_account_id", "=", accountId)
|
|
73
|
+
.where("e.deleted_at", "is", null)
|
|
74
|
+
.orderBy("c.updated_at", "desc")
|
|
75
|
+
.limit(1)
|
|
76
|
+
.executeTakeFirst();
|
|
77
|
+
return {
|
|
78
|
+
items,
|
|
79
|
+
defaultId: defaultId ?? items.find((v) => v.isDefault)?.id ?? null,
|
|
80
|
+
lastUsedId: last?.environment_id ?? null,
|
|
81
|
+
cloudAvailable,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** One of the person's live environments; anyone else's (or a missing one) → `not_found`. */
|
|
85
|
+
async get(orgId, accountId, id) {
|
|
86
|
+
const [view] = await this.views(orgId, accountId, id);
|
|
87
|
+
if (!view)
|
|
88
|
+
throw environmentNotFound();
|
|
89
|
+
return view;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A new personal cloud environment, ready at once (its instance and files are made on first
|
|
93
|
+
* use). Needs a current sandbox provider (`environment.unavailable`); a live name of the person's
|
|
94
|
+
* (case-insensitive) → `environment.name_taken`; `environments.maxPersonal` live ones (the
|
|
95
|
+
* default counts) → `environment.limit_reached`. Serialized per person by their membership row.
|
|
96
|
+
*/
|
|
97
|
+
async create(orgId, accountId, input, actorTokenId) {
|
|
98
|
+
const id = await this.insert(orgId, accountId, input.name, actorTokenId);
|
|
99
|
+
return this.get(orgId, accountId, id);
|
|
100
|
+
}
|
|
101
|
+
async insert(orgId, accountId, name, actorTokenId) {
|
|
102
|
+
const current = this.providers.current();
|
|
103
|
+
if (!current)
|
|
104
|
+
throw environmentUnavailable(null);
|
|
105
|
+
await this.lockMember(orgId, accountId);
|
|
106
|
+
const { n } = await this.db
|
|
107
|
+
.selectFrom("environments")
|
|
108
|
+
.select((eb) => eb.fn.countAll().as("n"))
|
|
109
|
+
.where("org_id", "=", orgId)
|
|
110
|
+
.where("owner_kind", "=", "personal")
|
|
111
|
+
.where("owner_account_id", "=", accountId)
|
|
112
|
+
.where("deleted_at", "is", null)
|
|
113
|
+
.executeTakeFirstOrThrow();
|
|
114
|
+
const max = this.config.get().environments.maxPersonal;
|
|
115
|
+
if (Number(n) >= max) {
|
|
116
|
+
throw new ApiError("environment.limit_reached", `You already have ${max} environments in this organization; delete one to create another`);
|
|
117
|
+
}
|
|
118
|
+
await this.assertNameFree(orgId, accountId, name);
|
|
119
|
+
const id = randomUUID();
|
|
120
|
+
try {
|
|
121
|
+
await this.db
|
|
122
|
+
.insertInto("environments")
|
|
123
|
+
.values({
|
|
124
|
+
id,
|
|
125
|
+
org_id: orgId,
|
|
126
|
+
owner_kind: "personal",
|
|
127
|
+
owner_account_id: accountId,
|
|
128
|
+
name,
|
|
129
|
+
source: "cloud",
|
|
130
|
+
provider: current.plugin,
|
|
131
|
+
})
|
|
132
|
+
.execute();
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
if (isUniqueViolation(e, "environments_name_uq"))
|
|
136
|
+
throw nameTaken();
|
|
137
|
+
throw e;
|
|
138
|
+
}
|
|
139
|
+
await audit(this.db.db, {
|
|
140
|
+
actorAccountId: accountId,
|
|
141
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
142
|
+
orgId,
|
|
143
|
+
action: "environment.created",
|
|
144
|
+
target: id,
|
|
145
|
+
detail: { name },
|
|
146
|
+
});
|
|
147
|
+
return id;
|
|
148
|
+
}
|
|
149
|
+
/** Renames one of the person's live environments (the default too); see {@link create}. */
|
|
150
|
+
async rename(orgId, accountId, id, name, actorTokenId) {
|
|
151
|
+
await this.renameIn(orgId, accountId, id, name, actorTokenId);
|
|
152
|
+
return this.get(orgId, accountId, id);
|
|
153
|
+
}
|
|
154
|
+
async renameIn(orgId, accountId, id, name, actorTokenId) {
|
|
155
|
+
const before = await this.lockOwn(orgId, accountId, id);
|
|
156
|
+
if (before.name === name)
|
|
157
|
+
return;
|
|
158
|
+
// the same name in another case is this environment's own: the index allows it
|
|
159
|
+
if (before.name?.toLowerCase() !== name.toLowerCase()) {
|
|
160
|
+
await this.assertNameFree(orgId, accountId, name);
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
await this.db
|
|
164
|
+
.updateTable("environments")
|
|
165
|
+
.set({ name, updated_at: sql `now()` })
|
|
166
|
+
.where("id", "=", id)
|
|
167
|
+
.execute();
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
if (isUniqueViolation(e, "environments_name_uq"))
|
|
171
|
+
throw nameTaken();
|
|
172
|
+
throw e;
|
|
173
|
+
}
|
|
174
|
+
await audit(this.db.db, {
|
|
175
|
+
actorAccountId: accountId,
|
|
176
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
177
|
+
orgId,
|
|
178
|
+
action: "environment.renamed",
|
|
179
|
+
target: id,
|
|
180
|
+
detail: { from: before.name, to: name },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Deletes one of the person's live environments: soft delete, its IM default row cleared, and
|
|
185
|
+
* after the commit a `sandbox-destroy-for` job (the worker waits for running commands, then
|
|
186
|
+
* destroys the instance and the files). Conversations bound to it keep pointing at it; their
|
|
187
|
+
* sandbox tools then fail with `environment.not_found`.
|
|
188
|
+
*/
|
|
189
|
+
async remove(orgId, accountId, id, actorTokenId) {
|
|
190
|
+
const before = await this.lockOwn(orgId, accountId, id);
|
|
191
|
+
await this.db
|
|
192
|
+
.updateTable("environments")
|
|
193
|
+
.set({ deleted_at: sql `now()`, updated_at: sql `now()` })
|
|
194
|
+
.where("id", "=", id)
|
|
195
|
+
.execute();
|
|
196
|
+
await this.db
|
|
197
|
+
.deleteFrom("environment_defaults")
|
|
198
|
+
.where("org_id", "=", orgId)
|
|
199
|
+
.where("account_id", "=", accountId)
|
|
200
|
+
.where("environment_id", "=", id)
|
|
201
|
+
.execute();
|
|
202
|
+
await audit(this.db.db, {
|
|
203
|
+
actorAccountId: accountId,
|
|
204
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
205
|
+
orgId,
|
|
206
|
+
action: "environment.deleted",
|
|
207
|
+
target: id,
|
|
208
|
+
detail: { name: before.name, isDefault: before.is_default },
|
|
209
|
+
});
|
|
210
|
+
afterCommit(async () => {
|
|
211
|
+
try {
|
|
212
|
+
await this.sandboxJobs.destroy([id]);
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
// the hourly destruction sweep destroys deleted environments too
|
|
216
|
+
this.log.warn("cannot schedule environment destruction", { environmentId: id, err });
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Starts one of the person's environments over with empty files (after
|
|
222
|
+
* `environment.files_lost`): records the request (audit), then, after the commit, enqueues the
|
|
223
|
+
* `sandbox-reset-files` job (deterministic id per environment), whose worker waits for running
|
|
224
|
+
* commands and destroys any instance and the file system; the next use creates new ones. Its
|
|
225
|
+
* provider must be the current one (`environment.unavailable`). An enqueue failure is thrown
|
|
226
|
+
* (the request can be repeated: the reset is idempotent).
|
|
227
|
+
*/
|
|
228
|
+
async resetFiles(orgId, accountId, id, actorTokenId) {
|
|
229
|
+
await this.recordReset(orgId, accountId, id, actorTokenId);
|
|
230
|
+
await this.sandboxJobs.resetFiles(id);
|
|
231
|
+
}
|
|
232
|
+
/** The check and audit row of {@link resetFiles}, committed before the job is enqueued. */
|
|
233
|
+
async recordReset(orgId, accountId, id, actorTokenId) {
|
|
234
|
+
await this.access.usable(orgId, accountId, id);
|
|
235
|
+
await audit(this.db.db, {
|
|
236
|
+
actorAccountId: accountId,
|
|
237
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
238
|
+
orgId,
|
|
239
|
+
action: "environment.files_reset",
|
|
240
|
+
target: id,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* The person's default environment in the org, created when missing (named by the UI, `name`
|
|
245
|
+
* NULL). An existing usable one is read without locking. A live default whose files or
|
|
246
|
+
* instance are kept by a provider that is not the current one (a provider switch, spec §4.2
|
|
247
|
+
* item 13) is stranded: it is demoted, named `Personal (<provider>)` (` 2`, ` 3`, … when that
|
|
248
|
+
* name is taken) and stays listed as unavailable and deletable, and a fresh default is created,
|
|
249
|
+
* in one transaction. Creating one first takes the person's membership row (`FOR SHARE`, after
|
|
250
|
+
* the org row), so an offboarding that removes them cannot leave a live default behind, and
|
|
251
|
+
* their creates and renames (`FOR NO KEY UPDATE`) cannot race the demoted name; not a member
|
|
252
|
+
* (any more) → `org.not_found`. Idempotent under concurrency: the demotion locks the default
|
|
253
|
+
* row and re-checks it, the partial unique index on the live default makes a racing insert do
|
|
254
|
+
* nothing, and the select that follows reads the winner. Needs a current sandbox provider
|
|
255
|
+
* (`environment.unavailable`). It is the person's baseline, so it is created even at
|
|
256
|
+
* `environments.maxPersonal`.
|
|
257
|
+
*/
|
|
258
|
+
async ensureDefault(orgId, accountId) {
|
|
259
|
+
const live = await this.defaultOf(orgId, accountId);
|
|
260
|
+
if (live && !this.stranded(live))
|
|
261
|
+
return live.id;
|
|
262
|
+
return this.insertDefault(orgId, accountId);
|
|
263
|
+
}
|
|
264
|
+
async insertDefault(orgId, accountId) {
|
|
265
|
+
const current = this.providers.current();
|
|
266
|
+
if (!current)
|
|
267
|
+
throw environmentUnavailable(null);
|
|
268
|
+
await this.lockMember(orgId, accountId, "share");
|
|
269
|
+
const live = await this.defaultOf(orgId, accountId, true);
|
|
270
|
+
if (live && !this.stranded(live))
|
|
271
|
+
return live.id;
|
|
272
|
+
if (live) {
|
|
273
|
+
const held = environmentProvider(live, current.plugin) ?? "unknown";
|
|
274
|
+
await this.demote(orgId, accountId, live.id, held);
|
|
275
|
+
}
|
|
276
|
+
await this.db
|
|
277
|
+
.insertInto("environments")
|
|
278
|
+
.values({
|
|
279
|
+
id: randomUUID(),
|
|
280
|
+
org_id: orgId,
|
|
281
|
+
owner_kind: "personal",
|
|
282
|
+
owner_account_id: accountId,
|
|
283
|
+
name: null,
|
|
284
|
+
is_default: true,
|
|
285
|
+
source: "cloud",
|
|
286
|
+
provider: current.plugin,
|
|
287
|
+
})
|
|
288
|
+
.onConflict((oc) => oc
|
|
289
|
+
.columns(["org_id", "owner_account_id"])
|
|
290
|
+
.where(sql `is_default AND deleted_at IS NULL`)
|
|
291
|
+
.doNothing())
|
|
292
|
+
.execute();
|
|
293
|
+
const row = await this.defaultOf(orgId, accountId);
|
|
294
|
+
if (row === undefined)
|
|
295
|
+
throw new Error("the default environment was not created");
|
|
296
|
+
return row.id;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Turns a stranded default into an ordinary environment named `Personal (<provider>)`, with
|
|
300
|
+
* ` 2`, ` 3`, … appended while that name is one of the person's live names (case-insensitive).
|
|
301
|
+
* Runs under the person's membership lock and the default row's lock.
|
|
302
|
+
*/
|
|
303
|
+
async demote(orgId, accountId, id, provider) {
|
|
304
|
+
const base = `Personal (${provider})`;
|
|
305
|
+
const taken = new Set((await this.db
|
|
306
|
+
.selectFrom("environments")
|
|
307
|
+
.select("name")
|
|
308
|
+
.where("org_id", "=", orgId)
|
|
309
|
+
.where("owner_account_id", "=", accountId)
|
|
310
|
+
.where("deleted_at", "is", null)
|
|
311
|
+
.where("name", "is not", null)
|
|
312
|
+
.execute()).map((r) => r.name.toLowerCase()));
|
|
313
|
+
let name = base;
|
|
314
|
+
for (let n = 2; taken.has(name.toLowerCase()); n++)
|
|
315
|
+
name = `${base} ${n}`;
|
|
316
|
+
await this.db
|
|
317
|
+
.updateTable("environments")
|
|
318
|
+
.set({ is_default: false, name, updated_at: sql `now()` })
|
|
319
|
+
.where("id", "=", id)
|
|
320
|
+
.execute();
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* The person's IM default (what `/env` set): the environment their next new IM conversation
|
|
324
|
+
* uses. Null when none was set, or the chosen one is deleted (the row is cleared with it).
|
|
325
|
+
*/
|
|
326
|
+
async imDefault(orgId, accountId) {
|
|
327
|
+
const row = await this.db
|
|
328
|
+
.selectFrom("environment_defaults as d")
|
|
329
|
+
.innerJoin("environments as e", "e.id", "d.environment_id")
|
|
330
|
+
.select("e.id")
|
|
331
|
+
.where("d.org_id", "=", orgId)
|
|
332
|
+
.where("d.account_id", "=", accountId)
|
|
333
|
+
.where("e.org_id", "=", orgId)
|
|
334
|
+
.where("e.owner_kind", "=", "personal")
|
|
335
|
+
.where("e.owner_account_id", "=", accountId)
|
|
336
|
+
.where("e.deleted_at", "is", null)
|
|
337
|
+
.executeTakeFirst();
|
|
338
|
+
return row?.id ?? null;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Sets the person's IM default. Only one of their own live environments in the org, usable now
|
|
342
|
+
* (`environment.not_found` / `environment.unavailable` otherwise); the row is written by one
|
|
343
|
+
* statement that re-checks the environment is live. There is no row lock, so a delete racing
|
|
344
|
+
* past that check can leave a stale row; reads ignore it ({@link imDefault} joins on
|
|
345
|
+
* `deleted_at IS NULL`).
|
|
346
|
+
*/
|
|
347
|
+
async setImDefault(orgId, accountId, environmentId) {
|
|
348
|
+
await this.access.usable(orgId, accountId, environmentId);
|
|
349
|
+
const written = await this.db
|
|
350
|
+
.insertInto("environment_defaults")
|
|
351
|
+
.columns(["org_id", "account_id", "environment_id"])
|
|
352
|
+
.expression(this.db
|
|
353
|
+
.selectFrom("environments")
|
|
354
|
+
.select([
|
|
355
|
+
sql `${orgId}::text`.as("org_id"),
|
|
356
|
+
sql `${accountId}::text`.as("account_id"),
|
|
357
|
+
"id",
|
|
358
|
+
])
|
|
359
|
+
.where("id", "=", environmentId)
|
|
360
|
+
.where("org_id", "=", orgId)
|
|
361
|
+
.where("owner_kind", "=", "personal")
|
|
362
|
+
.where("owner_account_id", "=", accountId)
|
|
363
|
+
.where("deleted_at", "is", null))
|
|
364
|
+
.onConflict((oc) => oc
|
|
365
|
+
.columns(["org_id", "account_id"])
|
|
366
|
+
.doUpdateSet({ environment_id: environmentId, updated_at: new Date() }))
|
|
367
|
+
.executeTakeFirst();
|
|
368
|
+
if (Number(written.numInsertedOrUpdatedRows ?? 0) === 0)
|
|
369
|
+
throw environmentNotFound();
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* The person's live default environment in the org, if any, with what decides its provider;
|
|
373
|
+
* `lock` takes its row (`FOR NO KEY UPDATE`; a racing demotion makes it read none).
|
|
374
|
+
*/
|
|
375
|
+
async defaultOf(orgId, accountId, lock = false) {
|
|
376
|
+
const row = await this.db
|
|
377
|
+
.selectFrom("environments as e")
|
|
378
|
+
.leftJoin("environment_instances as i", "i.environment_id", "e.id")
|
|
379
|
+
.select(["e.id", "e.provider", "i.provider as instance_provider", "i.fs_status", "i.handle"])
|
|
380
|
+
.where("e.org_id", "=", orgId)
|
|
381
|
+
.where("e.owner_kind", "=", "personal")
|
|
382
|
+
.where("e.owner_account_id", "=", accountId)
|
|
383
|
+
.where("e.is_default", "=", true)
|
|
384
|
+
.where("e.deleted_at", "is", null)
|
|
385
|
+
.$if(lock, (q) => q.forNoKeyUpdate("e"))
|
|
386
|
+
.executeTakeFirst();
|
|
387
|
+
return (row && {
|
|
388
|
+
id: row.id,
|
|
389
|
+
provider: row.provider,
|
|
390
|
+
instanceProvider: row.instance_provider,
|
|
391
|
+
fsStatus: row.fs_status,
|
|
392
|
+
hasInstance: row.handle !== null,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
/** Its files or instance are kept by a provider that is not the current one. */
|
|
396
|
+
stranded(f) {
|
|
397
|
+
const current = this.providers.current()?.plugin;
|
|
398
|
+
return current !== undefined && environmentProvider(f, current) !== current;
|
|
399
|
+
}
|
|
400
|
+
/** The person's live environments (or the one `id`) as views. */
|
|
401
|
+
async views(orgId, accountId, id) {
|
|
402
|
+
const rows = await this.db
|
|
403
|
+
.selectFrom("environments as e")
|
|
404
|
+
.leftJoin("environment_instances as i", "i.environment_id", "e.id")
|
|
405
|
+
.select([
|
|
406
|
+
"e.id",
|
|
407
|
+
"e.name",
|
|
408
|
+
"e.is_default",
|
|
409
|
+
"e.provider",
|
|
410
|
+
"e.created_at",
|
|
411
|
+
"i.provider as instance_provider",
|
|
412
|
+
"i.fs_status",
|
|
413
|
+
"i.handle",
|
|
414
|
+
"i.status",
|
|
415
|
+
"i.last_used_at",
|
|
416
|
+
])
|
|
417
|
+
.where("e.org_id", "=", orgId)
|
|
418
|
+
.where("e.owner_kind", "=", "personal")
|
|
419
|
+
.where("e.owner_account_id", "=", accountId)
|
|
420
|
+
.where("e.deleted_at", "is", null)
|
|
421
|
+
.$if(id !== undefined, (q) => q.where("e.id", "=", id))
|
|
422
|
+
.orderBy("e.is_default", "desc")
|
|
423
|
+
.orderBy("e.created_at")
|
|
424
|
+
.orderBy("e.id")
|
|
425
|
+
.execute();
|
|
426
|
+
if (rows.length === 0)
|
|
427
|
+
return [];
|
|
428
|
+
const limits = await this.sandbox.orgLimits(orgId);
|
|
429
|
+
const current = this.providers.current()?.plugin;
|
|
430
|
+
return rows.map((r) => {
|
|
431
|
+
const provider = environmentProvider({
|
|
432
|
+
provider: r.provider,
|
|
433
|
+
instanceProvider: r.instance_provider,
|
|
434
|
+
fsStatus: r.fs_status,
|
|
435
|
+
hasInstance: r.handle !== null,
|
|
436
|
+
}, current);
|
|
437
|
+
const live = (r.status === "running" || r.status === "suspended") && r.last_used_at;
|
|
438
|
+
return {
|
|
439
|
+
id: r.id,
|
|
440
|
+
name: r.name,
|
|
441
|
+
isDefault: r.is_default,
|
|
442
|
+
ownerKind: "personal",
|
|
443
|
+
source: "cloud",
|
|
444
|
+
provider,
|
|
445
|
+
available: current !== undefined && provider === current,
|
|
446
|
+
sessionIsolation: false,
|
|
447
|
+
filesLost: r.fs_status === "lost",
|
|
448
|
+
instance: live
|
|
449
|
+
? {
|
|
450
|
+
status: r.status,
|
|
451
|
+
lastUsedAt: r.last_used_at.toISOString(),
|
|
452
|
+
}
|
|
453
|
+
: null,
|
|
454
|
+
limits: { ...limits, allowHosts: [...limits.allowHosts] },
|
|
455
|
+
createdAt: r.created_at.toISOString(),
|
|
456
|
+
};
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Serializes the person's environment writes in the org: the org row (`FOR SHARE`), then their
|
|
461
|
+
* membership row (`FOR NO KEY UPDATE`, or `FOR SHARE` with `mode` share: enough to keep the
|
|
462
|
+
* membership from being removed meanwhile), the order member removal locks them in. Not a
|
|
463
|
+
* member (any more) → `org.not_found`, as the org guard answers.
|
|
464
|
+
*/
|
|
465
|
+
async lockMember(orgId, accountId, mode = "update") {
|
|
466
|
+
const org = await this.db
|
|
467
|
+
.selectFrom("orgs")
|
|
468
|
+
.select("id")
|
|
469
|
+
.where("id", "=", orgId)
|
|
470
|
+
.where("deleted_at", "is", null)
|
|
471
|
+
.forShare()
|
|
472
|
+
.executeTakeFirst();
|
|
473
|
+
const m = org &&
|
|
474
|
+
(await this.db
|
|
475
|
+
.selectFrom("memberships")
|
|
476
|
+
.select("account_id")
|
|
477
|
+
.where("org_id", "=", orgId)
|
|
478
|
+
.where("account_id", "=", accountId)
|
|
479
|
+
.$if(mode === "update", (q) => q.forNoKeyUpdate())
|
|
480
|
+
.$if(mode === "share", (q) => q.forShare())
|
|
481
|
+
.executeTakeFirst());
|
|
482
|
+
if (!m)
|
|
483
|
+
throw new ApiError("org.not_found", "Organization not found");
|
|
484
|
+
}
|
|
485
|
+
/** Locks one of the person's live environments (after their membership); else `not_found`. */
|
|
486
|
+
async lockOwn(orgId, accountId, id) {
|
|
487
|
+
await this.lockMember(orgId, accountId);
|
|
488
|
+
const row = await this.db
|
|
489
|
+
.selectFrom("environments")
|
|
490
|
+
.select(["name", "is_default"])
|
|
491
|
+
.where("id", "=", id)
|
|
492
|
+
.where("org_id", "=", orgId)
|
|
493
|
+
.where("owner_kind", "=", "personal")
|
|
494
|
+
.where("owner_account_id", "=", accountId)
|
|
495
|
+
.where("deleted_at", "is", null)
|
|
496
|
+
.forNoKeyUpdate()
|
|
497
|
+
.executeTakeFirst();
|
|
498
|
+
if (!row)
|
|
499
|
+
throw environmentNotFound();
|
|
500
|
+
return row;
|
|
501
|
+
}
|
|
502
|
+
async assertNameFree(orgId, accountId, name) {
|
|
503
|
+
const clash = await this.db
|
|
504
|
+
.selectFrom("environments")
|
|
505
|
+
.select("id")
|
|
506
|
+
.where("org_id", "=", orgId)
|
|
507
|
+
.where("owner_account_id", "=", accountId)
|
|
508
|
+
.where("deleted_at", "is", null)
|
|
509
|
+
.where(sql `lower(name) = lower(${name})`)
|
|
510
|
+
.executeTakeFirst();
|
|
511
|
+
if (clash)
|
|
512
|
+
throw nameTaken();
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
__decorate([
|
|
516
|
+
Transactional()
|
|
517
|
+
], EnvironmentsService.prototype, "insert", null);
|
|
518
|
+
__decorate([
|
|
519
|
+
Transactional()
|
|
520
|
+
], EnvironmentsService.prototype, "renameIn", null);
|
|
521
|
+
__decorate([
|
|
522
|
+
Transactional()
|
|
523
|
+
], EnvironmentsService.prototype, "remove", null);
|
|
524
|
+
__decorate([
|
|
525
|
+
Transactional()
|
|
526
|
+
], EnvironmentsService.prototype, "recordReset", null);
|
|
527
|
+
__decorate([
|
|
528
|
+
Transactional()
|
|
529
|
+
], EnvironmentsService.prototype, "insertDefault", null);
|
|
530
|
+
EnvironmentsService = __decorate([
|
|
531
|
+
Injectable(),
|
|
532
|
+
__param(0, Inject(KernelDb)),
|
|
533
|
+
__param(1, Inject(TransactionHost)),
|
|
534
|
+
__param(2, Inject(KernelConfigService)),
|
|
535
|
+
__param(3, Inject(SandboxProviders)),
|
|
536
|
+
__param(4, Inject(SandboxService)),
|
|
537
|
+
__param(5, Inject(SandboxJobs)),
|
|
538
|
+
__param(6, Inject(EnvironmentAccess)),
|
|
539
|
+
__param(7, Inject(KERNEL_LOGGER))
|
|
540
|
+
], EnvironmentsService);
|
|
541
|
+
export { EnvironmentsService };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
2
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { LockService } from "../infra/lock/lock.service.js";
|
|
4
|
+
import type { KernelLogger } from "../log.js";
|
|
5
|
+
import { SandboxProviders } from "../sandbox/providers.js";
|
|
6
|
+
/** The job's name (`@LockedInterval`, run lock `cron:environments-legacy-cleanup`). */
|
|
7
|
+
export declare const LEGACY_CLEANUP_JOB = "environments-legacy-cleanup";
|
|
8
|
+
/** What one run did: rows destroyed and deleted, rows kept because their provider is not loaded. */
|
|
9
|
+
export interface LegacyCleanupResult {
|
|
10
|
+
destroyed: number;
|
|
11
|
+
kept: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The cleanup of the per-conversation sandboxes of before environments (spec
|
|
15
|
+
* 2026-11-07-environments-design §4.2 item 9): for up to {@link BATCH} rows of the legacy
|
|
16
|
+
* `sandboxes` table per tick, the row's provider destroys the instance and the file system named
|
|
17
|
+
* `cap-<conversationId>` (`destroyByName`, `destroyFileSystemByName`; also the instance of the
|
|
18
|
+
* provider it replaced, `prev_provider`, when that one is loaded), then the row is deleted. No
|
|
19
|
+
* lease is taken: nothing holds a legacy row after the upgrade. A row whose provider is not loaded
|
|
20
|
+
* is kept (warned once per hour: on the tick in the first {@link PERIOD_MS} of each hour); a row
|
|
21
|
+
* whose destruction failed is retried at a later tick, after the others (`sweep_failed_at`). With
|
|
22
|
+
* no rows left a tick is one `SELECT … LIMIT 1`. The table is dropped by a later migration.
|
|
23
|
+
*/
|
|
24
|
+
export declare class LegacySandboxCleanupJob {
|
|
25
|
+
private readonly db;
|
|
26
|
+
private readonly providers;
|
|
27
|
+
readonly config: KernelConfigService;
|
|
28
|
+
readonly lockService: LockService;
|
|
29
|
+
readonly log: KernelLogger;
|
|
30
|
+
constructor(db: KernelDb, providers: Pick<SandboxProviders, "lookup">, config: KernelConfigService, lockService: LockService, log: KernelLogger);
|
|
31
|
+
tick(signal?: AbortSignal): Promise<void>;
|
|
32
|
+
/** One run (see the class); `signal` (the stop, or a lost run lock) is read between rows. */
|
|
33
|
+
runOnce(now?: Date, signal?: AbortSignal): Promise<LegacyCleanupResult>;
|
|
34
|
+
}
|