@capybara-hq/kernel 0.1.0-rc.0 → 0.1.0-rc.10
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 +92 -8
- package/dist/admin/admin.controller.d.ts +52 -71
- package/dist/admin/admin.controller.js +117 -63
- package/dist/admin/admin.module.d.ts +3 -0
- package/dist/admin/admin.module.js +22 -0
- package/dist/admin/admin.schemas.d.ts +57 -0
- package/dist/admin/admin.schemas.js +50 -0
- package/dist/admin/extensions.controller.d.ts +47 -16
- package/dist/admin/extensions.controller.js +94 -23
- package/dist/admin/extensions.schemas.d.ts +7 -0
- package/dist/admin/extensions.schemas.js +10 -0
- package/dist/admin/limit-defaults.d.ts +20 -0
- package/dist/admin/limit-defaults.js +10 -0
- package/dist/admin/setup-lock.d.ts +16 -0
- package/dist/admin/setup-lock.js +47 -0
- package/dist/admin/setup.controller.d.ts +9 -9
- package/dist/admin/setup.controller.js +28 -26
- package/dist/admin/setup.service.d.ts +20 -28
- package/dist/admin/setup.service.js +65 -65
- package/dist/agents/agent-lookup.d.ts +72 -0
- package/dist/agents/agent-lookup.js +208 -0
- package/dist/agents/agent-profile.service.d.ts +31 -0
- package/dist/agents/agent-profile.service.js +122 -0
- package/dist/agents/agents.controller.d.ts +54 -169
- package/dist/agents/agents.controller.js +172 -37
- package/dist/agents/agents.module.d.ts +10 -0
- package/dist/agents/agents.module.js +71 -0
- package/dist/agents/agents.schemas.d.ts +389 -0
- package/dist/agents/agents.schemas.js +126 -0
- package/dist/agents/agents.service.d.ts +104 -76
- package/dist/agents/agents.service.js +509 -383
- package/dist/agents/definition.d.ts +133 -21
- package/dist/agents/definition.js +361 -41
- package/dist/agents/from-template.d.ts +106 -0
- package/dist/agents/from-template.js +680 -0
- package/dist/agents/from-template.service.d.ts +72 -0
- package/dist/agents/from-template.service.js +178 -0
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +44 -6
- package/dist/agents/models.controller.js +84 -8
- package/dist/agents/org-templates.d.ts +186 -0
- package/dist/agents/org-templates.js +868 -0
- package/dist/agents/pending-connector-requests.d.ts +79 -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/profile.d.ts +114 -0
- package/dist/agents/profile.js +55 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.controller.d.ts +78 -6
- package/dist/agents/templates.controller.js +154 -8
- package/dist/agents/templates.d.ts +132 -30
- package/dist/agents/templates.js +500 -46
- package/dist/agents/templates.schemas.d.ts +20 -0
- package/dist/agents/templates.schemas.js +45 -0
- package/dist/app.d.ts +93 -0
- package/dist/app.js +150 -0
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +88 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +39 -0
- package/dist/background/background.schemas.d.ts +10 -0
- package/dist/background/background.schemas.js +16 -0
- package/dist/background/finish.d.ts +44 -0
- package/dist/background/finish.js +95 -0
- package/dist/background/launch-lock.d.ts +15 -0
- package/dist/background/launch-lock.js +40 -0
- package/dist/background/launch.d.ts +42 -0
- package/dist/background/launch.js +77 -0
- package/dist/background/poll.job.d.ts +56 -0
- package/dist/background/poll.job.js +195 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +48 -0
- package/dist/background/session.js +80 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +68 -0
- package/dist/background/stop.js +244 -0
- package/dist/background/store.d.ts +167 -0
- package/dist/background/store.js +361 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +77 -0
- package/dist/background/tasks.service.js +216 -0
- package/dist/background/wake-rules.d.ts +66 -0
- package/dist/background/wake-rules.js +113 -0
- package/dist/background/wake.d.ts +30 -0
- package/dist/background/wake.js +63 -0
- package/dist/catalog/admin-catalog.controller.d.ts +102 -52
- package/dist/catalog/admin-catalog.controller.js +222 -67
- package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
- package/dist/catalog/admin-catalog.schemas.js +92 -0
- package/dist/catalog/catalog-content.d.ts +232 -0
- package/dist/catalog/catalog-content.js +367 -0
- package/dist/catalog/catalog-files.d.ts +41 -0
- package/dist/catalog/catalog-files.js +86 -0
- 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 +290 -0
- package/dist/catalog/catalog-items.js +676 -0
- package/dist/catalog/catalog-scope.service.d.ts +260 -0
- package/dist/catalog/catalog-scope.service.js +1124 -0
- package/dist/catalog/catalog.module.d.ts +12 -0
- package/dist/catalog/catalog.module.js +81 -0
- package/dist/catalog/catalog.service.d.ts +141 -206
- package/dist/catalog/catalog.service.js +237 -528
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/cli.d.ts +14 -3
- package/dist/catalog/cli.js +39 -32
- 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 +90 -0
- package/dist/catalog/component-scope.controller.js +234 -0
- package/dist/catalog/component-scope.schemas.d.ts +114 -0
- package/dist/catalog/component-scope.schemas.js +97 -0
- package/dist/catalog/component-scope.service.d.ts +327 -0
- package/dist/catalog/component-scope.service.js +990 -0
- package/dist/catalog/component-state.d.ts +188 -0
- package/dist/catalog/component-state.js +455 -0
- package/dist/catalog/git-source.d.ts +9 -1
- package/dist/catalog/git-source.js +29 -2
- package/dist/catalog/job-ids.d.ts +45 -0
- package/dist/catalog/job-ids.js +40 -0
- package/dist/catalog/jobs.d.ts +27 -0
- package/dist/catalog/jobs.js +70 -0
- package/dist/catalog/locks.d.ts +24 -0
- package/dist/catalog/locks.js +63 -0
- package/dist/catalog/marketplace-fetch.d.ts +1 -1
- package/dist/catalog/marketplace-icons.d.ts +64 -0
- package/dist/catalog/marketplace-icons.js +131 -0
- package/dist/catalog/marketplaces.controller.d.ts +53 -44
- package/dist/catalog/marketplaces.controller.js +146 -51
- package/dist/catalog/marketplaces.schemas.d.ts +48 -0
- package/dist/catalog/marketplaces.schemas.js +53 -0
- package/dist/catalog/marketplaces.service.d.ts +136 -26
- package/dist/catalog/marketplaces.service.js +663 -281
- package/dist/catalog/org-catalog.controller.d.ts +115 -63
- package/dist/catalog/org-catalog.controller.js +207 -100
- package/dist/catalog/org-catalog.schemas.d.ts +88 -0
- package/dist/catalog/org-catalog.schemas.js +93 -0
- package/dist/catalog/org-catalog.service.d.ts +89 -216
- package/dist/catalog/org-catalog.service.js +431 -472
- 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 +113 -0
- package/dist/catalog/org-extension.controller.js +271 -0
- package/dist/catalog/org-extension.schemas.d.ts +15 -0
- package/dist/catalog/org-extension.schemas.js +22 -0
- package/dist/catalog/org-plugin-uploads.controller.d.ts +77 -0
- package/dist/catalog/org-plugin-uploads.controller.js +200 -0
- package/dist/catalog/org-plugin-uploads.d.ts +71 -0
- package/dist/catalog/org-plugin-uploads.js +122 -0
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
- package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
- package/dist/catalog/owned-items.d.ts +188 -0
- package/dist/catalog/owned-items.js +801 -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 +223 -0
- package/dist/catalog/platform-components.js +763 -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 +270 -68
- package/dist/catalog/plugin-import.js +1004 -277
- package/dist/catalog/plugin-install.d.ts +251 -65
- package/dist/catalog/plugin-install.js +1128 -344
- package/dist/catalog/plugin-package.js +14 -1
- package/dist/catalog/plugin-upgrade.d.ts +301 -188
- package/dist/catalog/plugin-upgrade.js +1256 -1068
- package/dist/catalog/request-rules.d.ts +65 -0
- package/dist/catalog/request-rules.js +217 -0
- package/dist/catalog/requests.service.d.ts +205 -117
- package/dist/catalog/requests.service.js +612 -369
- 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.d.ts +6 -4
- package/dist/channels/actions.js +11 -4
- package/dist/channels/cards.d.ts +33 -11
- package/dist/channels/cards.js +96 -24
- package/dist/channels/channels.module.d.ts +40 -0
- package/dist/channels/channels.module.js +130 -0
- package/dist/channels/channels.schemas.d.ts +37 -0
- package/dist/channels/channels.schemas.js +38 -0
- package/dist/channels/connections.controller.d.ts +44 -37
- package/dist/channels/connections.controller.js +83 -38
- package/dist/channels/connections.service.d.ts +101 -30
- package/dist/channels/connections.service.js +380 -147
- package/dist/channels/inbound.d.ts +44 -38
- package/dist/channels/inbound.js +190 -44
- package/dist/channels/job-ids.d.ts +10 -0
- package/dist/channels/job-ids.js +10 -0
- package/dist/channels/jobs.d.ts +85 -0
- package/dist/channels/jobs.js +157 -0
- package/dist/channels/outbound.d.ts +71 -80
- package/dist/channels/outbound.js +219 -201
- package/dist/channels/phrases.d.ts +33 -2
- package/dist/channels/phrases.js +29 -1
- package/dist/channels/supervisor.d.ts +88 -46
- package/dist/channels/supervisor.js +230 -132
- package/dist/channels/threads.d.ts +34 -8
- package/dist/channels/threads.js +79 -13
- package/dist/channels/webhook.d.ts +20 -14
- package/dist/channels/webhook.js +51 -20
- package/dist/config/docs.js +5 -1
- package/dist/config/load.d.ts +3 -2
- package/dist/config/load.js +3 -2
- package/dist/config/nacos-source.js +11 -2
- package/dist/config/schema.d.ts +51 -3
- package/dist/config/schema.js +269 -27
- package/dist/conversations/access.d.ts +31 -0
- package/dist/conversations/access.js +110 -0
- package/dist/conversations/agent-tree.d.ts +46 -0
- package/dist/conversations/agent-tree.js +92 -0
- package/dist/conversations/artifacts.d.ts +11 -11
- package/dist/conversations/artifacts.js +36 -10
- package/dist/conversations/attachments.controller.d.ts +1 -1
- package/dist/conversations/attachments.controller.js +8 -6
- package/dist/conversations/attachments.module.d.ts +7 -0
- package/dist/conversations/attachments.module.js +25 -0
- package/dist/conversations/attachments.service.d.ts +60 -22
- package/dist/conversations/attachments.service.js +249 -51
- package/dist/conversations/conversations.controller.d.ts +86 -50
- package/dist/conversations/conversations.controller.js +184 -103
- package/dist/conversations/conversations.module.d.ts +8 -0
- package/dist/conversations/conversations.module.js +72 -0
- package/dist/conversations/conversations.schemas.d.ts +52 -0
- package/dist/conversations/conversations.schemas.js +79 -0
- package/dist/conversations/conversations.service.d.ts +166 -49
- package/dist/conversations/conversations.service.js +383 -179
- package/dist/conversations/environment-status.d.ts +24 -0
- package/dist/conversations/environment-status.js +71 -0
- package/dist/conversations/event-log.d.ts +64 -27
- package/dist/conversations/event-log.js +167 -31
- package/dist/conversations/events.d.ts +252 -9
- package/dist/conversations/events.js +243 -32
- package/dist/conversations/files.d.ts +10 -10
- package/dist/conversations/files.js +37 -11
- package/dist/conversations/idem-keys.d.ts +5 -0
- package/dist/conversations/idem-keys.js +5 -0
- package/dist/conversations/job-ids.d.ts +6 -0
- package/dist/conversations/job-ids.js +6 -0
- package/dist/conversations/message-context.d.ts +79 -0
- package/dist/conversations/message-context.js +145 -0
- package/dist/conversations/outputs-read.d.ts +11 -11
- package/dist/conversations/outputs-read.js +31 -7
- package/dist/conversations/queue.d.ts +53 -58
- package/dist/conversations/queue.js +37 -293
- package/dist/conversations/queue.service.d.ts +60 -0
- package/dist/conversations/queue.service.js +350 -0
- package/dist/conversations/titles.d.ts +83 -27
- package/dist/conversations/titles.js +195 -70
- package/dist/conversations/tree.d.ts +17 -0
- package/dist/conversations/tree.js +42 -0
- package/dist/ctx/bus.js +9 -3
- package/dist/ctx/create-ctx.d.ts +26 -1
- package/dist/ctx/create-ctx.js +45 -16
- package/dist/ctx/lock.d.ts +7 -3
- package/dist/ctx/lock.js +9 -20
- package/dist/ctx/queue.js +3 -2
- package/dist/ctx/secrets.d.ts +10 -2
- package/dist/ctx/secrets.js +7 -3
- package/dist/db/kernel-schema.d.ts +550 -25
- package/dist/db/pool.d.ts +10 -0
- package/dist/db/pool.js +4 -0
- package/dist/devices/device-auth.controller.d.ts +42 -0
- package/dist/devices/device-auth.controller.js +116 -0
- package/dist/devices/device-auth.d.ts +119 -0
- package/dist/devices/device-auth.js +403 -0
- package/dist/devices/device-auth.module.d.ts +7 -0
- package/dist/devices/device-auth.module.js +25 -0
- package/dist/devices/device-gateway.d.ts +128 -0
- package/dist/devices/device-gateway.js +530 -0
- package/dist/devices/device-provider.d.ts +89 -0
- package/dist/devices/device-provider.js +151 -0
- package/dist/devices/device-routes.d.ts +36 -0
- package/dist/devices/device-routes.js +90 -0
- package/dist/devices/devices.module.d.ts +16 -0
- package/dist/devices/devices.module.js +44 -0
- package/dist/devices/dto.d.ts +66 -0
- package/dist/devices/dto.js +44 -0
- package/dist/devices/keys.d.ts +25 -0
- package/dist/devices/keys.js +25 -0
- package/dist/devices/machines.d.ts +118 -0
- package/dist/devices/machines.js +366 -0
- package/dist/devices/relay.d.ts +100 -0
- package/dist/devices/relay.js +373 -0
- package/dist/devices/targets.d.ts +28 -0
- package/dist/devices/targets.js +73 -0
- package/dist/environments/access.d.ts +66 -0
- package/dist/environments/access.js +113 -0
- package/dist/environments/conversation-environments.d.ts +75 -0
- package/dist/environments/conversation-environments.js +231 -0
- package/dist/environments/dto.d.ts +25 -0
- package/dist/environments/dto.js +12 -0
- package/dist/environments/environments.controller.d.ts +36 -0
- package/dist/environments/environments.controller.js +124 -0
- package/dist/environments/environments.module.d.ts +8 -0
- package/dist/environments/environments.module.js +31 -0
- package/dist/environments/environments.schemas.d.ts +3 -0
- package/dist/environments/environments.schemas.js +14 -0
- package/dist/environments/environments.service.d.ts +251 -0
- package/dist/environments/environments.service.js +791 -0
- package/dist/environments/label.d.ts +11 -0
- package/dist/environments/label.js +25 -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 +136 -2
- package/dist/errors.js +136 -2
- package/dist/evals/budget.d.ts +42 -21
- package/dist/evals/budget.js +114 -62
- package/dist/evals/evals.module.d.ts +31 -0
- package/dist/evals/evals.module.js +114 -0
- package/dist/evals/evals.schemas.d.ts +110 -0
- package/dist/evals/evals.schemas.js +107 -0
- package/dist/evals/jobs.d.ts +20 -0
- package/dist/evals/jobs.js +45 -0
- package/dist/evals/reconstruct.d.ts +18 -9
- package/dist/evals/reconstruct.js +36 -10
- package/dist/evals/recorded-tools.d.ts +37 -1
- package/dist/evals/recorded-tools.js +120 -10
- package/dist/evals/run-replay.d.ts +75 -10
- package/dist/evals/run-replay.js +218 -94
- package/dist/evals/runs.controller.d.ts +3 -58
- package/dist/evals/runs.controller.js +18 -50
- package/dist/evals/runs.service.d.ts +31 -52
- package/dist/evals/runs.service.js +281 -255
- package/dist/evals/sets.controller.d.ts +3 -29
- package/dist/evals/sets.controller.js +18 -39
- package/dist/evals/sets.service.d.ts +29 -13
- package/dist/evals/sets.service.js +262 -202
- package/dist/evals/snapshot.d.ts +5 -4
- package/dist/evals/snapshot.js +17 -4
- package/dist/evals/step-replay.d.ts +6 -8
- package/dist/evals/step-replay.js +17 -10
- package/dist/evals/trajectory.controller.d.ts +1 -1
- package/dist/evals/trajectory.controller.js +11 -7
- package/dist/evals/trajectory.d.ts +2 -2
- package/dist/evals/trajectory.js +1 -1
- package/dist/evals/trajectory.service.d.ts +13 -7
- package/dist/evals/trajectory.service.js +56 -21
- package/dist/evals/worker.d.ts +48 -31
- package/dist/evals/worker.js +229 -123
- package/dist/extensions/admin-ops.d.ts +133 -41
- package/dist/extensions/admin-ops.js +378 -172
- package/dist/extensions/admin-view.d.ts +82 -32
- package/dist/extensions/admin-view.js +284 -71
- package/dist/extensions/approvals.d.ts +24 -10
- package/dist/extensions/approvals.js +73 -46
- package/dist/extensions/blobs.d.ts +27 -10
- package/dist/extensions/blobs.js +112 -45
- package/dist/extensions/bootstrap.d.ts +136 -46
- package/dist/extensions/bootstrap.js +417 -167
- package/dist/extensions/cli.d.ts +32 -10
- package/dist/extensions/cli.js +52 -98
- package/dist/extensions/config-hash.d.ts +10 -0
- package/dist/extensions/config-hash.js +38 -0
- package/dist/extensions/config-issues.d.ts +19 -0
- package/dist/extensions/config-issues.js +48 -0
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +55 -0
- package/dist/extensions/deployment-config-store.js +133 -0
- package/dist/extensions/deployment-config.d.ts +146 -70
- package/dist/extensions/deployment-config.js +439 -246
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/effective-config.d.ts +127 -0
- package/dist/extensions/effective-config.js +368 -0
- package/dist/extensions/enabled.d.ts +5 -5
- package/dist/extensions/extensions.module.d.ts +8 -0
- package/dist/extensions/extensions.module.js +96 -0
- package/dist/extensions/hooks.d.ts +40 -6
- package/dist/extensions/hooks.js +83 -17
- package/dist/extensions/host.d.ts +161 -80
- package/dist/extensions/host.js +505 -213
- package/dist/extensions/installs.d.ts +73 -19
- package/dist/extensions/installs.js +174 -37
- package/dist/extensions/job-ids.d.ts +6 -0
- package/dist/extensions/job-ids.js +6 -0
- package/dist/extensions/lifecycle-topics.d.ts +18 -0
- package/dist/extensions/lifecycle-topics.js +18 -0
- package/dist/extensions/lifecycle.d.ts +35 -47
- package/dist/extensions/lifecycle.js +103 -39
- package/dist/extensions/locks.d.ts +45 -0
- package/dist/extensions/locks.js +112 -0
- package/dist/extensions/migrate-lock.d.ts +3 -4
- package/dist/extensions/org-config.d.ts +141 -49
- package/dist/extensions/org-config.js +471 -243
- 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/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +59 -6
- package/dist/extensions/permission-view.js +7 -5
- package/dist/extensions/plugin-guides.d.ts +129 -0
- package/dist/extensions/plugin-guides.js +283 -0
- package/dist/extensions/plugin-icons.d.ts +54 -0
- package/dist/extensions/plugin-icons.js +125 -0
- package/dist/extensions/plugin-items.d.ts +21 -0
- package/dist/extensions/plugin-items.js +42 -0
- package/dist/extensions/point-defaults.controller.d.ts +28 -0
- package/dist/extensions/point-defaults.controller.js +69 -0
- package/dist/extensions/point-defaults.d.ts +73 -0
- package/dist/extensions/point-defaults.js +236 -0
- package/dist/extensions/point-defaults.schemas.d.ts +9 -0
- package/dist/extensions/point-defaults.schemas.js +14 -0
- package/dist/extensions/registry.d.ts +50 -2
- package/dist/extensions/registry.js +91 -4
- package/dist/extensions/resolve.d.ts +51 -1
- package/dist/extensions/resolve.js +85 -3
- package/dist/extensions/single-provider.d.ts +92 -0
- package/dist/extensions/single-provider.js +180 -0
- package/dist/extensions/sources.d.ts +19 -10
- package/dist/extensions/sources.js +34 -13
- package/dist/extensions/state.module.d.ts +9 -0
- package/dist/extensions/state.module.js +38 -0
- package/dist/extensions/unavailable.d.ts +50 -0
- package/dist/extensions/unavailable.js +115 -0
- package/dist/files/files.module.d.ts +3 -0
- package/dist/files/files.module.js +22 -0
- package/dist/files/previewers.controller.d.ts +7 -2
- package/dist/files/previewers.controller.js +19 -12
- package/dist/files/previewers.d.ts +21 -19
- package/dist/files/previewers.js +114 -38
- package/dist/files/previewers.schemas.d.ts +10 -0
- package/dist/files/previewers.schemas.js +9 -0
- package/dist/http/adapter.d.ts +3 -0
- package/dist/http/adapter.js +25 -0
- package/dist/http/api.module.d.ts +3 -110
- package/dist/http/api.module.js +86 -358
- package/dist/http/app.d.ts +22 -17
- package/dist/http/app.js +83 -52
- package/dist/http/error-filter.module.d.ts +5 -0
- package/dist/http/error-filter.module.js +18 -0
- package/dist/http/error.filter.js +2 -2
- package/dist/http/{gateway.module.d.ts → gateway-routes.d.ts} +7 -3
- package/dist/http/gateway-routes.js +16 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/http/plugin-dispatch.d.ts +4 -1
- package/dist/http/plugin-dispatch.js +14 -2
- package/dist/identity/accounts.d.ts +130 -38
- package/dist/identity/accounts.js +373 -186
- package/dist/identity/api-tokens.d.ts +11 -7
- package/dist/identity/api-tokens.js +71 -44
- package/dist/identity/audit.d.ts +9 -5
- package/dist/identity/audit.js +5 -1
- package/dist/identity/auth.controller.d.ts +11 -10
- package/dist/identity/auth.controller.js +40 -30
- package/dist/identity/auth.guard.d.ts +16 -8
- package/dist/identity/auth.guard.js +41 -13
- package/dist/identity/binding.d.ts +9 -11
- package/dist/identity/binding.js +41 -13
- package/dist/identity/cookies.d.ts +26 -5
- package/dist/identity/cookies.js +58 -6
- package/dist/identity/external-identity-lock.d.ts +17 -0
- package/dist/identity/external-identity-lock.js +39 -0
- package/dist/identity/external.d.ts +19 -15
- package/dist/identity/external.js +163 -125
- package/dist/identity/identity.module.d.ts +6 -0
- package/dist/identity/identity.module.js +59 -0
- package/dist/identity/initial-passwords.controller.d.ts +22 -0
- package/dist/identity/initial-passwords.controller.js +49 -0
- package/dist/identity/initial-passwords.d.ts +61 -0
- package/dist/identity/initial-passwords.job.d.ts +16 -0
- package/dist/identity/initial-passwords.job.js +46 -0
- package/dist/identity/initial-passwords.js +159 -0
- package/dist/identity/me.controller.d.ts +32 -15
- package/dist/identity/me.controller.js +78 -33
- package/dist/identity/me.schemas.d.ts +14 -0
- package/dist/identity/me.schemas.js +17 -0
- package/dist/identity/principal.d.ts +11 -3
- package/dist/identity/principal.js +11 -3
- package/dist/identity/sessions.d.ts +24 -10
- package/dist/identity/sessions.js +119 -42
- package/dist/identity/settings.d.ts +42 -23
- package/dist/identity/settings.js +137 -72
- package/dist/identity/sso.controller.d.ts +7 -7
- package/dist/identity/sso.controller.js +13 -9
- package/dist/identity/sso.d.ts +9 -12
- package/dist/identity/sso.js +54 -24
- package/dist/identity/super-admin.d.ts +20 -0
- package/dist/identity/super-admin.js +81 -0
- package/dist/inbox/inbox.module.d.ts +6 -0
- package/dist/inbox/inbox.module.js +26 -0
- package/dist/inbox/inbox.schemas.d.ts +8 -0
- package/dist/inbox/inbox.schemas.js +11 -0
- package/dist/inbox/inbox.service.d.ts +68 -11
- package/dist/inbox/inbox.service.js +104 -13
- 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 +25 -14
- package/dist/index.js +20 -9
- package/dist/infra/cache/cache.module.d.ts +3 -0
- package/dist/infra/cache/cache.module.js +16 -0
- package/dist/infra/cache/cache.service.d.ts +21 -0
- package/dist/infra/cache/cache.service.js +80 -0
- package/dist/infra/cache/cacheable.decorator.d.ts +32 -0
- package/dist/infra/cache/cacheable.decorator.js +83 -0
- package/dist/infra/cli/kernel-cli.module.d.ts +66 -0
- package/dist/infra/cli/kernel-cli.module.js +173 -0
- package/dist/infra/close-within.d.ts +15 -0
- package/dist/infra/close-within.js +36 -0
- package/dist/infra/config/config.module.d.ts +13 -0
- package/dist/infra/config/config.module.js +39 -0
- package/dist/infra/config/kernel-config.service.d.ts +25 -0
- package/dist/infra/config/kernel-config.service.js +157 -0
- package/dist/infra/database/after-commit.d.ts +6 -0
- package/dist/infra/database/after-commit.js +9 -0
- package/dist/infra/database/database.module.d.ts +25 -0
- package/dist/infra/database/database.module.js +91 -0
- package/dist/infra/database/kernel-db.d.ts +22 -0
- package/dist/infra/database/kernel-db.js +65 -0
- package/dist/infra/database/transaction-host.d.ts +50 -0
- package/dist/infra/database/transaction-host.js +125 -0
- package/dist/infra/database/transactional.decorator.d.ts +15 -0
- package/dist/infra/database/transactional.decorator.js +27 -0
- package/dist/infra/database/xact-lock.d.ts +17 -0
- package/dist/infra/database/xact-lock.js +43 -0
- package/dist/infra/events/kernel-events.d.ts +121 -0
- package/dist/infra/events/kernel-events.js +65 -0
- package/dist/infra/health/health.controller.d.ts +26 -0
- package/dist/infra/health/health.controller.js +104 -0
- package/dist/infra/health/health.module.d.ts +9 -0
- package/dist/infra/health/health.module.js +24 -0
- package/dist/infra/health/health.options.d.ts +10 -0
- package/dist/infra/health/health.options.js +15 -0
- package/dist/infra/health/shutdown-state.d.ts +6 -0
- package/dist/infra/health/shutdown-state.js +2 -0
- package/dist/infra/lifecycle/graceful-shutdown.module.d.ts +6 -0
- package/dist/infra/lifecycle/graceful-shutdown.module.js +23 -0
- package/dist/infra/lifecycle/graceful-shutdown.service.d.ts +70 -0
- package/dist/infra/lifecycle/graceful-shutdown.service.js +135 -0
- package/dist/infra/lifecycle/process-guards.d.ts +52 -0
- package/dist/infra/lifecycle/process-guards.js +90 -0
- package/dist/infra/lifecycle/shutdown-signals.d.ts +30 -0
- package/dist/infra/lifecycle/shutdown-signals.js +48 -0
- package/dist/infra/lock/key-template.d.ts +13 -0
- package/dist/infra/lock/key-template.js +46 -0
- package/dist/infra/lock/lock.module.d.ts +3 -0
- package/dist/infra/lock/lock.module.js +16 -0
- package/dist/infra/lock/lock.service.d.ts +120 -0
- package/dist/infra/lock/lock.service.js +343 -0
- package/dist/infra/lock/shared-lease.d.ts +44 -0
- package/dist/infra/lock/shared-lease.js +121 -0
- package/dist/infra/lock/with-lock.decorator.d.ts +28 -0
- package/dist/infra/lock/with-lock.decorator.js +49 -0
- package/dist/infra/logging/logging.module.d.ts +18 -0
- package/dist/infra/logging/logging.module.js +52 -0
- package/dist/infra/queue/add-job-once.d.ts +14 -0
- package/dist/infra/queue/add-job-once.js +16 -0
- package/dist/infra/queue/configured-processor.d.ts +18 -0
- package/dist/infra/queue/configured-processor.js +23 -0
- package/dist/infra/queue/job-failure.d.ts +18 -0
- package/dist/infra/queue/job-failure.js +26 -0
- package/dist/infra/queue/queue-shutdown.d.ts +27 -0
- package/dist/infra/queue/queue-shutdown.js +81 -0
- package/dist/infra/queue/queue.module.d.ts +16 -0
- package/dist/infra/queue/queue.module.js +61 -0
- package/dist/infra/queue/redis-connection.d.ts +13 -0
- package/dist/infra/queue/redis-connection.js +25 -0
- package/dist/infra/queue/retired-schedulers.d.ts +7 -0
- package/dist/infra/queue/retired-schedulers.js +9 -0
- package/dist/infra/queue/run-job.d.ts +16 -0
- package/dist/infra/queue/run-job.js +19 -0
- package/dist/infra/redis/redis.module.d.ts +24 -0
- package/dist/infra/redis/redis.module.js +91 -0
- package/dist/infra/schedule/cron-tick.d.ts +12 -0
- package/dist/infra/schedule/cron-tick.js +25 -0
- package/dist/infra/schedule/locked-cron.decorator.d.ts +27 -0
- package/dist/infra/schedule/locked-cron.decorator.js +53 -0
- package/dist/infra/schedule/locked-interval.d.ts +69 -0
- package/dist/infra/schedule/locked-interval.js +190 -0
- package/dist/infra/schedule/locked-tick.d.ts +90 -0
- package/dist/infra/schedule/locked-tick.js +137 -0
- package/dist/infra/schedule/schedule.module.d.ts +8 -0
- package/dist/infra/schedule/schedule.module.js +27 -0
- package/dist/infra/schedule/scheduled-runs.d.ts +69 -0
- package/dist/infra/schedule/scheduled-runs.js +163 -0
- package/dist/infra/swagger/swagger.d.ts +16 -0
- package/dist/infra/swagger/swagger.js +31 -0
- package/dist/infra/throttler/credential-throttler.d.ts +35 -0
- package/dist/infra/throttler/credential-throttler.js +77 -0
- package/dist/infra/throttler/named-throttlers.d.ts +36 -0
- package/dist/infra/throttler/named-throttlers.js +157 -0
- package/dist/infra/throttler/redis-throttler-storage.d.ts +38 -0
- package/dist/infra/throttler/redis-throttler-storage.js +130 -0
- package/dist/infra/throttler/throttler.guard.d.ts +23 -0
- package/dist/infra/throttler/throttler.guard.js +68 -0
- package/dist/infra/throttler/throttler.module.d.ts +15 -0
- package/dist/infra/throttler/throttler.module.js +53 -0
- package/dist/infra/tokens.d.ts +20 -0
- package/dist/infra/tokens.js +20 -0
- package/dist/infra/validation/create-zod-dto.d.ts +23 -0
- package/dist/infra/validation/create-zod-dto.js +35 -0
- package/dist/infra/validation/parse-with-zod.d.ts +7 -0
- package/dist/infra/validation/parse-with-zod.js +12 -0
- package/dist/infra/validation/validation.module.d.ts +3 -0
- package/dist/infra/validation/validation.module.js +16 -0
- package/dist/infra/validation/zod-params.d.ts +7 -0
- package/dist/infra/validation/zod-params.js +42 -0
- package/dist/infra/validation/zod-validation.pipe.d.ts +11 -0
- package/dist/infra/validation/zod-validation.pipe.js +31 -0
- package/dist/kernel.d.ts +9 -241
- package/dist/kernel.js +8 -1305
- package/dist/kernel.module.d.ts +17 -0
- package/dist/kernel.module.js +145 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +140 -0
- package/dist/lifecycle/kernel-lifecycle.js +465 -0
- package/dist/lifecycle/tokens.d.ts +3 -0
- package/dist/lifecycle/tokens.js +3 -0
- package/dist/log-config.d.ts +9 -0
- package/dist/log-config.js +27 -0
- package/dist/log-context.d.ts +34 -0
- package/dist/log-context.js +44 -0
- package/dist/log-loki.d.ts +34 -0
- package/dist/log-loki.js +145 -0
- package/dist/log.d.ts +53 -10
- package/dist/log.js +168 -18
- package/dist/models/embeddings.d.ts +82 -0
- package/dist/models/embeddings.js +326 -0
- package/dist/models/enablement.controller.d.ts +40 -0
- package/dist/models/enablement.controller.js +74 -0
- package/dist/models/enablement.d.ts +101 -0
- package/dist/models/enablement.js +264 -0
- package/dist/models/models.module.d.ts +7 -0
- package/dist/models/models.module.js +36 -0
- package/dist/models/org-models.schemas.d.ts +8 -0
- package/dist/models/org-models.schemas.js +22 -0
- package/dist/models/prices.d.ts +13 -5
- package/dist/models/prices.js +69 -39
- package/dist/models/purposes.controller.d.ts +6 -4
- package/dist/models/purposes.controller.js +16 -11
- package/dist/models/purposes.d.ts +103 -23
- package/dist/models/purposes.js +208 -77
- package/dist/net/public-address.js +3 -2
- package/dist/orgs/directory-sync.controller.d.ts +1 -1
- package/dist/orgs/directory-sync.controller.js +2 -2
- package/dist/orgs/directory-sync.d.ts +74 -35
- package/dist/orgs/directory-sync.js +243 -132
- package/dist/orgs/invitations.controller.d.ts +8 -8
- package/dist/orgs/invitations.controller.js +27 -26
- package/dist/orgs/invitations.service.d.ts +12 -9
- package/dist/orgs/invitations.service.js +130 -92
- package/dist/orgs/job-ids.d.ts +8 -0
- package/dist/orgs/job-ids.js +8 -0
- package/dist/orgs/members.service.d.ts +19 -12
- package/dist/orgs/members.service.js +161 -117
- package/dist/orgs/offboarding.d.ts +61 -60
- package/dist/orgs/offboarding.js +206 -95
- package/dist/orgs/org-lock.d.ts +33 -19
- package/dist/orgs/org-lock.js +94 -35
- package/dist/orgs/org.guard.d.ts +11 -1
- package/dist/orgs/org.guard.js +45 -34
- package/dist/orgs/orgs.controller.d.ts +13 -16
- package/dist/orgs/orgs.controller.js +29 -20
- package/dist/orgs/orgs.module.d.ts +6 -0
- package/dist/orgs/orgs.module.js +71 -0
- package/dist/orgs/orgs.schemas.d.ts +8 -0
- package/dist/orgs/orgs.schemas.js +16 -0
- package/dist/orgs/orgs.service.d.ts +47 -21
- package/dist/orgs/orgs.service.js +166 -91
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +5 -1
- package/dist/orgs/settings.controller.d.ts +2 -2
- package/dist/orgs/settings.controller.js +8 -6
- package/dist/orgs/settings.service.d.ts +45 -14
- package/dist/orgs/settings.service.js +110 -51
- package/dist/overrides.d.ts +63 -0
- package/dist/overrides.js +34 -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 +28 -0
- package/dist/platform/errors.js +65 -0
- package/dist/platform/exclusions.d.ts +11 -0
- package/dist/platform/exclusions.js +667 -0
- package/dist/platform/method.d.ts +6 -0
- package/dist/platform/method.js +15 -0
- package/dist/platform/operation.d.ts +169 -0
- package/dist/platform/operation.js +90 -0
- package/dist/platform/ops/accounts.ops.d.ts +32 -0
- package/dist/platform/ops/accounts.ops.js +291 -0
- package/dist/platform/ops/admin.ops.d.ts +36 -0
- package/dist/platform/ops/admin.ops.js +389 -0
- package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
- package/dist/platform/ops/agent-skills.ops.js +226 -0
- package/dist/platform/ops/agent-templates.ops.d.ts +17 -0
- package/dist/platform/ops/agent-templates.ops.js +272 -0
- package/dist/platform/ops/agents.ops.d.ts +37 -0
- package/dist/platform/ops/agents.ops.js +717 -0
- package/dist/platform/ops/approvals.ops.d.ts +30 -0
- package/dist/platform/ops/approvals.ops.js +116 -0
- package/dist/platform/ops/background.ops.d.ts +14 -0
- package/dist/platform/ops/background.ops.js +134 -0
- package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
- package/dist/platform/ops/catalog-admin.ops.js +599 -0
- package/dist/platform/ops/channels.ops.d.ts +16 -0
- package/dist/platform/ops/channels.ops.js +195 -0
- package/dist/platform/ops/components.ops.d.ts +46 -0
- package/dist/platform/ops/components.ops.js +853 -0
- package/dist/platform/ops/connectors.ops.d.ts +17 -0
- package/dist/platform/ops/connectors.ops.js +188 -0
- package/dist/platform/ops/conversations.ops.d.ts +30 -0
- package/dist/platform/ops/conversations.ops.js +470 -0
- package/dist/platform/ops/environments.ops.d.ts +26 -0
- package/dist/platform/ops/environments.ops.js +311 -0
- package/dist/platform/ops/errors.d.ts +16 -0
- package/dist/platform/ops/errors.js +30 -0
- package/dist/platform/ops/evals.ops.d.ts +28 -0
- package/dist/platform/ops/evals.ops.js +783 -0
- package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
- package/dist/platform/ops/extensions-admin.ops.js +372 -0
- package/dist/platform/ops/extensions.ops.d.ts +25 -0
- package/dist/platform/ops/extensions.ops.js +347 -0
- package/dist/platform/ops/inbox.ops.d.ts +25 -0
- package/dist/platform/ops/inbox.ops.js +378 -0
- package/dist/platform/ops/marketplaces.ops.d.ts +22 -0
- package/dist/platform/ops/marketplaces.ops.js +466 -0
- package/dist/platform/ops/models.ops.d.ts +25 -0
- package/dist/platform/ops/models.ops.js +232 -0
- package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
- package/dist/platform/ops/org-plugins.ops.js +329 -0
- package/dist/platform/ops/org-settings.ops.d.ts +16 -0
- package/dist/platform/ops/org-settings.ops.js +102 -0
- package/dist/platform/ops/orgs.ops.d.ts +28 -0
- package/dist/platform/ops/orgs.ops.js +295 -0
- package/dist/platform/ops/other-orgs.d.ts +20 -0
- package/dist/platform/ops/other-orgs.js +72 -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 +28 -0
- package/dist/platform/ops/platform.ops.js +204 -0
- package/dist/platform/ops/plugins.ops.d.ts +35 -0
- package/dist/platform/ops/plugins.ops.js +476 -0
- package/dist/platform/ops/previewers.ops.d.ts +14 -0
- package/dist/platform/ops/previewers.ops.js +109 -0
- package/dist/platform/ops/requests.ops.d.ts +14 -0
- package/dist/platform/ops/requests.ops.js +191 -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 +17 -0
- package/dist/platform/ops/skills.ops.js +216 -0
- package/dist/platform/ops/summary.d.ts +10 -0
- package/dist/platform/ops/summary.js +18 -0
- package/dist/platform/ops/unavailable.d.ts +23 -0
- package/dist/platform/ops/unavailable.js +118 -0
- package/dist/platform/parity.d.ts +33 -0
- package/dist/platform/parity.js +272 -0
- package/dist/platform/platform-ops.module.d.ts +39 -0
- package/dist/platform/platform-ops.module.js +122 -0
- package/dist/platform/platform.module.d.ts +8 -0
- package/dist/platform/platform.module.js +25 -0
- package/dist/platform/registry.d.ts +30 -0
- package/dist/platform/registry.js +111 -0
- package/dist/platform/route-schemas.d.ts +18 -0
- package/dist/platform/route-schemas.js +63 -0
- package/dist/roles/gateway-role.d.ts +54 -0
- package/dist/roles/gateway-role.js +118 -0
- package/dist/roles/gateway.module.d.ts +9 -0
- package/dist/roles/gateway.module.js +31 -0
- package/dist/roles/worker-role.d.ts +65 -0
- package/dist/roles/worker-role.js +151 -0
- package/dist/roles/worker.module.d.ts +14 -0
- package/dist/roles/worker.module.js +106 -0
- package/dist/runtime/abort.js +19 -2
- package/dist/runtime/checkpointer.d.ts +8 -3
- package/dist/runtime/checkpointer.js +87 -55
- package/dist/runtime/context/build.d.ts +21 -13
- package/dist/runtime/context/build.js +106 -29
- package/dist/runtime/context/claude-tools.d.ts +4 -1
- package/dist/runtime/context/claude-tools.js +13 -12
- package/dist/runtime/context/compaction.js +24 -1
- package/dist/runtime/context/environment-paths.d.ts +40 -0
- package/dist/runtime/context/environment-paths.js +48 -0
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/reminders.d.ts +2 -0
- package/dist/runtime/context/reminders.js +2 -0
- package/dist/runtime/context/run-context.d.ts +65 -0
- package/dist/runtime/context/run-context.js +215 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +46 -32
- package/dist/runtime/context/tool-changes.d.ts +27 -0
- package/dist/runtime/context/tool-changes.js +60 -0
- package/dist/runtime/conversation-lock.d.ts +20 -11
- package/dist/runtime/conversation-lock.js +62 -72
- package/dist/runtime/hook-calls.d.ts +11 -4
- package/dist/runtime/hook-calls.js +41 -13
- package/dist/runtime/job-ids.d.ts +10 -0
- package/dist/runtime/job-ids.js +10 -0
- package/dist/runtime/langgraph-loop.d.ts +3 -1
- package/dist/runtime/langgraph-loop.js +37 -18
- package/dist/runtime/loop.d.ts +42 -6
- package/dist/runtime/loop.js +14 -0
- package/dist/runtime/maintenance-queue.d.ts +10 -0
- package/dist/runtime/maintenance-queue.js +10 -0
- package/dist/runtime/maintenance.d.ts +50 -74
- package/dist/runtime/maintenance.js +166 -136
- package/dist/runtime/model-call.d.ts +61 -15
- package/dist/runtime/model-call.js +128 -84
- package/dist/runtime/providers.d.ts +158 -27
- package/dist/runtime/providers.js +373 -63
- package/dist/runtime/quota.d.ts +17 -3
- package/dist/runtime/quota.js +27 -2
- package/dist/runtime/retired-schedulers.d.ts +7 -0
- package/dist/runtime/retired-schedulers.js +31 -0
- package/dist/runtime/run-context.service.d.ts +65 -0
- package/dist/runtime/run-context.service.js +236 -0
- package/dist/runtime/run-control.d.ts +43 -0
- package/dist/runtime/run-control.js +89 -0
- package/dist/runtime/run-drafts.d.ts +85 -0
- package/dist/runtime/run-drafts.js +230 -0
- package/dist/runtime/run-finish.d.ts +27 -18
- package/dist/runtime/run-finish.js +98 -51
- package/dist/runtime/run-jobs.d.ts +46 -0
- package/dist/runtime/run-jobs.js +91 -0
- package/dist/runtime/run-processors.d.ts +60 -0
- package/dist/runtime/run-processors.js +185 -0
- package/dist/runtime/run-queue.d.ts +90 -58
- package/dist/runtime/run-queue.js +566 -297
- package/dist/runtime/run-steps.d.ts +39 -0
- package/dist/runtime/run-steps.js +96 -0
- package/dist/runtime/run-worker.d.ts +134 -77
- package/dist/runtime/run-worker.js +412 -236
- package/dist/runtime/runtime.module.d.ts +10 -0
- package/dist/runtime/runtime.module.js +122 -0
- package/dist/runtime/step-log.d.ts +51 -0
- package/dist/runtime/step-log.js +111 -0
- package/dist/runtime/stream.controller.d.ts +28 -9
- package/dist/runtime/stream.controller.js +72 -13
- package/dist/runtime/stream.d.ts +27 -6
- package/dist/runtime/stream.js +102 -7
- package/dist/runtime/subagents/child.d.ts +58 -51
- package/dist/runtime/subagents/child.js +105 -86
- package/dist/runtime/subagents/definition.d.ts +32 -28
- package/dist/runtime/subagents/definition.js +89 -143
- package/dist/runtime/subagents/deliveries.d.ts +71 -0
- package/dist/runtime/subagents/deliveries.js +228 -0
- package/dist/runtime/subagents/dispatch.d.ts +197 -27
- package/dist/runtime/subagents/dispatch.js +336 -270
- package/dist/runtime/subagents/limits.d.ts +32 -8
- package/dist/runtime/subagents/limits.js +44 -8
- package/dist/runtime/subagents/messages.d.ts +95 -0
- package/dist/runtime/subagents/messages.js +328 -0
- package/dist/runtime/subagents/org-agents.d.ts +4 -4
- package/dist/runtime/subagents/org-agents.js +3 -2
- package/dist/runtime/subagents/preamble.d.ts +4 -4
- package/dist/runtime/subagents/preamble.js +9 -7
- package/dist/runtime/subagents/progress.d.ts +10 -8
- 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 +27 -10
- package/dist/runtime/subagents/roster.js +49 -13
- package/dist/runtime/subagents/skill-fork.d.ts +10 -10
- package/dist/runtime/subagents/skill-fork.js +23 -8
- 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 +43 -0
- package/dist/runtime/subagents/subagents.service.js +106 -0
- package/dist/runtime/usage-report-jobs.d.ts +88 -0
- package/dist/runtime/usage-report-jobs.js +158 -0
- package/dist/runtime/usage-report.d.ts +121 -83
- package/dist/runtime/usage-report.js +355 -180
- package/dist/runtime/waits.d.ts +258 -81
- package/dist/runtime/waits.js +800 -263
- package/dist/sandbox/job-ids.d.ts +10 -0
- package/dist/sandbox/job-ids.js +10 -0
- package/dist/sandbox/jobs.d.ts +68 -0
- package/dist/sandbox/jobs.js +150 -0
- package/dist/sandbox/leases.d.ts +73 -82
- package/dist/sandbox/leases.js +162 -346
- package/dist/sandbox/providers.d.ts +46 -0
- package/dist/sandbox/providers.js +83 -0
- package/dist/sandbox/sandbox.module.d.ts +9 -0
- package/dist/sandbox/sandbox.module.js +36 -0
- package/dist/sandbox/sandbox.service.d.ts +359 -151
- package/dist/sandbox/sandbox.service.js +950 -435
- package/dist/sandbox/unreachable.d.ts +30 -0
- package/dist/sandbox/unreachable.js +108 -0
- package/dist/skills/catalog.d.ts +40 -26
- package/dist/skills/catalog.js +120 -99
- package/dist/skills/changes.controller.d.ts +11 -4
- package/dist/skills/changes.controller.js +34 -9
- package/dist/skills/changes.service.d.ts +31 -21
- package/dist/skills/changes.service.js +426 -368
- package/dist/skills/invocable.controller.d.ts +2 -2
- package/dist/skills/invocable.controller.js +10 -7
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +19 -18
- package/dist/skills/invoke.js +68 -24
- package/dist/skills/package.d.ts +20 -1
- package/dist/skills/package.js +28 -1
- package/dist/skills/skills.controller.d.ts +33 -7
- package/dist/skills/skills.controller.js +79 -12
- package/dist/skills/skills.module.d.ts +6 -0
- package/dist/skills/skills.module.js +39 -0
- package/dist/skills/skills.schemas.d.ts +48 -0
- package/dist/skills/skills.schemas.js +61 -0
- package/dist/skills/skills.service.d.ts +151 -44
- package/dist/skills/skills.service.js +636 -204
- package/dist/skills/usable.d.ts +81 -0
- package/dist/skills/usable.js +379 -0
- package/dist/storage/job-ids.d.ts +6 -0
- package/dist/storage/job-ids.js +6 -0
- package/dist/storage/purge.d.ts +22 -7
- package/dist/storage/purge.js +55 -3
- package/dist/storage/storage.module.d.ts +6 -0
- package/dist/storage/storage.module.js +23 -0
- package/dist/storage/storage.service.d.ts +18 -4
- package/dist/storage/storage.service.js +44 -3
- package/dist/time-zone.d.ts +5 -0
- package/dist/time-zone.js +19 -0
- package/dist/tools/approvals.controller.d.ts +1 -1
- package/dist/tools/approvals.controller.js +14 -11
- package/dist/tools/approvals.schemas.d.ts +21 -0
- package/dist/tools/approvals.schemas.js +15 -0
- package/dist/tools/approvals.service.d.ts +53 -27
- package/dist/tools/approvals.service.js +365 -260
- package/dist/tools/breaker.d.ts +2 -2
- package/dist/tools/breaker.js +21 -3
- package/dist/tools/builtin-names.d.ts +109 -0
- package/dist/tools/builtin-names.js +173 -0
- package/dist/tools/builtins/agent.d.ts +27 -25
- package/dist/tools/builtins/agent.js +66 -63
- package/dist/tools/builtins/ask-user.d.ts +3 -3
- package/dist/tools/builtins/ask-user.js +3 -3
- package/dist/tools/builtins/builtin-tools.d.ts +41 -0
- package/dist/tools/builtins/builtin-tools.js +151 -0
- package/dist/tools/builtins/current-time.d.ts +26 -0
- package/dist/tools/builtins/current-time.js +99 -0
- package/dist/tools/builtins/handback.d.ts +28 -0
- package/dist/tools/builtins/handback.js +53 -0
- package/dist/tools/builtins/platform.d.ts +51 -0
- package/dist/tools/builtins/platform.js +451 -0
- package/dist/tools/builtins/read-tool-output.d.ts +3 -3
- package/dist/tools/builtins/read-tool-output.js +3 -3
- package/dist/tools/builtins/sandbox/bash.d.ts +5 -5
- package/dist/tools/builtins/sandbox/bash.js +293 -41
- package/dist/tools/builtins/sandbox/common.d.ts +142 -40
- package/dist/tools/builtins/sandbox/common.js +227 -65
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +21 -18
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +65 -51
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +19 -14
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +155 -36
- package/dist/tools/builtins/sandbox/index.d.ts +9 -5
- package/dist/tools/builtins/sandbox/index.js +13 -5
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +30 -20
- package/dist/tools/builtins/sandbox/task-output.d.ts +79 -0
- package/dist/tools/builtins/sandbox/task-output.js +334 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +113 -0
- package/dist/tools/builtins/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +52 -45
- 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 +32 -21
- package/dist/tools/builtins/skill-load.js +125 -74
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +12 -12
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +271 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +175 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +210 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/canonical-json.d.ts +6 -0
- package/dist/tools/canonical-json.js +16 -0
- package/dist/tools/connector-content.controller.d.ts +1 -1
- package/dist/tools/connector-content.controller.js +11 -6
- package/dist/tools/connector-content.d.ts +12 -15
- package/dist/tools/connector-content.js +53 -18
- package/dist/tools/connectors.controller.d.ts +16 -3
- package/dist/tools/connectors.controller.js +34 -14
- package/dist/tools/connectors.schemas.d.ts +12 -0
- package/dist/tools/connectors.schemas.js +19 -0
- package/dist/tools/connectors.service.d.ts +80 -18
- package/dist/tools/connectors.service.js +529 -358
- package/dist/tools/credentials.d.ts +20 -20
- package/dist/tools/credentials.js +55 -34
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.d.ts +29 -41
- package/dist/tools/drift.js +116 -84
- package/dist/tools/elicitation.js +1 -1
- 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 +73 -13
- package/dist/tools/info.js +151 -39
- package/dist/tools/job-ids.d.ts +13 -0
- package/dist/tools/job-ids.js +15 -0
- package/dist/tools/jobs.d.ts +24 -0
- package/dist/tools/jobs.js +69 -0
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +16 -0
- package/dist/tools/oauth/flow-paths.js +38 -0
- package/dist/tools/oauth/flow.d.ts +30 -30
- package/dist/tools/oauth/flow.js +109 -81
- package/dist/tools/oauth/oauth.controller.d.ts +3 -3
- package/dist/tools/oauth/oauth.controller.js +12 -9
- package/dist/tools/oauth/tokens.d.ts +45 -10
- package/dist/tools/oauth/tokens.js +70 -24
- package/dist/tools/org-tool-switches.d.ts +88 -0
- package/dist/tools/org-tool-switches.js +201 -0
- package/dist/tools/outputs.d.ts +13 -4
- package/dist/tools/outputs.js +48 -4
- package/dist/tools/pipeline.d.ts +108 -80
- package/dist/tools/pipeline.js +396 -409
- package/dist/tools/policy.d.ts +4 -17
- package/dist/tools/policy.js +49 -35
- package/dist/tools/questions.controller.d.ts +2 -2
- package/dist/tools/questions.controller.js +9 -6
- package/dist/tools/questions.service.d.ts +26 -25
- package/dist/tools/questions.service.js +201 -142
- package/dist/tools/registry.d.ts +215 -84
- package/dist/tools/registry.js +382 -264
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/specs.d.ts +5 -4
- package/dist/tools/specs.js +3 -1
- package/dist/tools/tools.module.d.ts +10 -0
- package/dist/tools/tools.module.js +113 -0
- package/dist/tools/validate.js +1 -1
- package/dist/ui/call-extension.d.ts +16 -0
- package/dist/ui/call-extension.js +38 -0
- package/dist/ui/embed-token.d.ts +9 -5
- package/dist/ui/embed-token.js +34 -6
- package/dist/ui/ui-stream.d.ts +22 -17
- package/dist/ui/ui-stream.js +72 -12
- package/dist/ui/ui.module.d.ts +7 -0
- package/dist/ui/ui.module.js +28 -0
- package/dist/ui/views.controller.d.ts +14 -12
- package/dist/ui/views.controller.js +32 -25
- package/dist/ui/views.d.ts +10 -57
- package/dist/ui/views.js +58 -46
- package/package.json +15 -3
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
- 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/src/migrations/0089_model_kinds_usage.sql +38 -0
- package/src/migrations/0090_initial_passwords.sql +27 -0
- package/src/migrations/0091_account_time_zone.sql +4 -0
- package/src/migrations/0092_tools_default_on.sql +27 -0
- package/src/migrations/0093_connected_environments.sql +37 -0
- package/src/migrations/0094_environment_paths_idx.sql +7 -0
- package/src/migrations/0095_environment_files_resets.sql +5 -0
- package/src/migrations/0096_environment_demoted_default.sql +18 -0
- package/src/migrations/0097_extension_installs_enabled_at.sql +16 -0
- package/src/migrations/0098_single_provider_running_first.sql +41 -0
- package/src/migrations/0099_channel_connection_guide_ack.sql +6 -0
- package/src/migrations/0100_catalog_files.sql +13 -0
- package/src/migrations/0101_marketplace_icons.sql +32 -0
- package/dist/catalog/upgrade-targets.d.ts +0 -59
- package/dist/catalog/upgrade-targets.js +0 -90
- package/dist/conversations/sandbox-status.d.ts +0 -21
- package/dist/conversations/sandbox-status.js +0 -24
- package/dist/extensions/org-config.controller.d.ts +0 -24
- package/dist/extensions/org-config.controller.js +0 -59
- package/dist/http/gateway.module.js +0 -13
- package/dist/http/health.controller.d.ts +0 -26
- package/dist/http/health.controller.js +0 -79
- package/dist/http/tokens.d.ts +0 -131
- package/dist/http/tokens.js +0 -131
- package/dist/http/zod.pipe.d.ts +0 -8
- package/dist/http/zod.pipe.js +0 -14
- package/dist/identity/enterprise-admin.d.ts +0 -14
- package/dist/identity/enterprise-admin.js +0 -27
- package/dist/identity/rate-limit.d.ts +0 -55
- package/dist/identity/rate-limit.js +0 -121
- package/dist/sandbox/lifecycle.d.ts +0 -21
- package/dist/sandbox/lifecycle.js +0 -68
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -1,18 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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, randomUUID } from "node:crypto";
|
|
11
|
+
import { EXTENSION_POINTS, marketplaceEntryDeprecation, parseExtensionPoint, parseSkillMd, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
|
|
12
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
3
13
|
import { sql } from "kysely";
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
14
|
+
import semver from "semver";
|
|
15
|
+
import { revertTemplateVersionIn, softDeleteTemplateIn } from "../agents/templates.js";
|
|
6
16
|
import { ApiError } from "../errors.js";
|
|
7
17
|
import { isExtensionEnabled } from "../extensions/enabled.js";
|
|
18
|
+
import { OrgExtensionConfigs, } from "../extensions/org-config.js";
|
|
19
|
+
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
8
20
|
import { audit } from "../identity/audit.js";
|
|
9
|
-
import {
|
|
21
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
22
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
23
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
24
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
25
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
26
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
27
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
10
28
|
import { packagePath } from "../packages/tgz.js";
|
|
11
|
-
import { skillConflictError, skillConflicts, } from "../skills/skills.service.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
29
|
+
import { SkillsService, skillConflictError, skillConflicts, } from "../skills/skills.service.js";
|
|
30
|
+
import { StorageService } from "../storage/storage.service.js";
|
|
31
|
+
import { ConnectorsService } from "../tools/connectors.service.js";
|
|
32
|
+
import { findConnectorIn, lockOrgForActions, readCatalogAgentTemplates, readCatalogFiles, readCatalogTemplates, requiredActions, templateConnectorInput, templatePluginProblem, } from "./catalog-content.js";
|
|
33
|
+
import { versionUsable } from "./catalog-items.js";
|
|
34
|
+
import { agentDefinitionRefs, componentOn, connectorTemplateState, connectorTemplatesOn, listedIn, loadComponents, loadScopeState, pluginFactsOf, referenceIds, switchOf, } from "./component-state.js";
|
|
35
|
+
import { assertItemInstallable, disabledPluginItems, pluginItemDisabled, resolveRequestsByInstall, } from "./request-rules.js";
|
|
36
|
+
import { visibleTo } from "./scope.js";
|
|
37
|
+
import { ScopeNoLongerWanted, ScopeStillWanted, wantedByScope } from "./scope-state.js";
|
|
15
38
|
import { maxSatisfying, satisfiesRange } from "./versions.js";
|
|
39
|
+
/** The confirm hash of an uninstall preview: sha256 over its sorted JSON (the scheme of `diffHash`). */
|
|
40
|
+
export function uninstallPreviewHash(p) {
|
|
41
|
+
const by = (xs) => [...xs].sort((a, b) => `${a.kind}:${a.ref}`.localeCompare(`${b.kind}:${b.ref}`));
|
|
42
|
+
return createHash("sha256")
|
|
43
|
+
.update(JSON.stringify({
|
|
44
|
+
...p,
|
|
45
|
+
components: by(p.components),
|
|
46
|
+
kept: by(p.kept),
|
|
47
|
+
agents: [...p.agents]
|
|
48
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
49
|
+
.map((a) => ({ ...a, uses: by(a.uses) })),
|
|
50
|
+
}))
|
|
51
|
+
.digest("hex");
|
|
52
|
+
}
|
|
53
|
+
/** Upserts the org's switch row of an item in the caller's transaction (the org lock is held). */
|
|
54
|
+
export async function upsertOrgSwitch(db, orgId, itemId, enabled, actor) {
|
|
55
|
+
await db
|
|
56
|
+
.insertInto("catalog_item_org_switches")
|
|
57
|
+
.values({ item_id: itemId, org_id: orgId, enabled, updated_by: actor })
|
|
58
|
+
.onConflict((oc) => oc.columns(["item_id", "org_id"]).doUpdateSet({
|
|
59
|
+
enabled,
|
|
60
|
+
updated_by: actor,
|
|
61
|
+
updated_at: sql `now()`,
|
|
62
|
+
}))
|
|
63
|
+
.execute();
|
|
64
|
+
}
|
|
65
|
+
/** The kernel (actor null, the scope sync) never installs what needs the org's input. */
|
|
66
|
+
export class NeedsOrgInput extends ApiError {
|
|
67
|
+
plugin;
|
|
68
|
+
constructor(plugin) {
|
|
69
|
+
super("internal", `Plugin ${plugin} needs the organization's input (connector templates); only a person can install it`);
|
|
70
|
+
this.plugin = plugin;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const systemNeedsInput = (name) => new NeedsOrgInput(name);
|
|
16
74
|
/** How deep plugin dependencies may nest (the root plugin's dependencies are level 1). */
|
|
17
75
|
export const DEPENDENCY_DEPTH_LIMIT = 10;
|
|
18
76
|
/** A failed install step, carried up through the dependency installs to the root install. */
|
|
@@ -45,33 +103,66 @@ const installNotFound = () => new ApiError("plugin.install_not_found", "Plugin i
|
|
|
45
103
|
const fail = (path, message) => new ApiError("validation_failed", "Request validation failed", [{ path, message }]);
|
|
46
104
|
const isUniqueViolation = (e) => typeof e === "object" && e !== null && e.code === "23505";
|
|
47
105
|
const unresolved = (name, range, why) => new ApiError("catalog.dependency_unresolved", `Dependency ${name}@${range} cannot be resolved: ${why}`, [{ dependency: name, range }]);
|
|
48
|
-
const dependencyDisabled = (name) => new ApiError("catalog.dependency_disabled", `Dependency ${name} is disabled by the
|
|
106
|
+
const dependencyDisabled = (name) => new ApiError("catalog.dependency_disabled", `Dependency ${name} is disabled by the super admin, so this plugin cannot be installed`, [{ dependency: name }]);
|
|
49
107
|
/**
|
|
50
|
-
* The dependency `d` resolved against the catalog
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
108
|
+
* The dependency `d` resolved against the catalog (ruling P2-17, one version per deployment): the
|
|
109
|
+
* dependency's platform version (`platform_synced_version`), which must satisfy its range; only
|
|
110
|
+
* while it has none yet (its first sync failed), the highest imported version satisfying the range
|
|
111
|
+
* that its marketplace does not deprecate, a stable one before a prerelease (the marketplace
|
|
112
|
+
* folding rule). No such item or version -> `catalog.dependency_unresolved`; the item disabled ->
|
|
113
|
+
* `catalog.dependency_disabled` (the super admin's ban is not bypassed, spec §10).
|
|
54
114
|
*/
|
|
55
115
|
async function resolveOne(db, d) {
|
|
56
116
|
const item = await db
|
|
57
117
|
.selectFrom("catalog_items")
|
|
58
|
-
.select([
|
|
118
|
+
.select([
|
|
119
|
+
"id",
|
|
120
|
+
"disabled",
|
|
121
|
+
"platform_synced_version",
|
|
122
|
+
"marketplace_id",
|
|
123
|
+
"awaiting_confirmation",
|
|
124
|
+
"owner_org_id",
|
|
125
|
+
"latest_version",
|
|
126
|
+
])
|
|
59
127
|
.where("name", "=", d.name)
|
|
60
128
|
.where("deleted_at", "is", null)
|
|
61
129
|
.executeTakeFirst();
|
|
62
130
|
if (!item) {
|
|
63
|
-
throw unresolved(d.name, d.version, "it is not in the
|
|
131
|
+
throw unresolved(d.name, d.version, "it is not in the platform catalog; ask the super admin to import it");
|
|
64
132
|
}
|
|
65
|
-
if (item.
|
|
133
|
+
if (item.disabled)
|
|
66
134
|
throw dependencyDisabled(d.name);
|
|
135
|
+
// An org upload waiting for the super admin is no dependency target (ruling P3-9)
|
|
136
|
+
if (item.awaiting_confirmation) {
|
|
137
|
+
throw unresolved(d.name, d.version, "it waits for a super admin to confirm its extension");
|
|
138
|
+
}
|
|
67
139
|
const versions = await db
|
|
68
140
|
.selectFrom("catalog_item_versions")
|
|
69
|
-
.select(["version", "manifest", "imported_at"])
|
|
141
|
+
.select(["version", "manifest", "imported_at", "applied_at", "rejected_at"])
|
|
70
142
|
.where("item_id", "=", item.id)
|
|
71
143
|
.execute();
|
|
72
|
-
|
|
144
|
+
let v;
|
|
145
|
+
if (item.platform_synced_version !== null) {
|
|
146
|
+
v = versions.find((x) => x.version === item.platform_synced_version);
|
|
147
|
+
if (!v || !satisfiesRange(v.version, d.version)) {
|
|
148
|
+
throw unresolved(d.name, d.version, `its platform version ${item.platform_synced_version} does not satisfy the range; ask ` +
|
|
149
|
+
"the super admin to update it");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
const deprecated = await deprecatedVersions(db, d.name, item.marketplace_id);
|
|
154
|
+
// An org's plugin offers only its applied version: never one pending or rejected (P3-34),
|
|
155
|
+
// also once transferred to the platform (P3-52)
|
|
156
|
+
const candidates = versions
|
|
157
|
+
.filter((x) => versionUsable(x))
|
|
158
|
+
.filter((x) => item.owner_org_id === null || x.version === item.latest_version)
|
|
159
|
+
.filter((x) => !deprecated.has(x.version))
|
|
160
|
+
.map((x) => ({ ...x, importedAt: x.imported_at }));
|
|
161
|
+
v =
|
|
162
|
+
maxSatisfying(candidates.filter((x) => semver.prerelease(x.version) === null), d.version) ?? maxSatisfying(candidates, d.version);
|
|
163
|
+
}
|
|
73
164
|
if (!v) {
|
|
74
|
-
throw unresolved(d.name, d.version, "no imported version satisfies the range; ask the
|
|
165
|
+
throw unresolved(d.name, d.version, "no imported version satisfies the range; ask the super admin to import one");
|
|
75
166
|
}
|
|
76
167
|
return {
|
|
77
168
|
name: d.name,
|
|
@@ -81,10 +172,24 @@ async function resolveOne(db, d) {
|
|
|
81
172
|
manifest: v.manifest,
|
|
82
173
|
};
|
|
83
174
|
}
|
|
175
|
+
/** The versions of plugin `name` its marketplace (`marketplaceId`) marks deprecated. */
|
|
176
|
+
async function deprecatedVersions(db, name, marketplaceId) {
|
|
177
|
+
if (marketplaceId === null)
|
|
178
|
+
return new Set();
|
|
179
|
+
const rows = await db
|
|
180
|
+
.selectFrom("marketplace_entries")
|
|
181
|
+
.select(["version", "entry"])
|
|
182
|
+
.where("source_id", "=", marketplaceId)
|
|
183
|
+
.where("name", "=", name)
|
|
184
|
+
.execute();
|
|
185
|
+
return new Set(rows
|
|
186
|
+
.filter((r) => marketplaceEntryDeprecation(r.entry) !== null)
|
|
187
|
+
.map((r) => r.version));
|
|
188
|
+
}
|
|
84
189
|
/**
|
|
85
|
-
* Resolves a plugin's dependencies against the catalog: for each one the
|
|
86
|
-
*
|
|
87
|
-
* dependency nothing satisfies -> `catalog.dependency_unresolved`; a disabled one ->
|
|
190
|
+
* Resolves a plugin's dependencies against the catalog: for each one the platform version of the
|
|
191
|
+
* live item with that name, which must satisfy its range (see `resolveOne`). The whole dependency
|
|
192
|
+
* tree is checked: a dependency nothing satisfies -> `catalog.dependency_unresolved`; a disabled one ->
|
|
88
193
|
* `catalog.dependency_disabled`; a cycle (`a` -> `b` -> `a`, by name) or nesting deeper than
|
|
89
194
|
* {@link DEPENDENCY_DEPTH_LIMIT} -> `catalog.dependency_cycle`. Returns the direct dependencies.
|
|
90
195
|
*/
|
|
@@ -169,9 +274,11 @@ export function under(e, at) {
|
|
|
169
274
|
* not run it; already enabled is recorded created=false);
|
|
170
275
|
* 3. connectors from the templates (credentials / clients go to secrets, default policies are
|
|
171
276
|
* recorded `policy_source 'template'`);
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
277
|
+
* The plugin's skills and agent templates are platform components (plugin scope phase 2): stored
|
|
278
|
+
* once for the deployment and on in the org while the plugin is, so an install writes no org rows
|
|
279
|
+
* for them; a skill name the org already uses (its own skill, another plugin's) refuses the install
|
|
280
|
+
* while planning with `plugin.skill_conflict` (spec §9.2, rule 10). Uninstall leaves the org copies
|
|
281
|
+
* earlier installs wrote (linked to the platform components by the migration).
|
|
175
282
|
* Approval follows the installed plugin's policy only (spec §10): dependency components are
|
|
176
283
|
* re-checked against the root item's policy and their own item's disabled state. Each component is
|
|
177
284
|
* recorded in `plugin_install_components` as soon as it exists; if any step fails, the components
|
|
@@ -179,18 +286,47 @@ export function under(e, at) {
|
|
|
179
286
|
* install is marked failed (error holds only the step and the error code) and 502
|
|
180
287
|
* `plugin.install_failed` is thrown. Uninstall removes only components with created=true that
|
|
181
288
|
* nothing else uses, and reports what it kept and why. No in-process state; the org row lock
|
|
182
|
-
* serializes writes within one org.
|
|
183
|
-
* (plugin-upgrade.ts
|
|
184
|
-
* `
|
|
289
|
+
* serializes writes within one org. There is no per-org upgrade: a platform plugin is updated
|
|
290
|
+
* once for the deployment (`PlatformPluginUpdater`, plugin-upgrade.ts, ruling F2); an install left
|
|
291
|
+
* `upgrading` by an earlier per-org upgrade is undone from its journal by the next uninstall. The
|
|
292
|
+
* methods without `private` are internal to the catalog, not an API.
|
|
185
293
|
*/
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
294
|
+
let PluginInstaller = class PluginInstaller {
|
|
295
|
+
kdb;
|
|
296
|
+
orgLock;
|
|
297
|
+
storage;
|
|
298
|
+
registry;
|
|
299
|
+
skills;
|
|
300
|
+
orgConfigs;
|
|
301
|
+
config;
|
|
302
|
+
connectors;
|
|
303
|
+
log;
|
|
304
|
+
txHost;
|
|
305
|
+
constructor(kdb,
|
|
306
|
+
/** The org row lock (orgs/org-lock.ts): joins the caller's transaction. */
|
|
307
|
+
orgLock, storage,
|
|
308
|
+
/** The loaded extensions and connectors of this replica (the extension registry). */
|
|
309
|
+
registry, skills, orgConfigs, config,
|
|
310
|
+
/** Org connectors: installs create, upgrade and remove them. */
|
|
311
|
+
connectors, log, txHost) {
|
|
312
|
+
this.kdb = kdb;
|
|
313
|
+
this.orgLock = orgLock;
|
|
314
|
+
this.storage = storage;
|
|
315
|
+
this.registry = registry;
|
|
316
|
+
this.skills = skills;
|
|
317
|
+
this.orgConfigs = orgConfigs;
|
|
318
|
+
this.config = config;
|
|
319
|
+
this.connectors = connectors;
|
|
320
|
+
this.log = log;
|
|
321
|
+
this.txHost = txHost;
|
|
322
|
+
}
|
|
323
|
+
/** The kernel-schema handle of the current context (the transaction, else the pool). */
|
|
324
|
+
get db() {
|
|
325
|
+
return this.kdb.db;
|
|
190
326
|
}
|
|
191
|
-
/**
|
|
192
|
-
|
|
193
|
-
return this.
|
|
327
|
+
/** `catalog.staleInstallMinutes`: an install `installing` for longer can be cleaned up by uninstalling it. */
|
|
328
|
+
staleInstallMinutes() {
|
|
329
|
+
return this.config.get().catalog.staleInstallMinutes;
|
|
194
330
|
}
|
|
195
331
|
/**
|
|
196
332
|
* The checks an install runs before it creates anything, without the org's input (for the org
|
|
@@ -203,12 +339,15 @@ export class PluginInstaller {
|
|
|
203
339
|
return { actions: planActions(plan) };
|
|
204
340
|
}
|
|
205
341
|
async install(orgId, actor, itemId, version, input, opts = {}) {
|
|
342
|
+
const { switchOn, via, ...actorOpts } = opts;
|
|
206
343
|
const plan = await this.plan(orgId, actor, itemId, version, input, "", undefined);
|
|
207
344
|
await this.assertNoSkillConflicts(orgId, plan);
|
|
208
345
|
let installId;
|
|
209
346
|
try {
|
|
210
|
-
installId = await this.execute(orgId, actor, plan,
|
|
347
|
+
installId = await this.execute(orgId, actor, plan, actorOpts, {
|
|
211
348
|
actions: planActions(plan),
|
|
349
|
+
...(switchOn === true && { switchOn }),
|
|
350
|
+
...(via !== undefined && { via }),
|
|
212
351
|
});
|
|
213
352
|
}
|
|
214
353
|
catch (e) {
|
|
@@ -243,14 +382,17 @@ export class PluginInstaller {
|
|
|
243
382
|
* and a name two plugins of the same plan both bring (the one installed first is the source).
|
|
244
383
|
*/
|
|
245
384
|
async assertNoSkillConflicts(orgId, plan) {
|
|
246
|
-
const conflicts = await planSkillConflicts(this.
|
|
385
|
+
const conflicts = await planSkillConflicts(this.db, orgId, plan);
|
|
247
386
|
if (conflicts.length > 0)
|
|
248
387
|
throw skillConflictError(conflicts);
|
|
249
388
|
}
|
|
250
389
|
/** The connector checks of templates against what this replica loads right now. */
|
|
251
390
|
templateDeps() {
|
|
252
|
-
const versions = new Map(this.
|
|
253
|
-
return {
|
|
391
|
+
const versions = new Map(this.registry.manifests().map((m) => [m.name, m.version]));
|
|
392
|
+
return {
|
|
393
|
+
findConnector: (plugin, kind) => findConnectorIn(this.registry, plugin, kind),
|
|
394
|
+
pluginVersion: (n) => versions.get(n),
|
|
395
|
+
};
|
|
254
396
|
}
|
|
255
397
|
/**
|
|
256
398
|
* Plans the install of one plugin version and, depth first, of its dependencies not yet
|
|
@@ -261,7 +403,7 @@ export class PluginInstaller {
|
|
|
261
403
|
async plan(orgId, actor, itemId, version, input, at, approvedBy) {
|
|
262
404
|
if (!UUID_RE.test(itemId))
|
|
263
405
|
throw new ApiError("catalog.item_not_found", "Plugin not found");
|
|
264
|
-
const v = await this.
|
|
406
|
+
const v = await this.db
|
|
265
407
|
.selectFrom("catalog_item_versions as v")
|
|
266
408
|
.innerJoin("catalog_items as i", "i.id", "v.item_id")
|
|
267
409
|
.select([
|
|
@@ -279,11 +421,19 @@ export class PluginInstaller {
|
|
|
279
421
|
if (!v)
|
|
280
422
|
throw new ApiError("catalog.item_not_found", "Plugin version not found");
|
|
281
423
|
const manifest = v.manifest;
|
|
282
|
-
const
|
|
424
|
+
const declared = await resolveDependencies(this.db, manifest);
|
|
283
425
|
const extension = await this.planExtension(orgId, manifest);
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
426
|
+
const allTemplates = await readCatalogTemplates(this.storage, v);
|
|
427
|
+
// Only the connector templates on in the org make connectors (ruling P2-6): one switched off
|
|
428
|
+
// there, outside its own scope or disabled is skipped (input given for it is ignored)
|
|
429
|
+
const on = await connectorTemplatesOn(this.db, orgId, itemId, allTemplates.map((t) => t.id));
|
|
430
|
+
const templates = allTemplates.filter((t) => on.has(t.id));
|
|
431
|
+
const deps = [
|
|
432
|
+
...declared,
|
|
433
|
+
...(await this.impliedProviders(orgId, manifest, templates, declared)),
|
|
434
|
+
];
|
|
435
|
+
const skillNames = await catalogSkillNames(this.storage, v, manifest);
|
|
436
|
+
const agentTemplates = await readCatalogAgentTemplates(this.storage, v);
|
|
287
437
|
const connectors = new Map();
|
|
288
438
|
if (input === null) {
|
|
289
439
|
for (const ct of templates) {
|
|
@@ -293,14 +443,17 @@ export class PluginInstaller {
|
|
|
293
443
|
}
|
|
294
444
|
}
|
|
295
445
|
else {
|
|
296
|
-
this.checkInput(manifest,
|
|
446
|
+
this.checkInput(manifest, allTemplates, input, at);
|
|
297
447
|
for (const ct of templates) {
|
|
448
|
+
// The kernel installs only what needs no org input (the scope sync's `needs_config` rule)
|
|
449
|
+
if (actor === null)
|
|
450
|
+
throw systemNeedsInput(manifest.name);
|
|
298
451
|
connectors.set(ct.id, this.planConnector(actor, { itemId, version, name: manifest.name }, ct, input, at, approvedBy));
|
|
299
452
|
}
|
|
300
453
|
}
|
|
301
454
|
const dependencies = [];
|
|
302
455
|
for (const dep of deps) {
|
|
303
|
-
if (await this.liveDependency(this.
|
|
456
|
+
if (await this.liveDependency(this.db, orgId, dep)) {
|
|
304
457
|
dependencies.push({ dep, plan: null });
|
|
305
458
|
continue;
|
|
306
459
|
}
|
|
@@ -325,6 +478,64 @@ export class PluginInstaller {
|
|
|
325
478
|
dependencies,
|
|
326
479
|
};
|
|
327
480
|
}
|
|
481
|
+
/**
|
|
482
|
+
* The providers of the templates' connector kinds as implied dependencies: a template whose
|
|
483
|
+
* `plugin` is neither this plugin, a declared dependency nor already enabled in the org makes that
|
|
484
|
+
* plugin a dependency (installed first, recorded like a declared one, so an uninstall hands it
|
|
485
|
+
* back). No such plugin offered by the catalog -> `connector.kind_unavailable` naming it, before
|
|
486
|
+
* anything is written.
|
|
487
|
+
*/
|
|
488
|
+
async impliedProviders(orgId, manifest, templates, declared) {
|
|
489
|
+
const out = [];
|
|
490
|
+
const seen = new Set([manifest.name, ...declared.map((d) => d.name)]);
|
|
491
|
+
for (const ct of templates) {
|
|
492
|
+
const provider = ct.file.template.plugin;
|
|
493
|
+
if (seen.has(provider))
|
|
494
|
+
continue;
|
|
495
|
+
seen.add(provider);
|
|
496
|
+
// Not deployed: the not_deployed refusal of the plan's own checks says it
|
|
497
|
+
if (templatePluginProblem(this.templateDeps(), ct.file.template) !== undefined)
|
|
498
|
+
continue;
|
|
499
|
+
if (await isExtensionEnabled(this.db, orgId, provider))
|
|
500
|
+
continue;
|
|
501
|
+
const refuse = (why) => new ApiError("connector.kind_unavailable", `Connector template ${ct.id} needs the plugin ${provider}, which is not enabled in this organization: ${why}`);
|
|
502
|
+
let dep;
|
|
503
|
+
try {
|
|
504
|
+
const { manifest: _m, ...resolved } = await resolveOne(this.db, {
|
|
505
|
+
name: provider,
|
|
506
|
+
version: ct.file.template.pluginVersion ?? "*",
|
|
507
|
+
});
|
|
508
|
+
dep = resolved;
|
|
509
|
+
}
|
|
510
|
+
catch (e) {
|
|
511
|
+
if (!(e instanceof ApiError))
|
|
512
|
+
throw e;
|
|
513
|
+
throw refuse(e.code === "catalog.dependency_unresolved"
|
|
514
|
+
? `${provider} is deployed but switched off here and the catalog has no entry to switch it on; ask the super admin to enable it`
|
|
515
|
+
: `${provider} is not offered to this organization`);
|
|
516
|
+
}
|
|
517
|
+
// Scope: only a plugin offered to this org may be switched on for it (nothing more is said)
|
|
518
|
+
const item = await this.db
|
|
519
|
+
.selectFrom("catalog_items")
|
|
520
|
+
.select(["scope", "builtin"])
|
|
521
|
+
.where("id", "=", dep.itemId)
|
|
522
|
+
.executeTakeFirstOrThrow();
|
|
523
|
+
const listed = await this.db
|
|
524
|
+
.selectFrom("catalog_item_scope_orgs")
|
|
525
|
+
.select("item_id")
|
|
526
|
+
.where("item_id", "=", dep.itemId)
|
|
527
|
+
.where("org_id", "=", orgId)
|
|
528
|
+
.executeTakeFirst();
|
|
529
|
+
if (!visibleTo({ scope: item.builtin ? "all" : item.scope }, listed !== undefined)) {
|
|
530
|
+
throw refuse(`${provider} is not offered to this organization`);
|
|
531
|
+
}
|
|
532
|
+
if (await this.findLiveDependency(this.db, orgId, dep, false)) {
|
|
533
|
+
throw refuse(`${provider} is installed but switched off in this organization`);
|
|
534
|
+
}
|
|
535
|
+
out.push(dep);
|
|
536
|
+
}
|
|
537
|
+
return out;
|
|
538
|
+
}
|
|
328
539
|
/**
|
|
329
540
|
* The connector input of one template from the org's input (C30), checked without a connection:
|
|
330
541
|
* the template's connector extension deployed, the input valid, the credential / OAuth client it
|
|
@@ -355,7 +566,7 @@ export class PluginInstaller {
|
|
|
355
566
|
: `This connector template needs ${needs}`);
|
|
356
567
|
}
|
|
357
568
|
try {
|
|
358
|
-
this.
|
|
569
|
+
this.connectors.checkCreateInput(actor, ci);
|
|
359
570
|
}
|
|
360
571
|
catch (e) {
|
|
361
572
|
throw under(e, path);
|
|
@@ -397,30 +608,30 @@ export class PluginInstaller {
|
|
|
397
608
|
* cannot leave the component pointing at a removed install. `created` false: the org's existing
|
|
398
609
|
* install, if any (returns its id, undefined when there is none); it must be `installed`
|
|
399
610
|
* (`installing` -> 409 `plugin.install_in_progress`, retry later) and in range. `created` true:
|
|
400
|
-
* `child`, the dependency install this install just created, must still exist.
|
|
611
|
+
* `child`, the dependency install this install just created, must still exist. A step of an
|
|
612
|
+
* install or upgrade: it commits on its own (`requires_new`), the undo on failure relies on it.
|
|
401
613
|
*/
|
|
402
614
|
async recordDependency(orgId, dep, record, child) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
await record({ kind: "plugin", ref: child, created: true, skillVersion: null }, t);
|
|
411
|
-
return child;
|
|
615
|
+
const t = this.db;
|
|
616
|
+
await this.orgLock.lock(orgId);
|
|
617
|
+
const live = await this.findLiveDependency(t, orgId, dep, true);
|
|
618
|
+
if (child !== undefined) {
|
|
619
|
+
if (live?.id !== child || live.status !== "installed") {
|
|
620
|
+
throw unresolved(dep.name, dep.range, "its install in this organization was removed meanwhile; try again");
|
|
412
621
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
622
|
+
await record({ kind: "plugin", ref: child, created: true, skillVersion: null });
|
|
623
|
+
return child;
|
|
624
|
+
}
|
|
625
|
+
if (!live)
|
|
626
|
+
return undefined;
|
|
627
|
+
if (!satisfiesRange(live.version, dep.range)) {
|
|
628
|
+
throw unresolved(dep.name, dep.range, `this organization has version ${live.version} installed; uninstall it to install a matching version`);
|
|
629
|
+
}
|
|
630
|
+
if (live.status !== "installed") {
|
|
631
|
+
throw new ApiError("plugin.install_in_progress", `Dependency ${dep.name} is being installed by another install in this organization; try again when it finishes. An install stuck for longer than catalog.staleInstallMinutes can be removed by uninstalling it`);
|
|
632
|
+
}
|
|
633
|
+
await record({ kind: "plugin", ref: live.id, created: false, skillVersion: null });
|
|
634
|
+
return live.id;
|
|
424
635
|
}
|
|
425
636
|
/**
|
|
426
637
|
* Runs a plan: the install row, then the steps (see the class comment). Throws
|
|
@@ -428,63 +639,19 @@ export class PluginInstaller {
|
|
|
428
639
|
* as they are. Returns the install id.
|
|
429
640
|
*/
|
|
430
641
|
async execute(orgId, actor, plan, opts, ctx) {
|
|
431
|
-
const { itemId,
|
|
642
|
+
const { itemId, manifest } = plan;
|
|
432
643
|
// The install row (role and item policy re-checked under the lock; one live install per org
|
|
433
644
|
// and item)
|
|
434
645
|
const installId = randomUUID();
|
|
435
|
-
await this.
|
|
436
|
-
await lockOrgForActions(t, orgId, actor, ctx.actions);
|
|
437
|
-
if (ctx.approvedBy !== undefined) {
|
|
438
|
-
// A dependency disabled (or removed) since it was planned
|
|
439
|
-
const own = await t
|
|
440
|
-
.selectFrom("catalog_items")
|
|
441
|
-
.select(["policy", "deleted_at"])
|
|
442
|
-
.where("id", "=", itemId)
|
|
443
|
-
.forShare()
|
|
444
|
-
.executeTakeFirst();
|
|
445
|
-
if (!own || own.deleted_at !== null) {
|
|
446
|
-
throw unresolved(plan.name, plan.version, "it was removed from the enterprise catalog");
|
|
447
|
-
}
|
|
448
|
-
if (own.policy === "disabled")
|
|
449
|
-
throw dependencyDisabled(plan.name);
|
|
450
|
-
}
|
|
451
|
-
await assertItemInstallable(t, orgId, itemId, ctx.approvedBy ?? itemId);
|
|
452
|
-
const live = await t
|
|
453
|
-
.selectFrom("plugin_installs")
|
|
454
|
-
.select("id")
|
|
455
|
-
.where("org_id", "=", orgId)
|
|
456
|
-
.where("item_id", "=", itemId)
|
|
457
|
-
.where("status", "<>", "failed")
|
|
458
|
-
.executeTakeFirst();
|
|
459
|
-
if (live)
|
|
460
|
-
throw alreadyInstalled();
|
|
461
|
-
try {
|
|
462
|
-
await t
|
|
463
|
-
.insertInto("plugin_installs")
|
|
464
|
-
.values({
|
|
465
|
-
id: installId,
|
|
466
|
-
org_id: orgId,
|
|
467
|
-
item_id: itemId,
|
|
468
|
-
version,
|
|
469
|
-
status: "installing",
|
|
470
|
-
installed_by: actor,
|
|
471
|
-
})
|
|
472
|
-
.execute();
|
|
473
|
-
}
|
|
474
|
-
catch (e) {
|
|
475
|
-
if (isUniqueViolation(e))
|
|
476
|
-
throw alreadyInstalled();
|
|
477
|
-
throw e;
|
|
478
|
-
}
|
|
479
|
-
});
|
|
646
|
+
await this.createInstallRow(orgId, actor, plan, ctx, installId);
|
|
480
647
|
const done = [];
|
|
481
|
-
// Records a component in the
|
|
482
|
-
// fails, the install aborts and rolls back)
|
|
483
|
-
const record = async (c
|
|
648
|
+
// Records a component in the transaction of the context (none: on its own; the install row
|
|
649
|
+
// already cleaned up -> the FK fails, the install aborts and rolls back)
|
|
650
|
+
const record = async (c) => {
|
|
484
651
|
// Into `done` first: a component that exists is rolled back even when recording it fails
|
|
485
652
|
// (enabling an extension and recording it share one transaction and fail together)
|
|
486
653
|
done.push(c);
|
|
487
|
-
await
|
|
654
|
+
await this.db
|
|
488
655
|
.insertInto("plugin_install_components")
|
|
489
656
|
.values({
|
|
490
657
|
install_id: installId,
|
|
@@ -514,6 +681,7 @@ export class PluginInstaller {
|
|
|
514
681
|
actions: requiredActions(depPlan.manifest),
|
|
515
682
|
approvedBy,
|
|
516
683
|
parent: installId,
|
|
684
|
+
...(ctx.via !== undefined && { via: ctx.via }),
|
|
517
685
|
});
|
|
518
686
|
}
|
|
519
687
|
catch (e) {
|
|
@@ -532,25 +700,19 @@ export class PluginInstaller {
|
|
|
532
700
|
}
|
|
533
701
|
step = "extension";
|
|
534
702
|
if (plan.extension !== null) {
|
|
535
|
-
|
|
536
|
-
// "Enabled before" is decided under the org row lock (already enabled: put writes nothing,
|
|
537
|
-
// the config is untouched); the component is recorded in the same transaction
|
|
538
|
-
await this.d.orgConfigs.put(orgId, p, {
|
|
703
|
+
await this.enableExtension(orgId, plan.extension, {
|
|
539
704
|
enabled: true,
|
|
540
705
|
...(plan.extensionConfig !== undefined && { config: plan.extensionConfig }),
|
|
541
|
-
}, actor, opts.actorTokenId, {
|
|
542
|
-
viaItem: itemId,
|
|
543
|
-
...(nested && { approvedBy }),
|
|
544
|
-
ifDisabled: { skipped: false },
|
|
545
|
-
inTransaction: (t, skipped) => record({ kind: "extension", ref: p, created: !skipped, skillVersion: null }, t),
|
|
546
|
-
});
|
|
706
|
+
}, actor, opts.actorTokenId, { viaItem: itemId, ...(nested && { approvedBy }) }, record);
|
|
547
707
|
}
|
|
548
708
|
step = "connectors";
|
|
549
709
|
for (const ct of plan.templates) {
|
|
550
710
|
const ci = plan.connectors.get(ct.id);
|
|
551
711
|
if (!ci)
|
|
552
712
|
throw new ApiError("internal", `Connector template ${ct.id} was not planned`);
|
|
553
|
-
|
|
713
|
+
if (actor === null)
|
|
714
|
+
throw systemNeedsInput(manifest.name);
|
|
715
|
+
const r = await this.connectors.create(orgId, actor, ci, opts.actorTokenId);
|
|
554
716
|
await record({
|
|
555
717
|
kind: "connector",
|
|
556
718
|
ref: r.connector.id,
|
|
@@ -559,109 +721,170 @@ export class PluginInstaller {
|
|
|
559
721
|
templateId: ct.id,
|
|
560
722
|
});
|
|
561
723
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// recorded in one transaction, under the org row lock
|
|
566
|
-
await this.d.db.transaction().execute(async (t) => {
|
|
567
|
-
await lockOrg(t, orgId);
|
|
568
|
-
const r = await putTemplateVersionIn(t, {
|
|
569
|
-
orgId,
|
|
570
|
-
plugin: plan.name,
|
|
571
|
-
catalogItemId: itemId,
|
|
572
|
-
catalogVersion: version,
|
|
573
|
-
sourceFormat: plan.sourceFormat,
|
|
574
|
-
}, a.template);
|
|
575
|
-
await record({
|
|
576
|
-
kind: "agent_template",
|
|
577
|
-
ref: r.id,
|
|
578
|
-
created: r.created,
|
|
579
|
-
skillVersion: !r.created && r.changed ? r.version : null,
|
|
580
|
-
}, t);
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
step = "skills";
|
|
584
|
-
for (const s of manifest.skills ?? []) {
|
|
585
|
-
const files = await readCatalogFiles(this.d.storage, plan.row.object_prefix, plan.row.files, packagePath(s.path));
|
|
586
|
-
const r = await this.d.skills.createVersionFromFiles(orgId, actor, { ...skillOf(files), files }, {
|
|
587
|
-
catalog: {
|
|
588
|
-
itemId,
|
|
589
|
-
version,
|
|
590
|
-
...(nested && { approvedBy }),
|
|
591
|
-
format: plan.sourceFormat,
|
|
592
|
-
suggestPinned: s.pinned === true,
|
|
593
|
-
},
|
|
594
|
-
...opts,
|
|
595
|
-
});
|
|
596
|
-
await record({
|
|
597
|
-
kind: "skill",
|
|
598
|
-
ref: r.skill.id,
|
|
599
|
-
created: r.created,
|
|
600
|
-
skillVersion: r.created ? null : r.version,
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
await this.d.db.transaction().execute(async (t) => {
|
|
604
|
-
await lockOrg(t, orgId);
|
|
605
|
-
const updated = await t
|
|
606
|
-
.updateTable("plugin_installs")
|
|
607
|
-
.set({ status: "installed" })
|
|
608
|
-
.where("id", "=", installId)
|
|
609
|
-
.where("status", "=", "installing")
|
|
610
|
-
.executeTakeFirst();
|
|
611
|
-
// The install row was already cleaned up as stale: do not audit plugin.org_installed, roll
|
|
612
|
-
// back
|
|
613
|
-
if (updated.numUpdatedRows === 0n) {
|
|
614
|
-
throw new ApiError("plugin.install_not_found", "The install record was cleaned up as stale while the install was running");
|
|
615
|
-
}
|
|
616
|
-
await this.d.requests.resolveByInstall(t, orgId, itemId, actor, opts);
|
|
617
|
-
await audit(t, {
|
|
618
|
-
actorAccountId: actor,
|
|
619
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
620
|
-
orgId,
|
|
621
|
-
action: "plugin.org_installed",
|
|
622
|
-
target: installId,
|
|
623
|
-
detail: {
|
|
624
|
-
itemId,
|
|
625
|
-
name: plan.name,
|
|
626
|
-
version,
|
|
627
|
-
components: done,
|
|
628
|
-
...(ctx.parent !== undefined && { dependencyOf: ctx.parent }),
|
|
629
|
-
},
|
|
630
|
-
});
|
|
631
|
-
});
|
|
724
|
+
// Skills and agent templates are platform components (plugin scope phase 2): stored once for
|
|
725
|
+
// the deployment and on in the org while the plugin is, so the install writes no org rows
|
|
726
|
+
await this.markInstalled(orgId, actor, installId, plan, done, ctx, opts);
|
|
632
727
|
return installId;
|
|
633
728
|
}
|
|
634
729
|
catch (e) {
|
|
635
730
|
const failure = e instanceof InstallFailure ? e : undefined;
|
|
636
731
|
const code = failure ? failure.code : e instanceof ApiError ? e.code : "internal";
|
|
637
732
|
const rollbackErrors = await this.rollback(orgId, actor, installId, done, opts);
|
|
638
|
-
await this.
|
|
639
|
-
await t
|
|
640
|
-
.updateTable("plugin_installs")
|
|
641
|
-
.set({ status: "failed", error: JSON.stringify({ step, code }) })
|
|
642
|
-
.where("id", "=", installId)
|
|
643
|
-
.execute();
|
|
644
|
-
await audit(t, {
|
|
645
|
-
actorAccountId: actor,
|
|
646
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
647
|
-
orgId,
|
|
648
|
-
action: "plugin.org_install_failed",
|
|
649
|
-
target: installId,
|
|
650
|
-
detail: {
|
|
651
|
-
itemId,
|
|
652
|
-
name: plan.name,
|
|
653
|
-
version,
|
|
654
|
-
step,
|
|
655
|
-
code,
|
|
656
|
-
rolledBack: done,
|
|
657
|
-
rollbackErrors,
|
|
658
|
-
...(ctx.parent !== undefined && { dependencyOf: ctx.parent }),
|
|
659
|
-
},
|
|
660
|
-
});
|
|
661
|
-
});
|
|
733
|
+
await this.markFailed(orgId, actor, installId, plan, ctx, { step, code, done, rollbackErrors }, opts);
|
|
662
734
|
throw new InstallFailure(failure ? failure.step : step, failure ? failure.cause : e, failure ? failure.dependency : [], rollbackErrors.length === 0 && (failure?.rolledBack ?? true));
|
|
663
735
|
}
|
|
664
736
|
}
|
|
737
|
+
/**
|
|
738
|
+
* The install row (role and item policy re-checked under the lock; one live install per org and
|
|
739
|
+
* item). A step of the install: committed on its own.
|
|
740
|
+
*/
|
|
741
|
+
/**
|
|
742
|
+
* Enables a plugin's extension for the org and records it as a component of the install, in one
|
|
743
|
+
* transaction (`put` joins it): "enabled before" is decided under the org row lock (already
|
|
744
|
+
* enabled: `put` writes nothing, the config is untouched, the component is recorded as not
|
|
745
|
+
* created), and the ledger row is written before the COMMIT, so no concurrent uninstall fits
|
|
746
|
+
* between enabling and recording. Used by the install and the upgrade.
|
|
747
|
+
*/
|
|
748
|
+
async enableExtension(orgId, name, input, actor, actorTokenId, opts, record) {
|
|
749
|
+
const ifDisabled = { skipped: false };
|
|
750
|
+
await this.orgConfigs.put(orgId, name, input, actor, actorTokenId, { ...opts, ifDisabled });
|
|
751
|
+
await record({
|
|
752
|
+
kind: "extension",
|
|
753
|
+
ref: name,
|
|
754
|
+
created: !ifDisabled.skipped,
|
|
755
|
+
skillVersion: null,
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
async createInstallRow(orgId, actor, plan, ctx, installId) {
|
|
759
|
+
const { itemId, version } = plan;
|
|
760
|
+
const t = this.db;
|
|
761
|
+
await lockOrgForActions(this.orgLock, orgId, actor, ctx.actions);
|
|
762
|
+
// The scope sync decided outside this lock: a person's switch-off or a scope change committed
|
|
763
|
+
// since then wins (nothing written, converged)
|
|
764
|
+
if (ctx.via === "scope" &&
|
|
765
|
+
ctx.approvedBy === undefined &&
|
|
766
|
+
!(await wantedByScope(t, orgId, itemId))) {
|
|
767
|
+
throw new ScopeNoLongerWanted(orgId, itemId);
|
|
768
|
+
}
|
|
769
|
+
if (ctx.approvedBy !== undefined) {
|
|
770
|
+
// A dependency disabled (or removed) since it was planned
|
|
771
|
+
const own = await t
|
|
772
|
+
.selectFrom("catalog_items")
|
|
773
|
+
.select(["disabled", "deleted_at"])
|
|
774
|
+
.where("id", "=", itemId)
|
|
775
|
+
.forShare()
|
|
776
|
+
.executeTakeFirst();
|
|
777
|
+
if (!own || own.deleted_at !== null) {
|
|
778
|
+
throw unresolved(plan.name, plan.version, "it was removed from the platform catalog");
|
|
779
|
+
}
|
|
780
|
+
if (own.disabled)
|
|
781
|
+
throw dependencyDisabled(plan.name);
|
|
782
|
+
}
|
|
783
|
+
await assertItemInstallable(t, orgId, itemId, ctx.approvedBy ?? itemId);
|
|
784
|
+
const live = await t
|
|
785
|
+
.selectFrom("plugin_installs")
|
|
786
|
+
.select("id")
|
|
787
|
+
.where("org_id", "=", orgId)
|
|
788
|
+
.where("item_id", "=", itemId)
|
|
789
|
+
.where("status", "<>", "failed")
|
|
790
|
+
.executeTakeFirst();
|
|
791
|
+
if (live)
|
|
792
|
+
throw alreadyInstalled();
|
|
793
|
+
try {
|
|
794
|
+
await t
|
|
795
|
+
.insertInto("plugin_installs")
|
|
796
|
+
.values({
|
|
797
|
+
id: installId,
|
|
798
|
+
org_id: orgId,
|
|
799
|
+
item_id: itemId,
|
|
800
|
+
version,
|
|
801
|
+
status: "installing",
|
|
802
|
+
installed_by: actor,
|
|
803
|
+
})
|
|
804
|
+
.execute();
|
|
805
|
+
}
|
|
806
|
+
catch (e) {
|
|
807
|
+
if (isUniqueViolation(e))
|
|
808
|
+
throw alreadyInstalled();
|
|
809
|
+
throw e;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
/** The install `installed` and its `plugin.org_installed` audit, under the org row lock (its own transaction). */
|
|
813
|
+
async markInstalled(orgId, actor, installId, plan, done, ctx, opts) {
|
|
814
|
+
const { itemId, version } = plan;
|
|
815
|
+
const t = this.db;
|
|
816
|
+
await this.orgLock.lock(orgId);
|
|
817
|
+
// The platform version current at commit (one per deployment): a platform update that
|
|
818
|
+
// committed while this install ran moved the row already, or did not see it yet
|
|
819
|
+
const updated = await t
|
|
820
|
+
.updateTable("plugin_installs")
|
|
821
|
+
.set((eb) => ({
|
|
822
|
+
status: "installed",
|
|
823
|
+
version: eb.fn.coalesce(eb
|
|
824
|
+
.selectFrom("catalog_items as i")
|
|
825
|
+
.select("i.platform_synced_version")
|
|
826
|
+
.where("i.id", "=", itemId), eb.ref("plugin_installs.version")),
|
|
827
|
+
}))
|
|
828
|
+
.where("id", "=", installId)
|
|
829
|
+
.where("status", "=", "installing")
|
|
830
|
+
.executeTakeFirst();
|
|
831
|
+
// The install row was already cleaned up as stale: do not audit plugin.org_installed, roll
|
|
832
|
+
// back
|
|
833
|
+
if (updated.numUpdatedRows === 0n) {
|
|
834
|
+
throw new ApiError("plugin.install_not_found", "The install record was cleaned up as stale while the install was running");
|
|
835
|
+
}
|
|
836
|
+
await resolveRequestsByInstall(t, orgId, itemId, actor, opts);
|
|
837
|
+
// The org switch is written with the install, in one transaction under the org lock
|
|
838
|
+
if (ctx.switchOn === true && ctx.parent === undefined) {
|
|
839
|
+
await upsertOrgSwitch(t, orgId, itemId, true, actor);
|
|
840
|
+
}
|
|
841
|
+
await audit(t, {
|
|
842
|
+
actorAccountId: actor,
|
|
843
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
844
|
+
orgId,
|
|
845
|
+
action: "plugin.org_installed",
|
|
846
|
+
target: installId,
|
|
847
|
+
detail: {
|
|
848
|
+
itemId,
|
|
849
|
+
name: plan.name,
|
|
850
|
+
version,
|
|
851
|
+
components: done,
|
|
852
|
+
...(ctx.parent !== undefined && { dependencyOf: ctx.parent }),
|
|
853
|
+
...(ctx.via !== undefined && { via: ctx.via }),
|
|
854
|
+
...opts.auditDetail,
|
|
855
|
+
},
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
/** The install `failed` with `{ step, code }` and its `plugin.org_install_failed` audit (its own transaction). */
|
|
859
|
+
async markFailed(orgId, actor, installId, plan, ctx, f, opts) {
|
|
860
|
+
const { itemId, version } = plan;
|
|
861
|
+
const { step, code, done, rollbackErrors } = f;
|
|
862
|
+
const t = this.db;
|
|
863
|
+
await t
|
|
864
|
+
.updateTable("plugin_installs")
|
|
865
|
+
.set({ status: "failed", error: JSON.stringify({ step, code }) })
|
|
866
|
+
.where("id", "=", installId)
|
|
867
|
+
.execute();
|
|
868
|
+
await audit(t, {
|
|
869
|
+
actorAccountId: actor,
|
|
870
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
871
|
+
orgId,
|
|
872
|
+
action: "plugin.org_install_failed",
|
|
873
|
+
target: installId,
|
|
874
|
+
detail: {
|
|
875
|
+
itemId,
|
|
876
|
+
name: plan.name,
|
|
877
|
+
version,
|
|
878
|
+
step,
|
|
879
|
+
code,
|
|
880
|
+
rolledBack: done,
|
|
881
|
+
rollbackErrors,
|
|
882
|
+
...(ctx.parent !== undefined && { dependencyOf: ctx.parent }),
|
|
883
|
+
...(ctx.via !== undefined && { via: ctx.via }),
|
|
884
|
+
...opts.auditDetail,
|
|
885
|
+
},
|
|
886
|
+
});
|
|
887
|
+
}
|
|
665
888
|
/**
|
|
666
889
|
* The extension to enable: the plugin's own, when it has one. Not loaded on this replica ->
|
|
667
890
|
* `catalog.not_deployed`; not yet enabled in this org while its own catalog item is disabled ->
|
|
@@ -672,11 +895,11 @@ export class PluginInstaller {
|
|
|
672
895
|
if (!manifest.extension)
|
|
673
896
|
return null;
|
|
674
897
|
const name = manifest.name;
|
|
675
|
-
if (!this.
|
|
676
|
-
throw new ApiError("catalog.not_deployed", `The extension of plugin ${name} is not
|
|
898
|
+
if (!this.registry.manifests().some((m) => m.name === name)) {
|
|
899
|
+
throw new ApiError("catalog.not_deployed", `The extension of plugin ${name} is not running on the platform (not installed, waiting for its deployment config or permission approval, disabled, or failed to load); the org cannot switch it on until it runs`);
|
|
677
900
|
}
|
|
678
|
-
const enabled = await isExtensionEnabled(this.
|
|
679
|
-
if (!enabled && (await disabledPluginItems(this.
|
|
901
|
+
const enabled = await isExtensionEnabled(this.db, orgId, name);
|
|
902
|
+
if (!enabled && (await disabledPluginItems(this.db, [name])).length > 0) {
|
|
680
903
|
throw pluginItemDisabled([name]);
|
|
681
904
|
}
|
|
682
905
|
return name;
|
|
@@ -705,46 +928,13 @@ export class PluginInstaller {
|
|
|
705
928
|
if (!c.created && c.skillVersion === null)
|
|
706
929
|
continue;
|
|
707
930
|
try {
|
|
708
|
-
const disabled =
|
|
709
|
-
await this.d.db.transaction().execute(async (t) => {
|
|
710
|
-
await lockOrg(t, orgId);
|
|
711
|
-
if (c.kind === "plugin") {
|
|
712
|
-
// A dependency install this install created: uninstalled by the usual rules
|
|
713
|
-
const sub = { removed: [], kept: [] };
|
|
714
|
-
await this.uninstallIn(t, orgId, actor, c.ref, {
|
|
715
|
-
report: sub,
|
|
716
|
-
removing: new Set([installId]),
|
|
717
|
-
from: installId,
|
|
718
|
-
authorize: false,
|
|
719
|
-
reason: "plugin_install_rollback",
|
|
720
|
-
opts,
|
|
721
|
-
});
|
|
722
|
-
disabled.push(...sub.removed.filter((r) => r.kind === "extension").map((r) => r.ref));
|
|
723
|
-
}
|
|
724
|
-
else {
|
|
725
|
-
// Another enabled extension depends on it (only it provides what that one needs in this
|
|
726
|
-
// org): kept (its component row too), so the other does not lose its dependency
|
|
727
|
-
if (c.kind === "extension" &&
|
|
728
|
-
(await this.d.orgConfigs.enabledDependents(t, orgId, c.ref)).length > 0) {
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
const removed = await this.removeComponent(t, orgId, actor, c, "plugin_install_rollback");
|
|
732
|
-
if (removed && c.kind === "extension")
|
|
733
|
-
disabled.push(c.ref);
|
|
734
|
-
}
|
|
735
|
-
await t
|
|
736
|
-
.deleteFrom("plugin_install_components")
|
|
737
|
-
.where("install_id", "=", installId)
|
|
738
|
-
.where("kind", "=", c.kind)
|
|
739
|
-
.where("ref", "=", c.ref)
|
|
740
|
-
.execute();
|
|
741
|
-
});
|
|
931
|
+
const disabled = await this.rollbackOne(orgId, actor, installId, c, opts);
|
|
742
932
|
for (const p of disabled)
|
|
743
|
-
await this.
|
|
933
|
+
await this.orgConfigs.afterDisable(orgId, p);
|
|
744
934
|
}
|
|
745
935
|
catch (e) {
|
|
746
936
|
errors.push({ kind: c.kind, ref: c.ref });
|
|
747
|
-
this.
|
|
937
|
+
this.log.warn("plugin install rollback step failed", {
|
|
748
938
|
orgId,
|
|
749
939
|
kind: c.kind,
|
|
750
940
|
ref: c.ref,
|
|
@@ -754,11 +944,53 @@ export class PluginInstaller {
|
|
|
754
944
|
}
|
|
755
945
|
return errors;
|
|
756
946
|
}
|
|
947
|
+
/**
|
|
948
|
+
* Undoes one component of a failed install and deletes its component row, under the org row lock,
|
|
949
|
+
* in a transaction of its own (committed when it returns); returns the extensions it disabled
|
|
950
|
+
* (the caller notifies them).
|
|
951
|
+
*/
|
|
952
|
+
async rollbackOne(orgId, actor, installId, c, opts) {
|
|
953
|
+
const disabled = [];
|
|
954
|
+
const t = this.db;
|
|
955
|
+
await this.orgLock.lock(orgId);
|
|
956
|
+
if (c.kind === "plugin") {
|
|
957
|
+
// A dependency install this install created: uninstalled by the usual rules
|
|
958
|
+
const sub = { removed: [], kept: [] };
|
|
959
|
+
await this.uninstallIn(orgId, actor, c.ref, {
|
|
960
|
+
report: sub,
|
|
961
|
+
removing: new Set([installId]),
|
|
962
|
+
from: installId,
|
|
963
|
+
authorize: false,
|
|
964
|
+
reason: "plugin_install_rollback",
|
|
965
|
+
opts,
|
|
966
|
+
});
|
|
967
|
+
disabled.push(...sub.removed.filter((r) => r.kind === "extension").map((r) => r.ref));
|
|
968
|
+
}
|
|
969
|
+
else {
|
|
970
|
+
// Another enabled extension depends on it (only it provides what that one needs in this
|
|
971
|
+
// org): kept (its component row too), so the other does not lose its dependency
|
|
972
|
+
if (c.kind === "extension" &&
|
|
973
|
+
(await this.orgConfigs.enabledDependents(orgId, c.ref)).length > 0) {
|
|
974
|
+
return [];
|
|
975
|
+
}
|
|
976
|
+
const removed = await this.removeComponent(orgId, actor, c, "plugin_install_rollback");
|
|
977
|
+
if (removed && c.kind === "extension")
|
|
978
|
+
disabled.push(c.ref);
|
|
979
|
+
}
|
|
980
|
+
await t
|
|
981
|
+
.deleteFrom("plugin_install_components")
|
|
982
|
+
.where("install_id", "=", installId)
|
|
983
|
+
.where("kind", "=", c.kind)
|
|
984
|
+
.where("ref", "=", c.ref)
|
|
985
|
+
.execute();
|
|
986
|
+
return disabled;
|
|
987
|
+
}
|
|
757
988
|
/** Removes one component (one already gone is no error); returns whether anything changed. */
|
|
758
|
-
async removeComponent(
|
|
989
|
+
async removeComponent(orgId, actor, c, reason) {
|
|
759
990
|
if (c.kind === "extension") {
|
|
760
|
-
return this.
|
|
991
|
+
return this.orgConfigs.disableIn(orgId, c.ref, actor, reason);
|
|
761
992
|
}
|
|
993
|
+
const t = this.db;
|
|
762
994
|
if (c.kind === "connector") {
|
|
763
995
|
const live = await t
|
|
764
996
|
.selectFrom("connectors")
|
|
@@ -769,11 +1001,18 @@ export class PluginInstaller {
|
|
|
769
1001
|
.executeTakeFirst();
|
|
770
1002
|
if (!live)
|
|
771
1003
|
return false;
|
|
772
|
-
await this.
|
|
1004
|
+
await this.connectors.removeIn(orgId, c.ref, actor, undefined, reason);
|
|
773
1005
|
return true;
|
|
774
1006
|
}
|
|
775
1007
|
if (c.kind === "plugin")
|
|
776
1008
|
return false;
|
|
1009
|
+
// A row the org promoted is the org's own shared item (ruling P3-47): an install never
|
|
1010
|
+
// removes or reverts it (P3-46 keeps plugin content from being promoted; this guards rows
|
|
1011
|
+
// recorded before that or by a legacy install)
|
|
1012
|
+
if ((c.kind === "agent_template" || c.kind === "skill") &&
|
|
1013
|
+
(await promotedOrgRow(t, orgId, c.kind, c.ref))) {
|
|
1014
|
+
return false;
|
|
1015
|
+
}
|
|
777
1016
|
if (c.kind === "agent_template") {
|
|
778
1017
|
if (c.created)
|
|
779
1018
|
return softDeleteTemplateIn(t, orgId, c.ref);
|
|
@@ -783,9 +1022,9 @@ export class PluginInstaller {
|
|
|
783
1022
|
return false;
|
|
784
1023
|
}
|
|
785
1024
|
if (c.created)
|
|
786
|
-
return this.
|
|
1025
|
+
return this.skills.softDeleteIn(orgId, c.ref, actor, reason);
|
|
787
1026
|
if (c.skillVersion !== null) {
|
|
788
|
-
return this.
|
|
1027
|
+
return this.skills.revertVersionIn(orgId, c.ref, c.skillVersion, actor, reason);
|
|
789
1028
|
}
|
|
790
1029
|
return false;
|
|
791
1030
|
}
|
|
@@ -811,35 +1050,93 @@ export class PluginInstaller {
|
|
|
811
1050
|
* (a replica crashed midway) - the last two are cleaned up as a rollback (versions added to
|
|
812
1051
|
* existing skills are reverted too). Still installing -> `plugin.install_in_progress`.
|
|
813
1052
|
*/
|
|
814
|
-
async uninstall(orgId, actor, installId, opts = {}) {
|
|
1053
|
+
async uninstall(orgId, actor, installId, opts = {}, sw) {
|
|
815
1054
|
if (!UUID_RE.test(installId))
|
|
816
1055
|
throw installNotFound();
|
|
1056
|
+
return this.writeUninstall(orgId, actor, installId, opts, sw);
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* The uninstall's one transaction; the extensions it disabled are notified once it commits. A
|
|
1060
|
+
* scope sync uninstall (`via: "scope"`) re-checks under the org row lock that the item is still
|
|
1061
|
+
* not wanted in the org and that no other live install depends on it ({@link ScopeStillWanted},
|
|
1062
|
+
* nothing written), and keeps the connectors it created as the org's own (`org_owned`).
|
|
1063
|
+
*/
|
|
1064
|
+
async writeUninstall(orgId, actor, installId, opts, sw) {
|
|
1065
|
+
const { via, ...actorOpts } = opts;
|
|
817
1066
|
const report = { removed: [], kept: [] };
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1067
|
+
let itemId;
|
|
1068
|
+
if (via === "scope") {
|
|
1069
|
+
// A person's switch-on (or a scope change) committed after the sync's decision wins
|
|
1070
|
+
await this.orgLock.lock(orgId);
|
|
1071
|
+
const row = await this.db
|
|
1072
|
+
.selectFrom("plugin_installs")
|
|
1073
|
+
.select("item_id")
|
|
1074
|
+
.where("id", "=", installId)
|
|
1075
|
+
.where("org_id", "=", orgId)
|
|
1076
|
+
.executeTakeFirst();
|
|
1077
|
+
if (row !== undefined &&
|
|
1078
|
+
((await wantedByScope(this.db, orgId, row.item_id)) ||
|
|
1079
|
+
(await this.heir(orgId, new Set([installId]), "plugin", installId)) !== undefined)) {
|
|
1080
|
+
throw new ScopeStillWanted(orgId, row.item_id);
|
|
829
1081
|
}
|
|
1082
|
+
}
|
|
1083
|
+
if (sw !== undefined) {
|
|
1084
|
+
// Switching off: the org lock first, then the preview is re-checked and the switch row is
|
|
1085
|
+
// written in this same transaction
|
|
1086
|
+
await this.orgLock.lock(orgId);
|
|
1087
|
+
const row = await this.db
|
|
1088
|
+
.selectFrom("plugin_installs")
|
|
1089
|
+
.select("item_id")
|
|
1090
|
+
.where("id", "=", installId)
|
|
1091
|
+
.where("org_id", "=", orgId)
|
|
1092
|
+
.executeTakeFirst();
|
|
1093
|
+
itemId = row?.item_id;
|
|
1094
|
+
// The item row FOR SHARE, as a switch without an uninstall takes it: an owner's delete or
|
|
1095
|
+
// transfer (FOR UPDATE) decides on who uses it
|
|
1096
|
+
if (itemId !== undefined) {
|
|
1097
|
+
await this.db
|
|
1098
|
+
.selectFrom("catalog_items")
|
|
1099
|
+
.select("id")
|
|
1100
|
+
.where("id", "=", itemId)
|
|
1101
|
+
.forShare()
|
|
1102
|
+
.executeTakeFirst();
|
|
1103
|
+
}
|
|
1104
|
+
if (sw.expectHash !== undefined && row !== undefined) {
|
|
1105
|
+
const now = uninstallPreviewHash(await this.previewUninstall(orgId, installId));
|
|
1106
|
+
if (now !== sw.expectHash) {
|
|
1107
|
+
throw new ApiError("plugin.switch_stale", "The uninstall preview changed; review it and confirm again");
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
const outcome = await this.uninstallIn(orgId, actor, installId, {
|
|
1112
|
+
report,
|
|
1113
|
+
removing: new Set(),
|
|
1114
|
+
authorize: true,
|
|
1115
|
+
opts: actorOpts,
|
|
1116
|
+
...(via !== undefined && { via }),
|
|
830
1117
|
});
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1118
|
+
if (outcome === "missing")
|
|
1119
|
+
throw installNotFound();
|
|
1120
|
+
if (outcome === "kept") {
|
|
1121
|
+
report.kept.push({ kind: "plugin", ref: installId, reason: "used_by_other_install" });
|
|
834
1122
|
}
|
|
1123
|
+
if (itemId !== undefined && outcome === "removed") {
|
|
1124
|
+
await upsertOrgSwitch(this.db, orgId, itemId, false, actor);
|
|
1125
|
+
}
|
|
1126
|
+
afterCommit(async () => {
|
|
1127
|
+
for (const r of report.removed) {
|
|
1128
|
+
if (r.kind === "extension")
|
|
1129
|
+
await this.orgConfigs.afterDisable(orgId, r.ref);
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
835
1132
|
return report;
|
|
836
1133
|
}
|
|
837
1134
|
/**
|
|
838
1135
|
* The oldest other live install (not in `removing`) that has component `kind` / `ref`, or
|
|
839
1136
|
* undefined.
|
|
840
1137
|
*/
|
|
841
|
-
async heir(
|
|
842
|
-
let q =
|
|
1138
|
+
async heir(orgId, removing, kind, ref) {
|
|
1139
|
+
let q = this.db
|
|
843
1140
|
.selectFrom("plugin_install_components as c")
|
|
844
1141
|
.innerJoin("plugin_installs as a", "a.id", "c.install_id")
|
|
845
1142
|
.select("a.id")
|
|
@@ -853,8 +1150,8 @@ export class PluginInstaller {
|
|
|
853
1150
|
return row?.id;
|
|
854
1151
|
}
|
|
855
1152
|
/** Passes ownership of a component to `heir` (its component row becomes created=true). */
|
|
856
|
-
async handOver(
|
|
857
|
-
await
|
|
1153
|
+
async handOver(heir, kind, ref) {
|
|
1154
|
+
await this.db
|
|
858
1155
|
.updateTable("plugin_install_components")
|
|
859
1156
|
.set({ created: true })
|
|
860
1157
|
.where("install_id", "=", heir)
|
|
@@ -868,7 +1165,8 @@ export class PluginInstaller {
|
|
|
868
1165
|
* outcome of the install itself is returned for the caller to report: `missing`, `kept` (another
|
|
869
1166
|
* install outside this uninstall depends on it) or `removed`.
|
|
870
1167
|
*/
|
|
871
|
-
async uninstallIn(
|
|
1168
|
+
async uninstallIn(orgId, actor, installId, ctx) {
|
|
1169
|
+
const t = this.db;
|
|
872
1170
|
const { removing } = ctx;
|
|
873
1171
|
if (removing.has(installId))
|
|
874
1172
|
return "removed";
|
|
@@ -882,7 +1180,7 @@ export class PluginInstaller {
|
|
|
882
1180
|
mine.kept.push(x);
|
|
883
1181
|
ctx.report.kept.push(x);
|
|
884
1182
|
};
|
|
885
|
-
const staleMinutes = this.
|
|
1183
|
+
const staleMinutes = this.staleInstallMinutes();
|
|
886
1184
|
if (ctx.authorize) {
|
|
887
1185
|
const target = await t
|
|
888
1186
|
.selectFrom("plugin_installs as a")
|
|
@@ -891,7 +1189,7 @@ export class PluginInstaller {
|
|
|
891
1189
|
.where("a.id", "=", installId)
|
|
892
1190
|
.where("a.org_id", "=", orgId)
|
|
893
1191
|
.executeTakeFirst();
|
|
894
|
-
await lockOrgForActions(
|
|
1192
|
+
await lockOrgForActions(this.orgLock, orgId, actor, target ? requiredActions(target.manifest) : ALL_ACTIONS);
|
|
895
1193
|
}
|
|
896
1194
|
const row = await t
|
|
897
1195
|
.selectFrom("plugin_installs as a")
|
|
@@ -912,12 +1210,17 @@ export class PluginInstaller {
|
|
|
912
1210
|
.executeTakeFirst();
|
|
913
1211
|
if (!row)
|
|
914
1212
|
return "missing";
|
|
1213
|
+
// A dependency its own scope still wants on in the org stays as a standalone install (the
|
|
1214
|
+
// dependent's component row goes with the dependent's install row)
|
|
1215
|
+
if (ctx.from !== undefined && (await wantedByScope(t, orgId, row.item_id))) {
|
|
1216
|
+
return "wanted_by_scope";
|
|
1217
|
+
}
|
|
915
1218
|
// Another install outside this uninstall depends on it: kept (a dependency uninstall hands
|
|
916
1219
|
// ownership over)
|
|
917
|
-
const user = await this.heir(
|
|
1220
|
+
const user = await this.heir(orgId, new Set([...removing, installId]), "plugin", installId);
|
|
918
1221
|
if (user !== undefined) {
|
|
919
1222
|
if (ctx.from !== undefined)
|
|
920
|
-
await this.handOver(
|
|
1223
|
+
await this.handOver(user, "plugin", installId);
|
|
921
1224
|
return "kept";
|
|
922
1225
|
}
|
|
923
1226
|
if (row.status === "uninstalling" ||
|
|
@@ -927,7 +1230,7 @@ export class PluginInstaller {
|
|
|
927
1230
|
}
|
|
928
1231
|
if (row.status === "upgrading") {
|
|
929
1232
|
// An upgrade interrupted midway (a replica crashed): undone first, back at the old version
|
|
930
|
-
const undone = await this.undoUpgradeIn(
|
|
1233
|
+
const undone = await this.undoUpgradeIn(orgId, actor, installId, journalEntries(row.upgrade), "plugin_upgrade_cleanup");
|
|
931
1234
|
for (const x of undone)
|
|
932
1235
|
addRemoved(x);
|
|
933
1236
|
}
|
|
@@ -953,7 +1256,7 @@ export class PluginInstaller {
|
|
|
953
1256
|
? 2 + extensionOrder.indexOf(c.ref)
|
|
954
1257
|
: 1000 + (c.created ? 0 : 1);
|
|
955
1258
|
comps.sort((a, b) => rank(a) - rank(b));
|
|
956
|
-
const agentRefs = await this.agentRefs(
|
|
1259
|
+
const agentRefs = await this.agentRefs(orgId);
|
|
957
1260
|
for (const c of comps) {
|
|
958
1261
|
const keep = (reason) => addKept({ kind: c.kind, ref: c.ref, reason });
|
|
959
1262
|
let created = c.created;
|
|
@@ -977,13 +1280,17 @@ export class PluginInstaller {
|
|
|
977
1280
|
created = now.created;
|
|
978
1281
|
}
|
|
979
1282
|
const comp = { kind: c.kind, ref: c.ref, created, skillVersion: c.skill_version };
|
|
1283
|
+
// Skills and agent templates of earlier installs (org copies, now linked to the platform
|
|
1284
|
+
// components, phase 2) stay: the plugin's components go off in the org with the install
|
|
1285
|
+
if ((c.kind === "skill" || c.kind === "agent_template") && !rollbackMode)
|
|
1286
|
+
continue;
|
|
980
1287
|
if (!created) {
|
|
981
1288
|
// Rollback cleanup: a version this install added to an existing skill is reverted; other
|
|
982
1289
|
// pre-existing components are kept
|
|
983
1290
|
if (rollbackMode &&
|
|
984
1291
|
(c.kind === "skill" || c.kind === "agent_template") &&
|
|
985
1292
|
c.skill_version !== null &&
|
|
986
|
-
(await this.removeComponent(
|
|
1293
|
+
(await this.removeComponent(orgId, actor, comp, "plugin_install_cleanup"))) {
|
|
987
1294
|
addRemoved({ kind: c.kind, ref: c.ref });
|
|
988
1295
|
continue;
|
|
989
1296
|
}
|
|
@@ -991,15 +1298,23 @@ export class PluginInstaller {
|
|
|
991
1298
|
continue;
|
|
992
1299
|
}
|
|
993
1300
|
if (c.kind === "plugin") {
|
|
994
|
-
const outcome = await this.uninstallIn(
|
|
1301
|
+
const outcome = await this.uninstallIn(orgId, actor, c.ref, { ...ctx, from: installId });
|
|
995
1302
|
if (outcome === "removed")
|
|
996
1303
|
addRemoved({ kind: "plugin", ref: c.ref });
|
|
997
1304
|
else if (outcome === "kept")
|
|
998
1305
|
keep("used_by_other_install");
|
|
1306
|
+
else if (outcome === "wanted_by_scope")
|
|
1307
|
+
keep("wanted_by_scope");
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
// A scope sync uninstall leaves the connectors to the org (spec §5 rule 8): the component row
|
|
1311
|
+
// goes with the install row, so nothing removes them later
|
|
1312
|
+
if (c.kind === "connector" && ctx.via === "scope" && !rollbackMode) {
|
|
1313
|
+
keep("org_owned");
|
|
999
1314
|
continue;
|
|
1000
1315
|
}
|
|
1001
1316
|
const reason = rollbackMode ? "plugin_install_cleanup" : (ctx.reason ?? "plugin_uninstall");
|
|
1002
|
-
const outcome = await this.decideRemovalIn(
|
|
1317
|
+
const outcome = await this.decideRemovalIn(orgId, actor, comp, removing, agentRefs, reason);
|
|
1003
1318
|
if (outcome === "removed")
|
|
1004
1319
|
addRemoved({ kind: c.kind, ref: c.ref });
|
|
1005
1320
|
else if (outcome !== "gone")
|
|
@@ -1020,6 +1335,8 @@ export class PluginInstaller {
|
|
|
1020
1335
|
removed: mine.removed,
|
|
1021
1336
|
kept: mine.kept,
|
|
1022
1337
|
...(ctx.from !== undefined && { dependencyOf: ctx.from }),
|
|
1338
|
+
...(ctx.via !== undefined && { via: ctx.via }),
|
|
1339
|
+
...ctx.opts.auditDetail,
|
|
1023
1340
|
},
|
|
1024
1341
|
});
|
|
1025
1342
|
return "removed";
|
|
@@ -1034,7 +1351,7 @@ export class PluginInstaller {
|
|
|
1034
1351
|
* (`used_by_plugins`); otherwise removed (`removed`, or `gone` when it no longer existed). Used
|
|
1035
1352
|
* by uninstall and by an upgrade's removals.
|
|
1036
1353
|
*/
|
|
1037
|
-
async decideRemovalIn(
|
|
1354
|
+
async decideRemovalIn(orgId, actor, c, removing, agentRefs, reason) {
|
|
1038
1355
|
if (c.kind === "skill" && agentRefs.skills.has(c.ref))
|
|
1039
1356
|
return "used_by_agents";
|
|
1040
1357
|
if (c.kind === "agent_template" && agentRefs.templates.has(c.ref))
|
|
@@ -1042,16 +1359,16 @@ export class PluginInstaller {
|
|
|
1042
1359
|
if (c.kind === "connector" && agentRefs.connectors.has(c.ref))
|
|
1043
1360
|
return "used_by_agents";
|
|
1044
1361
|
if (c.kind !== "connector") {
|
|
1045
|
-
const heir = await this.heir(
|
|
1362
|
+
const heir = await this.heir(orgId, removing, c.kind, c.ref);
|
|
1046
1363
|
if (heir !== undefined) {
|
|
1047
|
-
await this.handOver(
|
|
1364
|
+
await this.handOver(heir, c.kind, c.ref);
|
|
1048
1365
|
return "used_by_other_install";
|
|
1049
1366
|
}
|
|
1050
1367
|
}
|
|
1051
1368
|
if (c.kind === "extension") {
|
|
1052
1369
|
const kinds = this.connectorKindsOf(c.ref);
|
|
1053
1370
|
if (kinds.length > 0) {
|
|
1054
|
-
const used = await
|
|
1371
|
+
const used = await this.db
|
|
1055
1372
|
.selectFrom("connectors")
|
|
1056
1373
|
.select("id")
|
|
1057
1374
|
.where("org_id", "=", orgId)
|
|
@@ -1061,21 +1378,21 @@ export class PluginInstaller {
|
|
|
1061
1378
|
if (used)
|
|
1062
1379
|
return "used_by_connectors";
|
|
1063
1380
|
}
|
|
1064
|
-
if ((await this.
|
|
1381
|
+
if ((await this.orgConfigs.enabledDependents(orgId, c.ref)).length > 0) {
|
|
1065
1382
|
return "used_by_plugins";
|
|
1066
1383
|
}
|
|
1067
1384
|
}
|
|
1068
|
-
return (await this.removeComponent(
|
|
1385
|
+
return (await this.removeComponent(orgId, actor, c, reason)) ? "removed" : "gone";
|
|
1069
1386
|
}
|
|
1070
1387
|
/** The order extensions are uninstalled in: the reverse of the install (requires) order; extensions not loaded on this replica last. */
|
|
1071
1388
|
uninstallExtensionOrder(refs) {
|
|
1072
|
-
const loaded = new Map(this.
|
|
1389
|
+
const loaded = new Map(this.registry.manifests().map((m) => [m.name, m]));
|
|
1073
1390
|
const known = refs.filter((r) => loaded.has(r)).map((r) => loaded.get(r));
|
|
1074
1391
|
return [...orderByRequires(known).reverse(), ...refs.filter((r) => !loaded.has(r))];
|
|
1075
1392
|
}
|
|
1076
1393
|
/** The org's plugin installs (failed ones included), newest first; `installId` picks one. */
|
|
1077
1394
|
async list(orgId, installId) {
|
|
1078
|
-
let q = this.
|
|
1395
|
+
let q = this.db
|
|
1079
1396
|
.selectFrom("plugin_installs as a")
|
|
1080
1397
|
.innerJoin("catalog_items as i", "i.id", "a.item_id")
|
|
1081
1398
|
.select([
|
|
@@ -1094,8 +1411,7 @@ export class PluginInstaller {
|
|
|
1094
1411
|
const rows = await q.orderBy("a.installed_at", "desc").orderBy("a.id").execute();
|
|
1095
1412
|
if (rows.length === 0)
|
|
1096
1413
|
return [];
|
|
1097
|
-
const
|
|
1098
|
-
const comps = await this.d.db
|
|
1414
|
+
const comps = await this.db
|
|
1099
1415
|
.selectFrom("plugin_install_components")
|
|
1100
1416
|
.select(["install_id", "kind", "ref", "created", "skill_version", "dropped"])
|
|
1101
1417
|
.where("install_id", "in", rows.map((r) => r.id))
|
|
@@ -1118,8 +1434,8 @@ export class PluginInstaller {
|
|
|
1118
1434
|
skillVersion: c.skill_version,
|
|
1119
1435
|
dropped: c.dropped,
|
|
1120
1436
|
})),
|
|
1121
|
-
upgradeAvailable:
|
|
1122
|
-
deploymentPending:
|
|
1437
|
+
upgradeAvailable: null,
|
|
1438
|
+
deploymentPending: false,
|
|
1123
1439
|
}));
|
|
1124
1440
|
}
|
|
1125
1441
|
/**
|
|
@@ -1131,9 +1447,9 @@ export class PluginInstaller {
|
|
|
1131
1447
|
* extension among them needs `afterDisable` once committed). Used when an upgrade fails and when
|
|
1132
1448
|
* an interrupted one is cleaned up.
|
|
1133
1449
|
*/
|
|
1134
|
-
async undoUpgradeIn(
|
|
1450
|
+
async undoUpgradeIn(orgId, actor, installId, steps, reason) {
|
|
1135
1451
|
const removed = [];
|
|
1136
|
-
const dropRow = (kind, ref) =>
|
|
1452
|
+
const dropRow = (kind, ref) => this.db
|
|
1137
1453
|
.deleteFrom("plugin_install_components")
|
|
1138
1454
|
.where("install_id", "=", installId)
|
|
1139
1455
|
.where("kind", "=", kind)
|
|
@@ -1141,11 +1457,11 @@ export class PluginInstaller {
|
|
|
1141
1457
|
.execute();
|
|
1142
1458
|
for (const s of [...steps].reverse()) {
|
|
1143
1459
|
if (s.op === "skill_version") {
|
|
1144
|
-
await this.
|
|
1460
|
+
await this.skills.revertVersionIn(orgId, s.ref, s.version, actor, reason);
|
|
1145
1461
|
continue;
|
|
1146
1462
|
}
|
|
1147
1463
|
if (s.op === "template_version") {
|
|
1148
|
-
await revertTemplateVersionIn(
|
|
1464
|
+
await revertTemplateVersionIn(this.db, orgId, s.ref, s.version);
|
|
1149
1465
|
continue;
|
|
1150
1466
|
}
|
|
1151
1467
|
if (s.op === "recorded") {
|
|
@@ -1155,7 +1471,7 @@ export class PluginInstaller {
|
|
|
1155
1471
|
if (s.kind === "plugin") {
|
|
1156
1472
|
const sub = { removed: [], kept: [] };
|
|
1157
1473
|
await dropRow(s.kind, s.ref);
|
|
1158
|
-
const outcome = await this.uninstallIn(
|
|
1474
|
+
const outcome = await this.uninstallIn(orgId, actor, s.ref, {
|
|
1159
1475
|
report: sub,
|
|
1160
1476
|
removing: new Set([installId]),
|
|
1161
1477
|
from: installId,
|
|
@@ -1169,59 +1485,494 @@ export class PluginInstaller {
|
|
|
1169
1485
|
continue;
|
|
1170
1486
|
}
|
|
1171
1487
|
if (s.kind === "extension" &&
|
|
1172
|
-
(await this.
|
|
1488
|
+
(await this.orgConfigs.enabledDependents(orgId, s.ref)).length > 0) {
|
|
1173
1489
|
// Another enabled extension needs it: kept, and stays this install's component
|
|
1174
1490
|
continue;
|
|
1175
1491
|
}
|
|
1176
1492
|
const c = { kind: s.kind, ref: s.ref, created: true, skillVersion: null };
|
|
1177
|
-
if (await this.removeComponent(
|
|
1493
|
+
if (await this.removeComponent(orgId, actor, c, reason)) {
|
|
1178
1494
|
removed.push({ kind: s.kind, ref: s.ref });
|
|
1179
1495
|
}
|
|
1180
1496
|
await dropRow(s.kind, s.ref);
|
|
1181
1497
|
}
|
|
1182
1498
|
return removed;
|
|
1183
1499
|
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Installs the dependencies an installed plugin's version declares and the org lacks (rule 9),
|
|
1502
|
+
* as the kernel (actor null): a platform update can add one. Each is recorded on the install
|
|
1503
|
+
* as a `plugin` component (created when this installed it, so an uninstall takes it along). One
|
|
1504
|
+
* that needs the org's input (connector templates) is left out and its name returned. A
|
|
1505
|
+
* dependency already installed in the org is recorded as it is (created false).
|
|
1506
|
+
*/
|
|
1507
|
+
async addMissingDependencies(orgId, installId) {
|
|
1508
|
+
const row = await this.db
|
|
1509
|
+
.selectFrom("plugin_installs as a")
|
|
1510
|
+
.innerJoin("catalog_item_versions as v", (j) => j.onRef("v.item_id", "=", "a.item_id").onRef("v.version", "=", "a.version"))
|
|
1511
|
+
.select(["a.item_id", "a.status", "v.manifest"])
|
|
1512
|
+
.where("a.id", "=", installId)
|
|
1513
|
+
.where("a.org_id", "=", orgId)
|
|
1514
|
+
.executeTakeFirst();
|
|
1515
|
+
if (row?.status !== "installed")
|
|
1516
|
+
return [];
|
|
1517
|
+
const record = async (c) => {
|
|
1518
|
+
await this.db
|
|
1519
|
+
.insertInto("plugin_install_components")
|
|
1520
|
+
.values({
|
|
1521
|
+
install_id: installId,
|
|
1522
|
+
kind: c.kind,
|
|
1523
|
+
ref: c.ref,
|
|
1524
|
+
created: c.created,
|
|
1525
|
+
skill_version: null,
|
|
1526
|
+
})
|
|
1527
|
+
.onConflict((oc) => oc.columns(["install_id", "kind", "ref"]).doNothing())
|
|
1528
|
+
.execute();
|
|
1529
|
+
};
|
|
1530
|
+
const needsInput = [];
|
|
1531
|
+
for (const dep of await resolveDependencies(this.db, row.manifest)) {
|
|
1532
|
+
if ((await this.recordDependency(orgId, dep, record)) !== undefined)
|
|
1533
|
+
continue;
|
|
1534
|
+
let plan;
|
|
1535
|
+
try {
|
|
1536
|
+
plan = await this.plan(orgId, null, dep.itemId, dep.version, {}, "", row.item_id);
|
|
1537
|
+
}
|
|
1538
|
+
catch (e) {
|
|
1539
|
+
if (e instanceof NeedsOrgInput) {
|
|
1540
|
+
needsInput.push(dep.name);
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
throw e;
|
|
1544
|
+
}
|
|
1545
|
+
const child = await this.execute(orgId, null, plan, {}, {
|
|
1546
|
+
actions: requiredActions(plan.manifest),
|
|
1547
|
+
approvedBy: row.item_id,
|
|
1548
|
+
parent: installId,
|
|
1549
|
+
via: "scope",
|
|
1550
|
+
});
|
|
1551
|
+
await this.recordDependency(orgId, dep, record, child);
|
|
1552
|
+
}
|
|
1553
|
+
return needsInput;
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* The connector templates of an installed plugin that are on in the org (ruling P2-6) and have
|
|
1557
|
+
* no live connector there: made from the platform template (`platform_template_id`) or recorded
|
|
1558
|
+
* on the install (`template_id`). The org's plugin is `needs_config` while any is missing (ruling
|
|
1559
|
+
* P2-10). Empty for a plugin not installed.
|
|
1560
|
+
*/
|
|
1561
|
+
async missingConnectors(orgId, itemId) {
|
|
1562
|
+
const a = await this.db
|
|
1563
|
+
.selectFrom("plugin_installs as a")
|
|
1564
|
+
.innerJoin("catalog_item_versions as v", (j) => j.onRef("v.item_id", "=", "a.item_id").onRef("v.version", "=", "a.version"))
|
|
1565
|
+
.select(["a.id", "a.version", "v.manifest", "v.object_prefix", "v.files"])
|
|
1566
|
+
.where("a.org_id", "=", orgId)
|
|
1567
|
+
.where("a.item_id", "=", itemId)
|
|
1568
|
+
.where("a.status", "=", "installed")
|
|
1569
|
+
.executeTakeFirst();
|
|
1570
|
+
if (!a)
|
|
1571
|
+
return undefined;
|
|
1572
|
+
if ((a.manifest.connectorTemplates ?? []).length === 0) {
|
|
1573
|
+
return { installId: a.id, version: a.version, templates: [] };
|
|
1574
|
+
}
|
|
1575
|
+
const all = await readCatalogTemplates(this.storage, a);
|
|
1576
|
+
const on = await connectorTemplatesOn(this.db, orgId, itemId, all.map((t) => t.id));
|
|
1577
|
+
const made = new Set((await this.db
|
|
1578
|
+
.selectFrom("connectors as c")
|
|
1579
|
+
.innerJoin("platform_connector_templates as p", "p.id", "c.platform_template_id")
|
|
1580
|
+
.select("p.template_id")
|
|
1581
|
+
.where("c.org_id", "=", orgId)
|
|
1582
|
+
.where("c.deleted_at", "is", null)
|
|
1583
|
+
.where("p.catalog_item_id", "=", itemId)
|
|
1584
|
+
.execute()).map((r) => r.template_id));
|
|
1585
|
+
const recorded = await this.db
|
|
1586
|
+
.selectFrom("plugin_install_components as l")
|
|
1587
|
+
.innerJoin("connectors as c", (j) => j.on(sql `c.id::text`, "=", sql `l.ref`))
|
|
1588
|
+
.select("l.template_id")
|
|
1589
|
+
.where("l.install_id", "=", a.id)
|
|
1590
|
+
.where("l.kind", "=", "connector")
|
|
1591
|
+
.where("c.deleted_at", "is", null)
|
|
1592
|
+
.execute();
|
|
1593
|
+
for (const r of recorded)
|
|
1594
|
+
if (r.template_id !== null)
|
|
1595
|
+
made.add(r.template_id);
|
|
1596
|
+
return {
|
|
1597
|
+
installId: a.id,
|
|
1598
|
+
version: a.version,
|
|
1599
|
+
templates: all.filter((t) => on.has(t.id) && !made.has(t.id)),
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* Creates the connectors an installed plugin is missing (ruling P2-10, `POST …/catalog/:itemId/
|
|
1604
|
+
* connectors`): `input.connectors` names some of {@link missingConnectors}' templates with the
|
|
1605
|
+
* same input as an install (endpoint, credential or OAuth client); each is created as at install
|
|
1606
|
+
* and recorded on the install. Returns the created connectors by template.
|
|
1607
|
+
*/
|
|
1608
|
+
async configureConnectors(orgId, actor, itemId, input, opts = {}) {
|
|
1609
|
+
if (!UUID_RE.test(itemId))
|
|
1610
|
+
throw installNotFound();
|
|
1611
|
+
const missing = await this.missingConnectors(orgId, itemId);
|
|
1612
|
+
if (!missing)
|
|
1613
|
+
throw installNotFound();
|
|
1614
|
+
const keys = Object.keys(input.connectors ?? {});
|
|
1615
|
+
if (keys.length === 0) {
|
|
1616
|
+
throw new ApiError("validation_failed", "Request validation failed", [
|
|
1617
|
+
{ path: "connectors", message: "Give the input of at least one missing connector" },
|
|
1618
|
+
]);
|
|
1619
|
+
}
|
|
1620
|
+
for (const k of keys) {
|
|
1621
|
+
if (!missing.templates.some((t) => t.id === k)) {
|
|
1622
|
+
throw new ApiError("validation_failed", "Request validation failed", [
|
|
1623
|
+
{
|
|
1624
|
+
path: `connectors.${k}`,
|
|
1625
|
+
message: "No connector of this template is missing in this organization",
|
|
1626
|
+
},
|
|
1627
|
+
]);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
const item = await this.db
|
|
1631
|
+
.selectFrom("catalog_items")
|
|
1632
|
+
.select("name")
|
|
1633
|
+
.where("id", "=", itemId)
|
|
1634
|
+
.executeTakeFirstOrThrow();
|
|
1635
|
+
const plans = missing.templates
|
|
1636
|
+
.filter((t) => keys.includes(t.id))
|
|
1637
|
+
.map((t) => ({
|
|
1638
|
+
id: t.id,
|
|
1639
|
+
ci: this.planConnector(actor, { itemId, version: missing.version, name: item.name }, t, input, "", undefined),
|
|
1640
|
+
}));
|
|
1641
|
+
const out = [];
|
|
1642
|
+
for (const p of plans) {
|
|
1643
|
+
const r = await this.connectors.create(orgId, actor, p.ci, opts.actorTokenId);
|
|
1644
|
+
await this.recordConnector(missing.installId, r.connector.id, p.id);
|
|
1645
|
+
out.push({ templateId: p.id, connectorId: r.connector.id });
|
|
1646
|
+
}
|
|
1647
|
+
return out;
|
|
1648
|
+
}
|
|
1649
|
+
/** A configured connector's ledger row (its own transaction). */
|
|
1650
|
+
async recordConnector(installId, ref, templateId) {
|
|
1651
|
+
await this.db
|
|
1652
|
+
.insertInto("plugin_install_components")
|
|
1653
|
+
.values({
|
|
1654
|
+
install_id: installId,
|
|
1655
|
+
kind: "connector",
|
|
1656
|
+
ref,
|
|
1657
|
+
created: true,
|
|
1658
|
+
skill_version: null,
|
|
1659
|
+
template_id: templateId,
|
|
1660
|
+
})
|
|
1661
|
+
.onConflict((oc) => oc.columns(["install_id", "kind", "ref"]).doNothing())
|
|
1662
|
+
.execute();
|
|
1663
|
+
}
|
|
1664
|
+
/**
|
|
1665
|
+
* One more connector from a platform connector template on in the org (rulings P4-7, P4-T6-8;
|
|
1666
|
+
* `POST …/connector-templates/:templateId/connectors`): `templateId` is the platform connector
|
|
1667
|
+
* template's id; `config` is an install's connector input (endpoint, credential or OAuth client,
|
|
1668
|
+
* slug) and `name` its name. Without a slug the name and slug default to the first free ones,
|
|
1669
|
+
* chosen by the create under the org lock after its outbound calls
|
|
1670
|
+
* (`CreateConnectorInput.slugDefault`); only a given slug answers 409 `connector.slug_taken`. Created as at install ({@link planConnector}, then
|
|
1671
|
+
* `ConnectorsService.create`, which checks the slug before any outbound call and re-checks it,
|
|
1672
|
+
* `connectors.manage`, the item and the template being on under the org lock), linked to the
|
|
1673
|
+
* template, and recorded on the plugin's live install in the org when there is one. A template
|
|
1674
|
+
* that is missing, deleted or not offered to the org -> 404 `component.not_found`; offered but
|
|
1675
|
+
* off there (its plugin not installed, or switched off) -> 409 `component.off`; input errors ->
|
|
1676
|
+
* 400 `validation_failed` at `config.<field>`.
|
|
1677
|
+
*/
|
|
1678
|
+
async addTemplateConnector(orgId, actor, templateId, input, opts = {}) {
|
|
1679
|
+
const notFound = () => new ApiError("component.not_found", "The connector template does not exist or is not available in this organization");
|
|
1680
|
+
if (!UUID_RE.test(templateId))
|
|
1681
|
+
throw notFound();
|
|
1682
|
+
// read here to fail early, and again under the org lock by the create (`mustBeOn`)
|
|
1683
|
+
const state = await connectorTemplateState(this.db, orgId, templateId);
|
|
1684
|
+
if (state === "absent")
|
|
1685
|
+
throw notFound();
|
|
1686
|
+
if (state === "off") {
|
|
1687
|
+
throw new ApiError("component.off", "This connector template is off in this organization; switch it (or its plugin) on first");
|
|
1688
|
+
}
|
|
1689
|
+
const row = await this.db
|
|
1690
|
+
.selectFrom("platform_connector_templates as t")
|
|
1691
|
+
.innerJoin("catalog_items as i", "i.id", "t.catalog_item_id")
|
|
1692
|
+
.leftJoin("plugin_installs as a", (j) => j
|
|
1693
|
+
.onRef("a.item_id", "=", "t.catalog_item_id")
|
|
1694
|
+
.on("a.org_id", "=", orgId)
|
|
1695
|
+
.on("a.status", "=", "installed"))
|
|
1696
|
+
.select([
|
|
1697
|
+
"t.template_id",
|
|
1698
|
+
"t.catalog_item_id",
|
|
1699
|
+
"t.file",
|
|
1700
|
+
"i.name",
|
|
1701
|
+
"i.latest_version",
|
|
1702
|
+
"a.version",
|
|
1703
|
+
])
|
|
1704
|
+
.where("t.id", "=", templateId)
|
|
1705
|
+
.executeTakeFirstOrThrow();
|
|
1706
|
+
const ct = { id: row.template_id, file: row.file };
|
|
1707
|
+
const at = `connectors.${ct.id}`;
|
|
1708
|
+
// the paths of an install's input and of the create, under `config` here (`name` stays)
|
|
1709
|
+
const rebase = (e) => {
|
|
1710
|
+
if (!(e instanceof ApiError) || e.code !== "validation_failed" || !e.details)
|
|
1711
|
+
return e;
|
|
1712
|
+
return new ApiError(e.code, e.message, e.details.map((d) => {
|
|
1713
|
+
const path = d.path;
|
|
1714
|
+
if (typeof path !== "string")
|
|
1715
|
+
return d;
|
|
1716
|
+
const rest = path === at || path.startsWith(`${at}.`) ? path.slice(at.length + 1) : path;
|
|
1717
|
+
if (!/^(slug|credential|endpoint|client)(\.|$)/.test(rest)) {
|
|
1718
|
+
return rest === path ? d : { ...d, path: rest };
|
|
1719
|
+
}
|
|
1720
|
+
return { ...d, path: `config.${rest}` };
|
|
1721
|
+
}));
|
|
1722
|
+
};
|
|
1723
|
+
const display = ct.file.displayName?.en ?? ct.id;
|
|
1724
|
+
// a slug given by the caller is theirs (409 when taken); otherwise the create picks the first
|
|
1725
|
+
// free default under the org lock, after its outbound calls (no retry repeats them)
|
|
1726
|
+
const defaulted = input.config.slug === undefined;
|
|
1727
|
+
let ci;
|
|
1728
|
+
try {
|
|
1729
|
+
ci = this.planConnector(actor, { itemId: row.catalog_item_id, version: row.version ?? row.latest_version, name: row.name }, ct, {
|
|
1730
|
+
connectors: {
|
|
1731
|
+
[ct.id]: { ...input.config, ...(input.name !== undefined && { name: input.name }) },
|
|
1732
|
+
},
|
|
1733
|
+
}, "", undefined);
|
|
1734
|
+
}
|
|
1735
|
+
catch (e) {
|
|
1736
|
+
throw rebase(e);
|
|
1737
|
+
}
|
|
1738
|
+
ci = {
|
|
1739
|
+
...ci,
|
|
1740
|
+
template: ci.template && { ...ci.template, mustBeOn: true },
|
|
1741
|
+
...(defaulted && {
|
|
1742
|
+
slugDefault: { display, ...(input.name !== undefined && { name: input.name }) },
|
|
1743
|
+
}),
|
|
1744
|
+
};
|
|
1745
|
+
try {
|
|
1746
|
+
const r = await this.connectors.create(orgId, actor, ci, opts.actorTokenId);
|
|
1747
|
+
await this.recordOnLiveInstall(orgId, row.catalog_item_id, r.connector.id, ct.id);
|
|
1748
|
+
return r;
|
|
1749
|
+
}
|
|
1750
|
+
catch (e) {
|
|
1751
|
+
throw rebase(e);
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Records a connector made from a plugin's template on the org's live install of that plugin,
|
|
1756
|
+
* when there is one, under the org lock (so an uninstall in between is seen).
|
|
1757
|
+
*/
|
|
1758
|
+
async recordOnLiveInstall(orgId, itemId, connectorId, templateId) {
|
|
1759
|
+
await this.orgLock.lock(orgId);
|
|
1760
|
+
const install = await this.db
|
|
1761
|
+
.selectFrom("plugin_installs")
|
|
1762
|
+
.select("id")
|
|
1763
|
+
.where("org_id", "=", orgId)
|
|
1764
|
+
.where("item_id", "=", itemId)
|
|
1765
|
+
.where("status", "=", "installed")
|
|
1766
|
+
.executeTakeFirst();
|
|
1767
|
+
if (!install)
|
|
1768
|
+
return;
|
|
1769
|
+
await this.db
|
|
1770
|
+
.insertInto("plugin_install_components")
|
|
1771
|
+
.values({
|
|
1772
|
+
install_id: install.id,
|
|
1773
|
+
kind: "connector",
|
|
1774
|
+
ref: connectorId,
|
|
1775
|
+
created: true,
|
|
1776
|
+
skill_version: null,
|
|
1777
|
+
template_id: templateId,
|
|
1778
|
+
})
|
|
1779
|
+
.onConflict((oc) => oc.columns(["install_id", "kind", "ref"]).doNothing())
|
|
1780
|
+
.execute();
|
|
1781
|
+
}
|
|
1184
1782
|
/** The connector kinds an extension provides (the `connector@1` implementations loaded on this replica). */
|
|
1185
1783
|
connectorKindsOf(plugin) {
|
|
1186
|
-
return this.
|
|
1784
|
+
return this.registry
|
|
1187
1785
|
.list("connector")
|
|
1188
1786
|
.filter((e) => e.plugin === plugin)
|
|
1189
1787
|
.map((e) => e.impl?.kind)
|
|
1190
1788
|
.filter((k) => typeof k === "string");
|
|
1191
1789
|
}
|
|
1192
1790
|
/**
|
|
1193
|
-
* The
|
|
1194
|
-
*
|
|
1791
|
+
* The uninstall preview of an install (see {@link UninstallPreview}); the real uninstall may keep
|
|
1792
|
+
* more (another install using a component, a connector still using an extension). The plugin's
|
|
1793
|
+
* skills and agent templates are platform components (phase 2): the ones on in the org through
|
|
1794
|
+
* the plugin (`follow`) go off with it, so the agents using them (by the platform id or an
|
|
1795
|
+
* unpinned org copy linked to it) are listed, also for the dependency installs it created that
|
|
1796
|
+
* go with it; ledger rows of earlier installs' org copies are not removed and not listed (an
|
|
1797
|
+
* uninstall keeps legacy copies, like the platform update keeps copies of removed components).
|
|
1195
1798
|
*/
|
|
1196
|
-
async
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1799
|
+
async previewUninstall(orgId, installId) {
|
|
1800
|
+
if (!UUID_RE.test(installId))
|
|
1801
|
+
throw installNotFound();
|
|
1802
|
+
const t = this.db;
|
|
1803
|
+
const row = await t
|
|
1804
|
+
.selectFrom("plugin_installs as a")
|
|
1805
|
+
.innerJoin("catalog_items as i", "i.id", "a.item_id")
|
|
1806
|
+
.select(["a.id", "a.item_id", "a.version", "i.name"])
|
|
1807
|
+
.where("a.id", "=", installId)
|
|
1201
1808
|
.where("a.org_id", "=", orgId)
|
|
1202
|
-
.
|
|
1809
|
+
.executeTakeFirst();
|
|
1810
|
+
if (!row)
|
|
1811
|
+
throw installNotFound();
|
|
1812
|
+
const ledger = (id) => t
|
|
1813
|
+
.selectFrom("plugin_install_components")
|
|
1814
|
+
.select(["kind", "ref", "created"])
|
|
1815
|
+
.where("install_id", "=", id)
|
|
1816
|
+
.orderBy("kind")
|
|
1817
|
+
.orderBy("ref")
|
|
1203
1818
|
.execute();
|
|
1204
|
-
const
|
|
1205
|
-
const
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1819
|
+
const comps = (await ledger(installId)).filter((c) => c.kind !== "skill" && c.kind !== "agent_template");
|
|
1820
|
+
const agents = await agentDefinitionRefs(t, orgId);
|
|
1821
|
+
const used = new Map();
|
|
1822
|
+
const use = (a, kind, ref) => {
|
|
1823
|
+
const e = used.get(a.id) ?? { id: a.id, name: a.name, uses: [] };
|
|
1824
|
+
if (!e.uses.some((u) => u.kind === kind && u.ref === ref))
|
|
1825
|
+
e.uses.push({ kind, ref });
|
|
1826
|
+
used.set(a.id, e);
|
|
1827
|
+
};
|
|
1828
|
+
const kept = [];
|
|
1829
|
+
/**
|
|
1830
|
+
* The agents using what goes with an install: connectors it created (they stay, kept for the
|
|
1831
|
+
* agents) and the plugin's platform skills and agent templates on in the org through it
|
|
1832
|
+
* (`follow`; by the platform id or an unpinned org copy linked to it). Dependency installs it
|
|
1833
|
+
* created go with it unless their own scope wants them (Task 7: their components count too).
|
|
1834
|
+
*/
|
|
1835
|
+
const visit = async (itemId, rows, top, seen) => {
|
|
1836
|
+
for (const c of rows) {
|
|
1837
|
+
if (!c.created) {
|
|
1838
|
+
if (top)
|
|
1839
|
+
kept.push({ kind: c.kind, ref: c.ref, reason: "pre_existing" });
|
|
1840
|
+
continue;
|
|
1841
|
+
}
|
|
1842
|
+
if (c.kind === "plugin") {
|
|
1843
|
+
const dep = await t
|
|
1844
|
+
.selectFrom("plugin_installs")
|
|
1845
|
+
.select("item_id")
|
|
1846
|
+
.where("id", "=", c.ref)
|
|
1847
|
+
.where("org_id", "=", orgId)
|
|
1848
|
+
.executeTakeFirst();
|
|
1849
|
+
if (!dep)
|
|
1850
|
+
continue;
|
|
1851
|
+
if (await wantedByScope(t, orgId, dep.item_id)) {
|
|
1852
|
+
if (top)
|
|
1853
|
+
kept.push({ kind: c.kind, ref: c.ref, reason: "wanted_by_scope" });
|
|
1854
|
+
continue;
|
|
1855
|
+
}
|
|
1856
|
+
if (seen.has(c.ref))
|
|
1857
|
+
continue;
|
|
1858
|
+
seen.add(c.ref);
|
|
1859
|
+
const sub = (await ledger(c.ref)).filter((x) => x.kind !== "skill" && x.kind !== "agent_template");
|
|
1860
|
+
await visit(dep.item_id, sub, false, seen);
|
|
1861
|
+
continue;
|
|
1862
|
+
}
|
|
1863
|
+
if (c.kind !== "connector")
|
|
1864
|
+
continue;
|
|
1865
|
+
const users = agents.filter((a) => a.connectors.has(c.ref));
|
|
1866
|
+
if (users.length === 0)
|
|
1867
|
+
continue;
|
|
1868
|
+
if (top)
|
|
1869
|
+
kept.push({ kind: c.kind, ref: c.ref, reason: "used_by_agents" });
|
|
1870
|
+
for (const a of users)
|
|
1871
|
+
use(a, c.kind, c.ref);
|
|
1872
|
+
}
|
|
1873
|
+
for (const kind of ["skill", "agent_template"]) {
|
|
1874
|
+
const platform = await loadComponents(t, kind, { itemId });
|
|
1875
|
+
const st = await loadScopeState(t, kind, platform);
|
|
1876
|
+
const off = platform.filter((c) => c.scopeMode === "follow" &&
|
|
1877
|
+
componentOn(c, pluginFactsOf(st, c.itemId, orgId), listedIn(st, c.id, orgId), switchOf(st, c.id, orgId)));
|
|
1878
|
+
const refs = await referenceIds(t, orgId, kind, off.map((c) => c.id));
|
|
1879
|
+
for (const a of agents) {
|
|
1880
|
+
for (const ref of kind === "skill" ? a.skills : a.templates) {
|
|
1881
|
+
if (refs.has(ref))
|
|
1882
|
+
use(a, kind, ref);
|
|
1883
|
+
}
|
|
1213
1884
|
}
|
|
1214
1885
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1886
|
+
};
|
|
1887
|
+
await visit(row.item_id, comps, true, new Set([installId]));
|
|
1888
|
+
return {
|
|
1889
|
+
installId,
|
|
1890
|
+
name: row.name,
|
|
1891
|
+
version: row.version,
|
|
1892
|
+
components: comps.map((c) => ({ kind: c.kind, ref: c.ref, created: c.created })),
|
|
1893
|
+
kept,
|
|
1894
|
+
agents: [...used.values()]
|
|
1895
|
+
.map((a) => ({ ...a, uses: a.uses.sort((x, y) => x.ref.localeCompare(y.ref)) }))
|
|
1896
|
+
.sort((x, y) => x.id.localeCompare(y.id)),
|
|
1897
|
+
};
|
|
1223
1898
|
}
|
|
1224
|
-
|
|
1899
|
+
/**
|
|
1900
|
+
* The connectors, skills (selected, pinned, or in an inline sub-agent template) and agent
|
|
1901
|
+
* templates (`subagents.templates`) referenced by the current definitions of the org's live
|
|
1902
|
+
* agents.
|
|
1903
|
+
*/
|
|
1904
|
+
async agentRefs(orgId) {
|
|
1905
|
+
const out = { connectors: new Set(), skills: new Set(), templates: new Set() };
|
|
1906
|
+
for (const a of await agentDefinitionRefs(this.db, orgId)) {
|
|
1907
|
+
for (const x of a.connectors)
|
|
1908
|
+
out.connectors.add(x);
|
|
1909
|
+
for (const x of a.skills)
|
|
1910
|
+
out.skills.add(x);
|
|
1911
|
+
for (const x of a.templates)
|
|
1912
|
+
out.templates.add(x);
|
|
1913
|
+
}
|
|
1914
|
+
return out;
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1917
|
+
__decorate([
|
|
1918
|
+
Transactional({ propagation: "requires_new" })
|
|
1919
|
+
], PluginInstaller.prototype, "recordDependency", null);
|
|
1920
|
+
__decorate([
|
|
1921
|
+
Transactional()
|
|
1922
|
+
], PluginInstaller.prototype, "enableExtension", null);
|
|
1923
|
+
__decorate([
|
|
1924
|
+
Transactional({ propagation: "requires_new" })
|
|
1925
|
+
], PluginInstaller.prototype, "createInstallRow", null);
|
|
1926
|
+
__decorate([
|
|
1927
|
+
Transactional({ propagation: "requires_new" })
|
|
1928
|
+
], PluginInstaller.prototype, "markInstalled", null);
|
|
1929
|
+
__decorate([
|
|
1930
|
+
Transactional({ propagation: "requires_new" })
|
|
1931
|
+
], PluginInstaller.prototype, "markFailed", null);
|
|
1932
|
+
__decorate([
|
|
1933
|
+
Transactional({ propagation: "requires_new" })
|
|
1934
|
+
], PluginInstaller.prototype, "rollbackOne", null);
|
|
1935
|
+
__decorate([
|
|
1936
|
+
Transactional({ propagation: "mandatory" })
|
|
1937
|
+
], PluginInstaller.prototype, "removeComponent", null);
|
|
1938
|
+
__decorate([
|
|
1939
|
+
Transactional()
|
|
1940
|
+
], PluginInstaller.prototype, "writeUninstall", null);
|
|
1941
|
+
__decorate([
|
|
1942
|
+
Transactional({ propagation: "mandatory" })
|
|
1943
|
+
], PluginInstaller.prototype, "heir", null);
|
|
1944
|
+
__decorate([
|
|
1945
|
+
Transactional({ propagation: "mandatory" })
|
|
1946
|
+
], PluginInstaller.prototype, "handOver", null);
|
|
1947
|
+
__decorate([
|
|
1948
|
+
Transactional({ propagation: "mandatory" })
|
|
1949
|
+
], PluginInstaller.prototype, "uninstallIn", null);
|
|
1950
|
+
__decorate([
|
|
1951
|
+
Transactional({ propagation: "mandatory" })
|
|
1952
|
+
], PluginInstaller.prototype, "decideRemovalIn", null);
|
|
1953
|
+
__decorate([
|
|
1954
|
+
Transactional({ propagation: "mandatory" })
|
|
1955
|
+
], PluginInstaller.prototype, "undoUpgradeIn", null);
|
|
1956
|
+
__decorate([
|
|
1957
|
+
Transactional({ propagation: "requires_new" })
|
|
1958
|
+
], PluginInstaller.prototype, "recordConnector", null);
|
|
1959
|
+
__decorate([
|
|
1960
|
+
Transactional()
|
|
1961
|
+
], PluginInstaller.prototype, "recordOnLiveInstall", null);
|
|
1962
|
+
PluginInstaller = __decorate([
|
|
1963
|
+
Injectable(),
|
|
1964
|
+
__param(0, Inject(KernelDb)),
|
|
1965
|
+
__param(1, Inject(OrgLock)),
|
|
1966
|
+
__param(2, Inject(StorageService)),
|
|
1967
|
+
__param(3, Inject(ExtensionRegistry)),
|
|
1968
|
+
__param(4, Inject(SkillsService)),
|
|
1969
|
+
__param(5, Inject(OrgExtensionConfigs)),
|
|
1970
|
+
__param(6, Inject(KernelConfigService)),
|
|
1971
|
+
__param(7, Inject(ConnectorsService)),
|
|
1972
|
+
__param(8, Inject(KERNEL_LOGGER)),
|
|
1973
|
+
__param(9, Inject(TransactionHost))
|
|
1974
|
+
], PluginInstaller);
|
|
1975
|
+
export { PluginInstaller };
|
|
1225
1976
|
/**
|
|
1226
1977
|
* The skill names of a catalog version, read from each skill's SKILL.md in storage (the names are
|
|
1227
1978
|
* not in plugin.json). Used by install planning and the upgrade preview.
|
|
@@ -1331,3 +2082,36 @@ function orderByRequires(set) {
|
|
|
1331
2082
|
}
|
|
1332
2083
|
return placed;
|
|
1333
2084
|
}
|
|
2085
|
+
/**
|
|
2086
|
+
* Whether org row `id` (a skill or an agent template of the org) is linked without a pin to a live
|
|
2087
|
+
* platform row the org promoted when sharing it (ruling P3-3): owned by the org and from no plugin
|
|
2088
|
+
* (`catalog_item_id` null). A component of the org's own uploaded plugin is a plugin's, so its
|
|
2089
|
+
* install copies are removed and reverted as any plugin's.
|
|
2090
|
+
*/
|
|
2091
|
+
async function promotedOrgRow(db, orgId, kind, id) {
|
|
2092
|
+
const row = kind === "skill"
|
|
2093
|
+
? await db
|
|
2094
|
+
.selectFrom("skills as s")
|
|
2095
|
+
.innerJoin("platform_skills as p", "p.id", "s.platform_skill_id")
|
|
2096
|
+
.select("s.id")
|
|
2097
|
+
.where("s.id", "=", id)
|
|
2098
|
+
.where("s.org_id", "=", orgId)
|
|
2099
|
+
.where("s.pinned_version", "is", null)
|
|
2100
|
+
.where("p.owner_org_id", "=", orgId)
|
|
2101
|
+
// promoted, not an org plugin's component (which has its plugin, P3-2)
|
|
2102
|
+
.where("p.catalog_item_id", "is", null)
|
|
2103
|
+
.where("p.deleted_at", "is", null)
|
|
2104
|
+
.executeTakeFirst()
|
|
2105
|
+
: await db
|
|
2106
|
+
.selectFrom("agent_templates as a")
|
|
2107
|
+
.innerJoin("platform_agent_templates as p", "p.id", "a.platform_template_id")
|
|
2108
|
+
.select("a.id")
|
|
2109
|
+
.where("a.id", "=", id)
|
|
2110
|
+
.where("a.org_id", "=", orgId)
|
|
2111
|
+
.where("a.pinned_version", "is", null)
|
|
2112
|
+
.where("p.owner_org_id", "=", orgId)
|
|
2113
|
+
.where("p.catalog_item_id", "is", null)
|
|
2114
|
+
.where("p.deleted_at", "is", null)
|
|
2115
|
+
.executeTakeFirst();
|
|
2116
|
+
return row !== undefined;
|
|
2117
|
+
}
|