@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,936 @@
|
|
|
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 { createHash } from "node:crypto";
|
|
11
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
12
|
+
import { sql } from "kysely";
|
|
13
|
+
import { templateTypeClashes, templateTypeOf } from "../agents/templates.js";
|
|
14
|
+
import { ApiError } from "../errors.js";
|
|
15
|
+
import { audit } from "../identity/audit.js";
|
|
16
|
+
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
17
|
+
import { notifyItemShared } from "../inbox/org-notices.js";
|
|
18
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
19
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
20
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
21
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
22
|
+
import { assertOrgsExist } from "./catalog-items.js";
|
|
23
|
+
import { ComponentPromotion, notOwnedError, PROMOTION_ATTEMPTS, PromotionStale, promotionStaleError, } from "./component-promotion.js";
|
|
24
|
+
import { agentsUsing, COMPONENT_KINDS, componentLocked, componentOffered, componentOn, componentPluginOn, connectorsMadeFrom, listedIn, loadComponents, loadScopeState, pluginFactsOf, skillNameClashes, switchOf, } from "./component-state.js";
|
|
25
|
+
import { assertOwnerListed, assertShareable, assertShareableTarget, newlySharedWith, ownerOf, ownersOf, } from "./ownership.js";
|
|
26
|
+
const notFound = () => new ApiError("component.not_found", "Component not found");
|
|
27
|
+
const staleError = () => new ApiError("plugin.scope_stale", "What this change affects has changed since the preview; preview it again and confirm the new hash");
|
|
28
|
+
const builtinError = () => new ApiError("plugin.builtin", "This component belongs to a built-in plugin: it is on in every organization and its scope cannot be changed or disabled");
|
|
29
|
+
/** The org action that manages a kind of component (the org admin's). */
|
|
30
|
+
const ACTION = {
|
|
31
|
+
skill: "skills.manage",
|
|
32
|
+
agent_template: "agents.manage",
|
|
33
|
+
connector_template: "connectors.manage",
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* 409 `plugin.skill_conflict` listing the orgs whose own skills use a component's name (rule 10);
|
|
37
|
+
* for an agent template 409 `agent_template.name_taken` listing the orgs that already use its
|
|
38
|
+
* roster type (ruling P4-13; details `[{ orgId, type, templateId, owner }]`, one per clashing
|
|
39
|
+
* template, `owner` as save-as names it).
|
|
40
|
+
*/
|
|
41
|
+
export function nameConflictError(conflicts, kind = "skill") {
|
|
42
|
+
if (kind === "agent_template") {
|
|
43
|
+
// the save-as wording (ruling P4-9), naming each clashing template's owner
|
|
44
|
+
const whose = (o, orgId) => o === undefined || o.kind === "platform"
|
|
45
|
+
? "the platform's"
|
|
46
|
+
: o.orgId === orgId
|
|
47
|
+
? "its own"
|
|
48
|
+
: `from organization ${o.name}`;
|
|
49
|
+
return new ApiError("agent_template.name_taken", conflicts
|
|
50
|
+
.map((c) => `An agent template named ${c.name} is already used in organization ${c.orgName} (${c.skills.map((_, i) => whose(c.owners?.[i], c.orgId)).join(", ")}); one name cannot be offered there twice.`)
|
|
51
|
+
.join("\n"), conflicts.flatMap((c) => c.skills.map((templateId, i) => ({
|
|
52
|
+
orgId: c.orgId,
|
|
53
|
+
type: c.name,
|
|
54
|
+
templateId,
|
|
55
|
+
owner: c.owners?.[i] ?? { kind: "platform" },
|
|
56
|
+
}))));
|
|
57
|
+
}
|
|
58
|
+
return new ApiError("plugin.skill_conflict", conflicts
|
|
59
|
+
.map((c) => `Skill "${c.name}" is already used in organization ${c.orgName} (${c.plugins.length > 0 ? `plugin "${c.plugins.join('", "')}"` : "its own skill"}); it would be offered there twice.`)
|
|
60
|
+
.join("\n"), conflicts.map((c) => ({
|
|
61
|
+
skill: c.name,
|
|
62
|
+
orgId: c.orgId,
|
|
63
|
+
skills: c.skills,
|
|
64
|
+
source: c.plugins.length > 0
|
|
65
|
+
? { kind: "plugin", name: c.plugins[0], version: "" }
|
|
66
|
+
: { kind: "org" },
|
|
67
|
+
})));
|
|
68
|
+
}
|
|
69
|
+
/** The hash of a preview: sha256 over its sorted JSON, the target included. */
|
|
70
|
+
function previewHash(c, target, p) {
|
|
71
|
+
return createHash("sha256")
|
|
72
|
+
.update(JSON.stringify({
|
|
73
|
+
component: { kind: c.kind, id: c.id },
|
|
74
|
+
target: { ...target, orgs: [...target.orgs].sort() },
|
|
75
|
+
affected: [...p.affected]
|
|
76
|
+
.sort((a, b) => a.orgId.localeCompare(b.orgId))
|
|
77
|
+
.map((a) => ({ ...a, agents: [...a.agents].sort((x, y) => x.id.localeCompare(y.id)) })),
|
|
78
|
+
conflicts: [...p.conflicts].sort((a, b) => a.orgId.localeCompare(b.orgId)),
|
|
79
|
+
}))
|
|
80
|
+
.digest("hex");
|
|
81
|
+
}
|
|
82
|
+
/** The confirm hash of an org switch-off preview. */
|
|
83
|
+
function switchHash(orgId, c, preview) {
|
|
84
|
+
return createHash("sha256")
|
|
85
|
+
.update(JSON.stringify({ orgId, kind: c.kind, id: c.id, ...preview }))
|
|
86
|
+
.digest("hex");
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Component scope and org switches (plugin scope phase 2, Task 6; spec §5 rules 2, 5, 8, 10, 11,
|
|
90
|
+
* §13.5). The super admin gives a platform component its own scope (`all` / `optional` / `named`),
|
|
91
|
+
* sends it back to following its plugin, disables it on the whole deployment or shows it to other
|
|
92
|
+
* orgs; each change that takes something away is previewed and confirmed with `scopeHash`
|
|
93
|
+
* (recomputed under the component row lock; a difference -> 409 `plugin.scope_stale`), and one that
|
|
94
|
+
* would offer a skill to an org whose own skill has its name is refused (409 `plugin.skill_conflict`).
|
|
95
|
+
* An org admin switches one component on or off in the org (only that component, rule 5); one of a
|
|
96
|
+
* builtin plugin -> 409 `plugin.scope_locked` (an `all` one may go off, layering spec §4); switching
|
|
97
|
+
* off something in use is previewed with its agents first.
|
|
98
|
+
* Name clashes are checked for skills only: an org agent template always carries its plugin's
|
|
99
|
+
* type, so one with a platform template's type is a copy of it. Components are resolved at read
|
|
100
|
+
* time (skills/usable.ts, agents/templates.ts), so nothing is enqueued. Stateless, shared by every
|
|
101
|
+
* replica.
|
|
102
|
+
*/
|
|
103
|
+
let ComponentScopeService = class ComponentScopeService {
|
|
104
|
+
kdb;
|
|
105
|
+
adminLock;
|
|
106
|
+
orgLock;
|
|
107
|
+
promotion;
|
|
108
|
+
txHost;
|
|
109
|
+
constructor(kdb, adminLock,
|
|
110
|
+
/** The org row lock (orgs/org-lock.ts): joins the caller's transaction. */
|
|
111
|
+
orgLock,
|
|
112
|
+
/** Promote on share (ruling P3-3): an org row shown or associated becomes a platform row. */
|
|
113
|
+
promotion, txHost) {
|
|
114
|
+
this.kdb = kdb;
|
|
115
|
+
this.adminLock = adminLock;
|
|
116
|
+
this.orgLock = orgLock;
|
|
117
|
+
this.promotion = promotion;
|
|
118
|
+
this.txHost = txHost;
|
|
119
|
+
}
|
|
120
|
+
get db() {
|
|
121
|
+
return this.kdb.db;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* What the admin routes act on (ruling P3-23): the platform component `id`, an org row the org
|
|
125
|
+
* promoted already (its platform row), or an org's own row not promoted yet. A connector
|
|
126
|
+
* template has no org rows; anything else -> 404 `component.not_found`.
|
|
127
|
+
*/
|
|
128
|
+
async resolve(kind, id) {
|
|
129
|
+
const [c] = await loadComponents(this.db, kind, { ids: [id] });
|
|
130
|
+
if (c)
|
|
131
|
+
return { c };
|
|
132
|
+
if (kind === "connector_template")
|
|
133
|
+
throw notFound();
|
|
134
|
+
const org = await this.promotion.orgRow(kind, id);
|
|
135
|
+
if (!org)
|
|
136
|
+
throw notFound();
|
|
137
|
+
if (org.link === null)
|
|
138
|
+
return { org };
|
|
139
|
+
const [linked] = await loadComponents(this.db, kind, { ids: [org.link] });
|
|
140
|
+
if (!linked)
|
|
141
|
+
throw notFound();
|
|
142
|
+
return { c: linked };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Runs `write` with the org row prepared for promotion ({@link ComponentPromotion.prepare}, files
|
|
146
|
+
* copied before the transaction), preparing again when the row changed meanwhile.
|
|
147
|
+
*/
|
|
148
|
+
async withPromotion(kind, orgRowId, write) {
|
|
149
|
+
for (let attempt = 1;; attempt++) {
|
|
150
|
+
const prepared = await this.promotion.prepare(kind, orgRowId);
|
|
151
|
+
try {
|
|
152
|
+
return await write(prepared);
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
await this.promotion.discard(prepared);
|
|
156
|
+
if (!(e instanceof PromotionStale))
|
|
157
|
+
throw e;
|
|
158
|
+
if (attempt >= PROMOTION_ATTEMPTS)
|
|
159
|
+
throw promotionStaleError();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/** The platform components of `kind`, with their effective scope and the orgs they are on in. */
|
|
164
|
+
async list(kind) {
|
|
165
|
+
const comps = await loadComponents(this.db, kind);
|
|
166
|
+
const st = await loadScopeState(this.db, kind, comps);
|
|
167
|
+
const orgs = await this.liveOrgs();
|
|
168
|
+
const owners = await ownersOf(this.db, comps.flatMap((c) => (c.ownerOrgId === null ? [] : [c.ownerOrgId])));
|
|
169
|
+
const platform = comps.map((c) => {
|
|
170
|
+
const plugin = c.itemId === null ? undefined : st.plugins.get(c.itemId);
|
|
171
|
+
const follow = c.scopeMode === "follow" && c.itemId !== null;
|
|
172
|
+
const scope = follow
|
|
173
|
+
? plugin?.builtin
|
|
174
|
+
? "all"
|
|
175
|
+
: (plugin?.scope ?? c.scope)
|
|
176
|
+
: c.scope;
|
|
177
|
+
const list = follow
|
|
178
|
+
? (st.pluginListed.get(c.itemId) ?? new Set())
|
|
179
|
+
: (st.listed.get(c.id) ?? new Set());
|
|
180
|
+
return {
|
|
181
|
+
kind,
|
|
182
|
+
id: c.id,
|
|
183
|
+
name: c.name,
|
|
184
|
+
description: c.description,
|
|
185
|
+
plugin: c.plugin,
|
|
186
|
+
itemId: c.itemId,
|
|
187
|
+
owner: ownerOf(c.ownerOrgId, owners),
|
|
188
|
+
shareable: c.shareable,
|
|
189
|
+
promoted: c.itemId === null && c.originOrgId !== null,
|
|
190
|
+
builtin: plugin?.builtin === true,
|
|
191
|
+
scopeMode: c.scopeMode,
|
|
192
|
+
scope,
|
|
193
|
+
orgs: scope === "named" ? [...list].sort() : [],
|
|
194
|
+
disabled: c.disabled,
|
|
195
|
+
pluginStopped: c.itemId !== null && (plugin === undefined || plugin.disabled),
|
|
196
|
+
shownToOthers: c.shownToOthers,
|
|
197
|
+
version: c.version,
|
|
198
|
+
onIn: orgs
|
|
199
|
+
.filter((o) => this.on(c, st, o.id))
|
|
200
|
+
.map((o) => o.id)
|
|
201
|
+
.sort(),
|
|
202
|
+
offCount: scope === "all" && plugin?.builtin !== true
|
|
203
|
+
? orgs.filter((o) => switchOf(st, c.id, o.id) === false).length
|
|
204
|
+
: 0,
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
const owned = await this.orgOwned(kind, orgs);
|
|
208
|
+
return [...platform, ...owned].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* The platform components offered to the org (`kind` / `itemId`: only those), by kind then name:
|
|
212
|
+
* on there, or visible to it and not stopped on the deployment (spec §5 rules 5, 11, §13.5).
|
|
213
|
+
*/
|
|
214
|
+
async orgList(orgId, filter) {
|
|
215
|
+
const out = [];
|
|
216
|
+
for (const kind of filter.kind !== undefined ? [filter.kind] : COMPONENT_KINDS) {
|
|
217
|
+
const comps = await loadComponents(this.db, kind, filter.itemId !== undefined ? { itemId: filter.itemId } : {});
|
|
218
|
+
const st = await loadScopeState(this.db, kind, comps);
|
|
219
|
+
const linked = await this.linkedCopies(orgId, kind);
|
|
220
|
+
const owners = await ownersOf(this.db, comps.flatMap((c) => (c.ownerOrgId === null ? [] : [c.ownerOrgId])));
|
|
221
|
+
const rows = [];
|
|
222
|
+
for (const c of comps) {
|
|
223
|
+
const p = pluginFactsOf(st, c.itemId, orgId);
|
|
224
|
+
const listed = listedIn(st, c.id, orgId);
|
|
225
|
+
const sw = switchOf(st, c.id, orgId);
|
|
226
|
+
const on = componentOn(c, p, listed, sw);
|
|
227
|
+
if (!on && !componentOffered(c, p, listed))
|
|
228
|
+
continue;
|
|
229
|
+
const locked = componentLocked(c, p);
|
|
230
|
+
const pluginOn = componentPluginOn(c, p);
|
|
231
|
+
rows.push({
|
|
232
|
+
kind,
|
|
233
|
+
id: c.id,
|
|
234
|
+
name: c.name,
|
|
235
|
+
description: c.description,
|
|
236
|
+
plugin: c.plugin,
|
|
237
|
+
itemId: c.itemId,
|
|
238
|
+
version: c.version,
|
|
239
|
+
scopeMode: c.scopeMode,
|
|
240
|
+
switch: sw,
|
|
241
|
+
on,
|
|
242
|
+
locked,
|
|
243
|
+
pluginOn,
|
|
244
|
+
switchable: !locked && pluginOn,
|
|
245
|
+
platformDefault: !locked && (c.scopeMode === "follow" ? p?.scope === "all" : c.scope === "all"),
|
|
246
|
+
linkedIds: linked.get(c.id) ?? [],
|
|
247
|
+
owner: ownerOf(c.ownerOrgId, owners),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
rows.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
251
|
+
out.push(...rows);
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The org's copies of platform skills or agent templates linked without a pin (ruling B2), by
|
|
257
|
+
* platform id: they resolve to it, so agents that select them use it (none for connector
|
|
258
|
+
* templates).
|
|
259
|
+
*/
|
|
260
|
+
async linkedCopies(orgId, kind) {
|
|
261
|
+
const out = new Map();
|
|
262
|
+
if (kind === "connector_template")
|
|
263
|
+
return out;
|
|
264
|
+
const rows = kind === "skill"
|
|
265
|
+
? await this.db
|
|
266
|
+
.selectFrom("skills")
|
|
267
|
+
.select(["id", "platform_skill_id as link"])
|
|
268
|
+
.where("org_id", "=", orgId)
|
|
269
|
+
.where("scope", "=", "org")
|
|
270
|
+
.where("deleted_at", "is", null)
|
|
271
|
+
.where("pinned_version", "is", null)
|
|
272
|
+
.where("platform_skill_id", "is not", null)
|
|
273
|
+
.orderBy("id")
|
|
274
|
+
.execute()
|
|
275
|
+
: await this.db
|
|
276
|
+
.selectFrom("agent_templates")
|
|
277
|
+
.select(["id", "platform_template_id as link"])
|
|
278
|
+
.where("org_id", "=", orgId)
|
|
279
|
+
.where("deleted_at", "is", null)
|
|
280
|
+
.where("pinned_version", "is", null)
|
|
281
|
+
.where("platform_template_id", "is not", null)
|
|
282
|
+
.orderBy("id")
|
|
283
|
+
.execute();
|
|
284
|
+
for (const r of rows) {
|
|
285
|
+
const k = r.link;
|
|
286
|
+
out.set(k, [...(out.get(k) ?? []), r.id]);
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* The orgs' own skills (org scope) and agent templates, not linked to a platform component
|
|
292
|
+
* (ruling P2-11): listed read-only, on in their org only. Connector templates have none.
|
|
293
|
+
*/
|
|
294
|
+
async orgOwned(kind, orgs) {
|
|
295
|
+
if (kind === "connector_template")
|
|
296
|
+
return [];
|
|
297
|
+
const live = new Set(orgs.map((o) => o.id));
|
|
298
|
+
const rows = kind === "skill"
|
|
299
|
+
? await this.db
|
|
300
|
+
.selectFrom("skills as s")
|
|
301
|
+
.leftJoin("catalog_items as c", "c.id", "s.catalog_item_id")
|
|
302
|
+
.select([
|
|
303
|
+
"s.id",
|
|
304
|
+
"s.org_id",
|
|
305
|
+
"s.name",
|
|
306
|
+
"s.description",
|
|
307
|
+
"s.current_version",
|
|
308
|
+
"s.catalog_item_id",
|
|
309
|
+
"s.shareable",
|
|
310
|
+
"c.name as plugin",
|
|
311
|
+
])
|
|
312
|
+
.where("s.scope", "=", "org")
|
|
313
|
+
.where("s.deleted_at", "is", null)
|
|
314
|
+
.where("s.platform_skill_id", "is", null)
|
|
315
|
+
.execute()
|
|
316
|
+
: (await this.db
|
|
317
|
+
.selectFrom("agent_templates")
|
|
318
|
+
.select([
|
|
319
|
+
"id",
|
|
320
|
+
"org_id",
|
|
321
|
+
"name",
|
|
322
|
+
"current_version",
|
|
323
|
+
"catalog_item_id",
|
|
324
|
+
"shareable",
|
|
325
|
+
"plugin_name as plugin",
|
|
326
|
+
])
|
|
327
|
+
.where("deleted_at", "is", null)
|
|
328
|
+
.where("platform_template_id", "is", null)
|
|
329
|
+
.execute()).map((r) => ({ ...r, description: null }));
|
|
330
|
+
const kept = rows.filter((r) => live.has(r.org_id));
|
|
331
|
+
const owners = await ownersOf(this.db, kept.map((r) => r.org_id));
|
|
332
|
+
return kept.map((r) => ({
|
|
333
|
+
kind,
|
|
334
|
+
id: r.id,
|
|
335
|
+
name: r.name,
|
|
336
|
+
description: r.description,
|
|
337
|
+
plugin: r.plugin,
|
|
338
|
+
itemId: r.catalog_item_id,
|
|
339
|
+
owner: ownerOf(r.org_id, owners),
|
|
340
|
+
shareable: r.shareable,
|
|
341
|
+
promoted: false,
|
|
342
|
+
builtin: false,
|
|
343
|
+
scopeMode: "own",
|
|
344
|
+
scope: "named",
|
|
345
|
+
orgs: [r.org_id],
|
|
346
|
+
disabled: false,
|
|
347
|
+
pluginStopped: false,
|
|
348
|
+
shownToOthers: false,
|
|
349
|
+
version: String(r.current_version),
|
|
350
|
+
onIn: [r.org_id],
|
|
351
|
+
offCount: 0,
|
|
352
|
+
}));
|
|
353
|
+
}
|
|
354
|
+
/** The preview of a scope change, a disable or a return to following the plugin (nothing written). */
|
|
355
|
+
async preview(kind, id, target) {
|
|
356
|
+
const r = await this.resolve(kind, id);
|
|
357
|
+
if ("c" in r) {
|
|
358
|
+
const c = await this.component(kind, r.c.id, false);
|
|
359
|
+
return this.compute(c, await this.targetOf(c, target), { hashId: id });
|
|
360
|
+
}
|
|
361
|
+
// an org row not promoted yet (P3-23): as the platform row it would become, `named: [owner]`;
|
|
362
|
+
// a disable is platform-only
|
|
363
|
+
if ("disabled" in target)
|
|
364
|
+
throw notFound();
|
|
365
|
+
const v = virtualOf(r.org);
|
|
366
|
+
const listed = [r.org.orgId];
|
|
367
|
+
return this.compute(v, await this.targetOf(v, target, listed), { hashId: id, listed });
|
|
368
|
+
}
|
|
369
|
+
/** Gives the component its own scope, or makes it follow its plugin again, after its preview. */
|
|
370
|
+
async setScope(actor, kind, id, body, opts = {}) {
|
|
371
|
+
const { scopeHash, ...target } = body;
|
|
372
|
+
const r = await this.resolve(kind, id);
|
|
373
|
+
if ("c" in r) {
|
|
374
|
+
await this.writeScope(actor, kind, r.c.id, target, scopeHash, opts, { hashId: id });
|
|
375
|
+
return this.view(kind, r.c.id);
|
|
376
|
+
}
|
|
377
|
+
// An org row not promoted yet (P3-23): a change that shows it to another org promotes it first
|
|
378
|
+
// (ruling P3-3), after the owner and share gate checks on the org row and the preview's hash
|
|
379
|
+
const v = virtualOf(r.org);
|
|
380
|
+
const listed = [r.org.orgId];
|
|
381
|
+
const t = await this.targetOf(v, target, listed);
|
|
382
|
+
if (t.scopeMode === "own" && t.scope === "named" && t.orgs.join() === listed.join()) {
|
|
383
|
+
return this.view(kind, id);
|
|
384
|
+
}
|
|
385
|
+
assertPromotable(r.org);
|
|
386
|
+
assertOwnerListed(gateRow(v), t);
|
|
387
|
+
assertShareable(gateRow(v));
|
|
388
|
+
const p = await this.compute(v, t, { hashId: id, listed });
|
|
389
|
+
if (p.scopeHash !== scopeHash)
|
|
390
|
+
throw staleError();
|
|
391
|
+
if (p.conflicts.length > 0)
|
|
392
|
+
throw nameConflictError(p.conflicts, kind);
|
|
393
|
+
const promotable = kind;
|
|
394
|
+
const written = await this.withPromotion(promotable, id, (prepared) => this.writeScope(actor, kind, prepared.platformId, target, scopeHash, opts, {
|
|
395
|
+
hashId: id,
|
|
396
|
+
promote: prepared,
|
|
397
|
+
}));
|
|
398
|
+
return this.view(kind, written);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Disables the component on the whole deployment (after its preview, `scopeHash` required) or
|
|
402
|
+
* enables it again (no hash; refused while an org it would be offered to has a skill of its name).
|
|
403
|
+
*/
|
|
404
|
+
async setDisabled(actor, kind, id, body, opts = {}) {
|
|
405
|
+
if (body.disabled && body.scopeHash === undefined) {
|
|
406
|
+
throw new ApiError("validation_failed", "scopeHash: required when disabling (from POST scope/preview with disabled: true)", [{ path: "scopeHash", message: "required when disabling" }]);
|
|
407
|
+
}
|
|
408
|
+
await this.writeDisabled(actor, kind, id, body.disabled, body.scopeHash, opts);
|
|
409
|
+
return this.view(kind, id);
|
|
410
|
+
}
|
|
411
|
+
/** Shows or hides the component to orgs outside its `named` list (never makes it usable). */
|
|
412
|
+
async setShown(actor, kind, id, shown, opts = {}) {
|
|
413
|
+
const r = await this.resolve(kind, id);
|
|
414
|
+
if ("c" in r) {
|
|
415
|
+
await this.writeShown(actor, kind, r.c.id, shown, opts);
|
|
416
|
+
return this.view(kind, r.c.id);
|
|
417
|
+
}
|
|
418
|
+
// An org row not promoted yet is shown to nobody: hiding it changes nothing; showing it goes
|
|
419
|
+
// through the share gate on the org row, then promotes it (rulings P3-3, P3-23)
|
|
420
|
+
if (!shown)
|
|
421
|
+
return this.view(kind, id);
|
|
422
|
+
assertPromotable(r.org);
|
|
423
|
+
assertShareable(gateRow(virtualOf(r.org)));
|
|
424
|
+
const written = await this.withPromotion(kind, id, (prepared) => this.writeShown(actor, kind, prepared.platformId, true, opts, prepared));
|
|
425
|
+
return this.view(kind, written);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* The org admin's switch of one component (`PUT orgs/:orgId/components/:kind/:id/switch`): only
|
|
429
|
+
* this component (rule 5). A component not offered to the org -> 404. On: refused while the
|
|
430
|
+
* component or its plugin is disabled (`plugin.disabled`) or an own skill of the org has its name
|
|
431
|
+
* (`plugin.skill_conflict`, rule 10). Off: of a builtin plugin -> `plugin.scope_locked`; while it
|
|
432
|
+
* is on, without `confirm` the preview (agents that use it) and its hash are returned, with the
|
|
433
|
+
* current hash the switch is written (a changed preview -> `plugin.switch_stale`).
|
|
434
|
+
*/
|
|
435
|
+
async setSwitch(orgId, actor, kind, id, body, actorTokenId) {
|
|
436
|
+
await this.orgLock.lockAndAuthorize(orgId, actor, ACTION[kind]);
|
|
437
|
+
// The rows an unshare narrows (ruling P3-25) are locked before the scope is read, in its order
|
|
438
|
+
// (plugin, then component): a switch-on never commits against a scope narrowed meanwhile
|
|
439
|
+
const [found] = await loadComponents(this.db, kind, { ids: [id] });
|
|
440
|
+
if (!found)
|
|
441
|
+
throw notFound();
|
|
442
|
+
if (found.itemId !== null)
|
|
443
|
+
await lockItemShared(this.db, found.itemId);
|
|
444
|
+
const [c] = await loadComponents(this.db, kind, { ids: [id], forUpdate: true });
|
|
445
|
+
if (!c)
|
|
446
|
+
throw notFound();
|
|
447
|
+
const st = await loadScopeState(this.db, kind, [c]);
|
|
448
|
+
const p = pluginFactsOf(st, c.itemId, orgId);
|
|
449
|
+
const listed = listedIn(st, c.id, orgId);
|
|
450
|
+
const sw = switchOf(st, c.id, orgId);
|
|
451
|
+
const on = componentOn(c, p, listed, sw);
|
|
452
|
+
// Disabled on the deployment (the component or its plugin): it keeps its scope, so the org's
|
|
453
|
+
// switch can still be turned off, never on; one its scope does not offer the org is unknown
|
|
454
|
+
const stopped = c.disabled || (p?.live === true && p.disabled);
|
|
455
|
+
const offered = componentOffered({ ...c, disabled: false }, p && { ...p, disabled: false }, listed);
|
|
456
|
+
if (!on && !offered)
|
|
457
|
+
throw notFound();
|
|
458
|
+
if (body.enabled && stopped) {
|
|
459
|
+
throw new ApiError("plugin.disabled", "This component is disabled by the super admin and cannot be switched on");
|
|
460
|
+
}
|
|
461
|
+
if (body.enabled) {
|
|
462
|
+
if (kind !== "connector_template" && !on) {
|
|
463
|
+
const clash = kind === "skill"
|
|
464
|
+
? await skillNameClashes(this.db, orgId, c, c.name)
|
|
465
|
+
: await templateTypeClashes(this.db, orgId, c);
|
|
466
|
+
if (clash.skills.length > 0) {
|
|
467
|
+
const [org] = await this.liveOrgs(orgId);
|
|
468
|
+
const name = kind === "skill" ? c.name : templateTypeOf(c.plugin, c.name);
|
|
469
|
+
throw nameConflictError([{ orgId, orgName: org?.name ?? orgId, name, ...clash }], kind);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
if (componentLocked(c, p)) {
|
|
475
|
+
throw new ApiError("plugin.scope_locked", "This component belongs to a built-in plugin: it is on for every organization and cannot be switched off here");
|
|
476
|
+
}
|
|
477
|
+
if (on) {
|
|
478
|
+
const preview = {
|
|
479
|
+
agents: await agentsUsing(this.db, orgId, kind, [c.id]),
|
|
480
|
+
connectorsKept: kind === "connector_template" ? await connectorsMadeFrom(this.db, orgId, c.id) : 0,
|
|
481
|
+
};
|
|
482
|
+
const confirm = switchHash(orgId, c, preview);
|
|
483
|
+
if (body.confirm === undefined)
|
|
484
|
+
return { kind: "preview", preview, confirm };
|
|
485
|
+
if (body.confirm !== confirm) {
|
|
486
|
+
throw new ApiError("plugin.switch_stale", "What switching this component off affects has changed; review it and confirm again");
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
if (sw !== body.enabled) {
|
|
491
|
+
await this.db
|
|
492
|
+
.insertInto("component_org_switches")
|
|
493
|
+
.values({
|
|
494
|
+
kind,
|
|
495
|
+
component_id: c.id,
|
|
496
|
+
org_id: orgId,
|
|
497
|
+
enabled: body.enabled,
|
|
498
|
+
updated_by: actor,
|
|
499
|
+
})
|
|
500
|
+
.onConflict((oc) => oc.columns(["kind", "component_id", "org_id"]).doUpdateSet({
|
|
501
|
+
enabled: body.enabled,
|
|
502
|
+
updated_by: actor,
|
|
503
|
+
updated_at: sql `now()`,
|
|
504
|
+
}))
|
|
505
|
+
.execute();
|
|
506
|
+
await audit(this.db, {
|
|
507
|
+
actorAccountId: actor,
|
|
508
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
509
|
+
orgId,
|
|
510
|
+
action: "component.org_switched",
|
|
511
|
+
target: c.id,
|
|
512
|
+
detail: { kind, name: c.name, plugin: c.plugin, from: sw, to: body.enabled },
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
kind: "done",
|
|
517
|
+
component: {
|
|
518
|
+
kind,
|
|
519
|
+
id: c.id,
|
|
520
|
+
name: c.name,
|
|
521
|
+
plugin: c.plugin,
|
|
522
|
+
switch: body.enabled,
|
|
523
|
+
on: componentOn(c, p, listed, body.enabled),
|
|
524
|
+
locked: componentLocked(c, p),
|
|
525
|
+
},
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* `x.hashId`: the id the preview was asked for (an org row's id before its promotion);
|
|
530
|
+
* `x.promote`: the org row to promote first, in this transaction. Returns the id written.
|
|
531
|
+
*/
|
|
532
|
+
async writeScope(actor, kind, id, target, hash, opts, x) {
|
|
533
|
+
await this.adminLock.lockAndAuthorize(actor);
|
|
534
|
+
if (x.promote)
|
|
535
|
+
id = await this.promotion.promote(x.promote, actor);
|
|
536
|
+
const c = await this.component(kind, id, true);
|
|
537
|
+
const t = await this.targetOf(c, target);
|
|
538
|
+
const from = await this.listed(kind, id);
|
|
539
|
+
// Its own scope: the owner stays listed (P3-17), widening goes through the share gate (P3-16);
|
|
540
|
+
// following the plugin again takes the plugin's scope, which its own writer gates
|
|
541
|
+
if (t.scopeMode === "own") {
|
|
542
|
+
assertOwnerListed(gateRow(c), t);
|
|
543
|
+
assertShareableTarget(gateRow(c), await this.effectiveScope(c, from), t);
|
|
544
|
+
}
|
|
545
|
+
const p = await this.compute(c, t, { hashId: x.hashId });
|
|
546
|
+
if (p.scopeHash !== hash)
|
|
547
|
+
throw staleError();
|
|
548
|
+
if (p.conflicts.length > 0)
|
|
549
|
+
throw nameConflictError(p.conflicts, kind);
|
|
550
|
+
if (c.scopeMode === t.scopeMode && c.scope === t.scope && from.join() === t.orgs.join()) {
|
|
551
|
+
return id;
|
|
552
|
+
}
|
|
553
|
+
const before = await this.effectiveScope(c, from);
|
|
554
|
+
await this.db
|
|
555
|
+
.updateTable(TABLE[kind])
|
|
556
|
+
.set({
|
|
557
|
+
scope_mode: t.scopeMode,
|
|
558
|
+
scope: t.scope,
|
|
559
|
+
scope_version: sql `scope_version + 1`,
|
|
560
|
+
updated_at: sql `now()`,
|
|
561
|
+
})
|
|
562
|
+
.where("id", "=", id)
|
|
563
|
+
.execute();
|
|
564
|
+
await this.db
|
|
565
|
+
.deleteFrom("component_scope_orgs")
|
|
566
|
+
.where("kind", "=", kind)
|
|
567
|
+
.where("component_id", "=", id)
|
|
568
|
+
.execute();
|
|
569
|
+
if (t.scopeMode === "own" && t.orgs.length > 0) {
|
|
570
|
+
await this.db
|
|
571
|
+
.insertInto("component_scope_orgs")
|
|
572
|
+
.values(t.orgs.map((org_id) => ({ kind, component_id: id, org_id })))
|
|
573
|
+
.execute();
|
|
574
|
+
}
|
|
575
|
+
// An own scope that newly shows an org-owned component tells its owner (P3-22)
|
|
576
|
+
if (t.scopeMode === "own" && kind !== "connector_template") {
|
|
577
|
+
const shared = newlySharedWith(before, t);
|
|
578
|
+
if (shared === "all_orgs" || shared.length > 0) {
|
|
579
|
+
await notifyItemShared(this.db, c.ownerOrgId, { kind, id }, c.name, shared);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
await audit(this.db, {
|
|
583
|
+
actorAccountId: actor,
|
|
584
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
585
|
+
action: "component.scope_changed",
|
|
586
|
+
target: id,
|
|
587
|
+
detail: {
|
|
588
|
+
kind,
|
|
589
|
+
name: c.name,
|
|
590
|
+
plugin: c.plugin,
|
|
591
|
+
from: { scopeMode: c.scopeMode, scope: c.scope, orgs: from },
|
|
592
|
+
to: { scopeMode: t.scopeMode, scope: t.scope, orgs: t.orgs },
|
|
593
|
+
},
|
|
594
|
+
});
|
|
595
|
+
return id;
|
|
596
|
+
}
|
|
597
|
+
async writeDisabled(actor, kind, id, disabled, hash, opts) {
|
|
598
|
+
await this.adminLock.lockAndAuthorize(actor);
|
|
599
|
+
const c = await this.component(kind, id, true);
|
|
600
|
+
if (c.disabled === disabled)
|
|
601
|
+
return;
|
|
602
|
+
const p = await this.compute(c, await this.targetOf(c, { disabled }));
|
|
603
|
+
if (disabled && p.scopeHash !== hash)
|
|
604
|
+
throw staleError();
|
|
605
|
+
if (p.conflicts.length > 0)
|
|
606
|
+
throw nameConflictError(p.conflicts, kind);
|
|
607
|
+
await this.db
|
|
608
|
+
.updateTable(TABLE[kind])
|
|
609
|
+
.set({
|
|
610
|
+
disabled,
|
|
611
|
+
scope_version: sql `scope_version + 1`,
|
|
612
|
+
updated_at: sql `now()`,
|
|
613
|
+
})
|
|
614
|
+
.where("id", "=", id)
|
|
615
|
+
.execute();
|
|
616
|
+
await audit(this.db, {
|
|
617
|
+
actorAccountId: actor,
|
|
618
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
619
|
+
action: "component.scope_changed",
|
|
620
|
+
target: id,
|
|
621
|
+
detail: {
|
|
622
|
+
kind,
|
|
623
|
+
name: c.name,
|
|
624
|
+
plugin: c.plugin,
|
|
625
|
+
disabled: { from: c.disabled, to: disabled },
|
|
626
|
+
},
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/** `promote`: the org row to promote first, in this transaction. Returns the id written. */
|
|
630
|
+
async writeShown(actor, kind, id, shown, opts, promote) {
|
|
631
|
+
await this.adminLock.lockAndAuthorize(actor);
|
|
632
|
+
if (promote)
|
|
633
|
+
id = await this.promotion.promote(promote, actor);
|
|
634
|
+
const [c] = await loadComponents(this.db, kind, { ids: [id], forUpdate: true });
|
|
635
|
+
if (!c)
|
|
636
|
+
throw notFound();
|
|
637
|
+
// Showing goes through the share gate (P3-16); hiding is always allowed
|
|
638
|
+
if (shown)
|
|
639
|
+
assertShareable(gateRow(c));
|
|
640
|
+
if (c.shownToOthers === shown)
|
|
641
|
+
return id;
|
|
642
|
+
await this.db
|
|
643
|
+
.updateTable(TABLE[kind])
|
|
644
|
+
.set({ shown_to_others: shown, updated_at: sql `now()` })
|
|
645
|
+
.where("id", "=", id)
|
|
646
|
+
.execute();
|
|
647
|
+
await audit(this.db, {
|
|
648
|
+
actorAccountId: actor,
|
|
649
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
650
|
+
action: "component.shown_changed",
|
|
651
|
+
target: id,
|
|
652
|
+
detail: { kind, name: c.name, plugin: c.plugin, from: c.shownToOthers, to: shown },
|
|
653
|
+
});
|
|
654
|
+
return id;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* A live component's versions, newest first. A connector template keeps no history: its one entry
|
|
658
|
+
* is the current version. Missing (or removed) -> 404 `component.not_found`.
|
|
659
|
+
*/
|
|
660
|
+
async versions(kind, id) {
|
|
661
|
+
const r = await this.resolve(kind, id);
|
|
662
|
+
if ("org" in r)
|
|
663
|
+
return this.orgOwnedVersions(kind, id);
|
|
664
|
+
const c = r.c;
|
|
665
|
+
id = c.id;
|
|
666
|
+
if (kind === "connector_template") {
|
|
667
|
+
const row = await this.db
|
|
668
|
+
.selectFrom("platform_connector_templates")
|
|
669
|
+
.select("updated_at")
|
|
670
|
+
.where("id", "=", id)
|
|
671
|
+
.executeTakeFirstOrThrow();
|
|
672
|
+
return [
|
|
673
|
+
{
|
|
674
|
+
version: c.version,
|
|
675
|
+
catalogVersion: c.version,
|
|
676
|
+
updatedOnOwn: false,
|
|
677
|
+
createdAt: row.updated_at.toISOString(),
|
|
678
|
+
},
|
|
679
|
+
];
|
|
680
|
+
}
|
|
681
|
+
const rows = kind === "skill"
|
|
682
|
+
? await this.db
|
|
683
|
+
.selectFrom("platform_skill_versions")
|
|
684
|
+
.select(["version", "catalog_version", "updated_on_own", "created_at"])
|
|
685
|
+
.where("skill_id", "=", id)
|
|
686
|
+
.orderBy("version", "desc")
|
|
687
|
+
.execute()
|
|
688
|
+
: await this.db
|
|
689
|
+
.selectFrom("platform_agent_template_versions")
|
|
690
|
+
.select(["version", "catalog_version", "updated_on_own", "created_at"])
|
|
691
|
+
.where("template_id", "=", id)
|
|
692
|
+
.orderBy("version", "desc")
|
|
693
|
+
.execute();
|
|
694
|
+
return rows.map((r) => ({
|
|
695
|
+
version: String(r.version),
|
|
696
|
+
catalogVersion: r.catalog_version,
|
|
697
|
+
updatedOnOwn: r.updated_on_own,
|
|
698
|
+
createdAt: r.created_at.toISOString(),
|
|
699
|
+
}));
|
|
700
|
+
}
|
|
701
|
+
/** An org-owned skill's or agent template's versions (ruling P2-11); else 404. */
|
|
702
|
+
async orgOwnedVersions(kind, id) {
|
|
703
|
+
const owned = (await this.list(kind)).find((x) => x.id === id && x.owner.kind === "org");
|
|
704
|
+
if (!owned)
|
|
705
|
+
throw notFound();
|
|
706
|
+
const rows = kind === "skill"
|
|
707
|
+
? await this.db
|
|
708
|
+
.selectFrom("skill_versions")
|
|
709
|
+
.select(["version", "catalog_version", "created_at"])
|
|
710
|
+
.where("skill_id", "=", id)
|
|
711
|
+
.orderBy("version", "desc")
|
|
712
|
+
.execute()
|
|
713
|
+
: await this.db
|
|
714
|
+
.selectFrom("agent_template_versions")
|
|
715
|
+
.select(["version", "catalog_version", "created_at"])
|
|
716
|
+
.where("template_id", "=", id)
|
|
717
|
+
.orderBy("version", "desc")
|
|
718
|
+
.execute();
|
|
719
|
+
return rows.map((r) => ({
|
|
720
|
+
version: String(r.version),
|
|
721
|
+
catalogVersion: r.catalog_version,
|
|
722
|
+
updatedOnOwn: false,
|
|
723
|
+
createdAt: r.created_at.toISOString(),
|
|
724
|
+
}));
|
|
725
|
+
}
|
|
726
|
+
async view(kind, id) {
|
|
727
|
+
const v = (await this.list(kind)).find((x) => x.id === id);
|
|
728
|
+
if (!v)
|
|
729
|
+
throw notFound();
|
|
730
|
+
return v;
|
|
731
|
+
}
|
|
732
|
+
/** The live component (row locked with `forUpdate`); missing -> 404, of a builtin plugin -> 409. */
|
|
733
|
+
async component(kind, id, forUpdate) {
|
|
734
|
+
const [c] = await loadComponents(this.db, kind, { ids: [id], forUpdate });
|
|
735
|
+
if (!c)
|
|
736
|
+
throw notFound();
|
|
737
|
+
if (c.itemId !== null) {
|
|
738
|
+
const item = await this.db
|
|
739
|
+
.selectFrom("catalog_items")
|
|
740
|
+
.select("builtin")
|
|
741
|
+
.where("id", "=", c.itemId)
|
|
742
|
+
.executeTakeFirst();
|
|
743
|
+
if (item?.builtin)
|
|
744
|
+
throw builtinError();
|
|
745
|
+
}
|
|
746
|
+
return c;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* The scope that offers the component now: its own (`listed`: its own list), or for `follow` its
|
|
750
|
+
* plugin's (`all` for a builtin or deleted plugin: the widest, so nothing counts as widening).
|
|
751
|
+
*/
|
|
752
|
+
async effectiveScope(c, listed) {
|
|
753
|
+
if (c.scopeMode === "own" || c.itemId === null)
|
|
754
|
+
return { scope: c.scope, orgs: listed };
|
|
755
|
+
const item = await this.db
|
|
756
|
+
.selectFrom("catalog_items")
|
|
757
|
+
.select(["scope", "builtin"])
|
|
758
|
+
.where("id", "=", c.itemId)
|
|
759
|
+
.where("deleted_at", "is", null)
|
|
760
|
+
.executeTakeFirst();
|
|
761
|
+
if (!item || item.builtin)
|
|
762
|
+
return { scope: "all", orgs: [] };
|
|
763
|
+
const rows = await this.db
|
|
764
|
+
.selectFrom("catalog_item_scope_orgs")
|
|
765
|
+
.select("org_id")
|
|
766
|
+
.where("item_id", "=", c.itemId)
|
|
767
|
+
.execute();
|
|
768
|
+
return { scope: item.scope, orgs: rows.map((r) => r.org_id) };
|
|
769
|
+
}
|
|
770
|
+
/** The component's own `named` list, sorted. */
|
|
771
|
+
async listed(kind, id) {
|
|
772
|
+
const rows = await this.db
|
|
773
|
+
.selectFrom("component_scope_orgs")
|
|
774
|
+
.select("org_id")
|
|
775
|
+
.where("kind", "=", kind)
|
|
776
|
+
.where("component_id", "=", id)
|
|
777
|
+
.orderBy("org_id")
|
|
778
|
+
.execute();
|
|
779
|
+
return rows.map((r) => r.org_id);
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* The state after the change: `orgs` only with `named`, each a live org. `listed`: the list now
|
|
783
|
+
* (an org row not promoted yet: `[owner]`), else read.
|
|
784
|
+
*/
|
|
785
|
+
async targetOf(c, target, listed) {
|
|
786
|
+
const now = {
|
|
787
|
+
scopeMode: c.scopeMode,
|
|
788
|
+
scope: c.scope,
|
|
789
|
+
orgs: listed ?? (await this.listed(c.kind, c.id)),
|
|
790
|
+
disabled: c.disabled,
|
|
791
|
+
};
|
|
792
|
+
if ("disabled" in target)
|
|
793
|
+
return { ...now, disabled: target.disabled };
|
|
794
|
+
if ("follow" in target) {
|
|
795
|
+
if (c.itemId === null) {
|
|
796
|
+
throw new ApiError("validation_failed", "follow: this component has no plugin to follow", [
|
|
797
|
+
{ path: "follow", message: "the component has no plugin" },
|
|
798
|
+
]);
|
|
799
|
+
}
|
|
800
|
+
return { ...now, scopeMode: "follow", orgs: [] };
|
|
801
|
+
}
|
|
802
|
+
if (target.orgs !== undefined && target.scope !== "named") {
|
|
803
|
+
throw new ApiError("validation_failed", "orgs: only allowed with scope named", [
|
|
804
|
+
{ path: "orgs", message: "only allowed with scope named" },
|
|
805
|
+
]);
|
|
806
|
+
}
|
|
807
|
+
const orgs = [...new Set(target.orgs ?? [])].sort();
|
|
808
|
+
await assertOrgsExist(this.db, orgs);
|
|
809
|
+
return { scopeMode: "own", scope: target.scope, orgs, disabled: c.disabled };
|
|
810
|
+
}
|
|
811
|
+
/** Live orgs (`only`: that one), sorted by id. */
|
|
812
|
+
async liveOrgs(only) {
|
|
813
|
+
let q = this.db
|
|
814
|
+
.selectFrom("orgs")
|
|
815
|
+
.select(["id", "name"])
|
|
816
|
+
.where("deleted_at", "is", null)
|
|
817
|
+
.orderBy("id");
|
|
818
|
+
if (only !== undefined)
|
|
819
|
+
q = q.where("id", "=", only);
|
|
820
|
+
return q.execute();
|
|
821
|
+
}
|
|
822
|
+
on(c, st, orgId) {
|
|
823
|
+
return componentOn(c, pluginFactsOf(st, c.itemId, orgId), listedIn(st, c.id, orgId), switchOf(st, c.id, orgId));
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* The preview of moving `c` to `target` (read through the current context). `x.hashId`: the id
|
|
827
|
+
* the hash names (the one the preview was asked for); `x.listed`: the list now of an org row not
|
|
828
|
+
* promoted yet (`[owner]`).
|
|
829
|
+
*/
|
|
830
|
+
async compute(c, target, x = {}) {
|
|
831
|
+
const st = await loadScopeState(this.db, c.kind, [c]);
|
|
832
|
+
if (x.listed !== undefined)
|
|
833
|
+
st.listed.set(c.id, new Set(x.listed));
|
|
834
|
+
const after = {
|
|
835
|
+
scopeMode: target.scopeMode,
|
|
836
|
+
scope: target.scope,
|
|
837
|
+
disabled: target.disabled,
|
|
838
|
+
itemId: c.itemId,
|
|
839
|
+
};
|
|
840
|
+
const listedAfter = new Set(target.orgs);
|
|
841
|
+
const affected = [];
|
|
842
|
+
const conflicts = [];
|
|
843
|
+
for (const org of await this.liveOrgs()) {
|
|
844
|
+
const p = pluginFactsOf(st, c.itemId, org.id);
|
|
845
|
+
const listed = listedIn(st, c.id, org.id);
|
|
846
|
+
const sw = switchOf(st, c.id, org.id);
|
|
847
|
+
if (componentOn(c, p, listed, sw) && !componentOn(after, p, listedAfter.has(org.id), sw)) {
|
|
848
|
+
const agents = await agentsUsing(this.db, org.id, c.kind, [c.id]);
|
|
849
|
+
affected.push({
|
|
850
|
+
orgId: org.id,
|
|
851
|
+
orgName: org.name,
|
|
852
|
+
agents: agents.map((a) => ({ id: a.id, name: a.name })),
|
|
853
|
+
connectorsKept: c.kind === "connector_template" ? await connectorsMadeFrom(this.db, org.id, c.id) : 0,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
if (c.kind !== "connector_template" &&
|
|
857
|
+
componentOffered(after, p, listedAfter.has(org.id)) &&
|
|
858
|
+
!componentOffered(c, p, listed)) {
|
|
859
|
+
// rule 10: a skill by its name, an agent template by its roster type (ruling P4-13)
|
|
860
|
+
const clash = c.kind === "skill"
|
|
861
|
+
? await skillNameClashes(this.db, org.id, c, c.name)
|
|
862
|
+
: await templateTypeClashes(this.db, org.id, c);
|
|
863
|
+
if (clash.skills.length > 0) {
|
|
864
|
+
const name = c.kind === "skill" ? c.name : templateTypeOf(c.plugin, c.name);
|
|
865
|
+
conflicts.push({ orgId: org.id, orgName: org.name, name, ...clash });
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
const p = { affected, conflicts };
|
|
870
|
+
return { ...p, scopeHash: previewHash({ kind: c.kind, id: x.hashId ?? c.id }, target, p) };
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
__decorate([
|
|
874
|
+
Transactional()
|
|
875
|
+
], ComponentScopeService.prototype, "setSwitch", null);
|
|
876
|
+
__decorate([
|
|
877
|
+
Transactional()
|
|
878
|
+
], ComponentScopeService.prototype, "writeScope", null);
|
|
879
|
+
__decorate([
|
|
880
|
+
Transactional()
|
|
881
|
+
], ComponentScopeService.prototype, "writeDisabled", null);
|
|
882
|
+
__decorate([
|
|
883
|
+
Transactional()
|
|
884
|
+
], ComponentScopeService.prototype, "writeShown", null);
|
|
885
|
+
ComponentScopeService = __decorate([
|
|
886
|
+
Injectable(),
|
|
887
|
+
__param(0, Inject(KernelDb)),
|
|
888
|
+
__param(1, Inject(SuperAdminLock)),
|
|
889
|
+
__param(2, Inject(OrgLock)),
|
|
890
|
+
__param(3, Inject(ComponentPromotion)),
|
|
891
|
+
__param(4, Inject(TransactionHost))
|
|
892
|
+
], ComponentScopeService);
|
|
893
|
+
export { ComponentScopeService };
|
|
894
|
+
/** The plugin row FOR SHARE (exclusive with its scope writers and an unshare, which hold it FOR UPDATE). */
|
|
895
|
+
async function lockItemShared(db, itemId) {
|
|
896
|
+
await db.selectFrom("catalog_items").select("id").where("id", "=", itemId).forShare().execute();
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* An org row not promoted yet as the platform row it would become (ruling P3-3): its own scope
|
|
900
|
+
* `named: [owner]`, not shown, owned and created by its org.
|
|
901
|
+
*/
|
|
902
|
+
const virtualOf = (o) => ({
|
|
903
|
+
kind: o.kind,
|
|
904
|
+
id: o.id,
|
|
905
|
+
name: o.name,
|
|
906
|
+
plugin: o.plugin,
|
|
907
|
+
version: String(o.version),
|
|
908
|
+
description: null,
|
|
909
|
+
itemId: null,
|
|
910
|
+
scopeMode: "own",
|
|
911
|
+
scope: "named",
|
|
912
|
+
disabled: false,
|
|
913
|
+
shownToOthers: false,
|
|
914
|
+
ownerOrgId: o.orgId,
|
|
915
|
+
originOrgId: o.orgId,
|
|
916
|
+
shareable: o.shareable,
|
|
917
|
+
});
|
|
918
|
+
/**
|
|
919
|
+
* 409 `catalog.not_owned` unless the org row is content its org created itself (ruling P3-46): a
|
|
920
|
+
* skill without plugin provenance, an org template (no plugin, no catalog item; ruling P4-13).
|
|
921
|
+
*/
|
|
922
|
+
function assertPromotable(o) {
|
|
923
|
+
if (!o.ownable)
|
|
924
|
+
throw notOwnedError(o.name);
|
|
925
|
+
}
|
|
926
|
+
/** The share gate's view of a component row. */
|
|
927
|
+
const gateRow = (c) => ({
|
|
928
|
+
owner_org_id: c.ownerOrgId,
|
|
929
|
+
shareable: c.shareable,
|
|
930
|
+
name: c.name,
|
|
931
|
+
});
|
|
932
|
+
const TABLE = {
|
|
933
|
+
skill: "platform_skills",
|
|
934
|
+
agent_template: "platform_agent_templates",
|
|
935
|
+
connector_template: "platform_connector_templates",
|
|
936
|
+
};
|