@capybara-hq/kernel 0.1.0-rc.1 → 0.1.0-rc.11
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 +85 -5
- 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 +60 -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 +264 -0
- package/dist/catalog/catalog-content.js +430 -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 +677 -0
- package/dist/catalog/catalog-scope.service.d.ts +286 -0
- package/dist/catalog/catalog-scope.service.js +1196 -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 +144 -207
- package/dist/catalog/catalog.service.js +258 -528
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/claude/translate.js +3 -0
- 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 +118 -0
- package/dist/catalog/component-scope.schemas.js +97 -0
- package/dist/catalog/component-scope.service.d.ts +366 -0
- package/dist/catalog/component-scope.service.js +1115 -0
- package/dist/catalog/component-state.d.ts +197 -0
- package/dist/catalog/component-state.js +473 -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 +434 -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 +808 -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 +243 -0
- package/dist/catalog/platform-components.js +872 -0
- package/dist/catalog/platform-migration.d.ts +115 -0
- package/dist/catalog/platform-migration.js +583 -0
- package/dist/catalog/plugin-import.d.ts +293 -71
- package/dist/catalog/plugin-import.js +1039 -281
- package/dist/catalog/plugin-install.d.ts +271 -66
- package/dist/catalog/plugin-install.js +1198 -344
- package/dist/catalog/plugin-package.d.ts +41 -4
- package/dist/catalog/plugin-package.js +140 -7
- package/dist/catalog/plugin-upgrade.d.ts +312 -188
- package/dist/catalog/plugin-upgrade.js +1371 -1065
- 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 +119 -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 -202
- 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 +36 -2
- package/dist/config/schema.js +226 -25
- 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 -71
- 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/secrets.d.ts +10 -2
- package/dist/ctx/secrets.js +7 -3
- package/dist/db/kernel-schema.d.ts +589 -27
- 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 +160 -2
- package/dist/errors.js +160 -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 -124
- 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 +99 -36
- package/dist/extensions/bootstrap.js +290 -134
- 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 +93 -358
- package/dist/http/app.d.ts +22 -17
- package/dist/http/app.js +46 -65
- 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 +137 -38
- package/dist/identity/accounts.js +386 -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 +80 -33
- package/dist/identity/me.schemas.d.ts +24 -0
- package/dist/identity/me.schemas.js +25 -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 +69 -23
- package/dist/identity/settings.js +201 -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 +22 -13
- package/dist/index.js +16 -7
- 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 -244
- 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-context.d.ts +2 -0
- package/dist/log-context.js +4 -0
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- 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/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 +76 -14
- package/dist/orgs/settings.service.js +140 -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 +683 -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 +94 -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 +38 -0
- package/dist/platform/ops/admin.ops.js +407 -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 +854 -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 +18 -0
- package/dist/platform/ops/org-settings.ops.js +127 -0
- package/dist/platform/ops/orgs.ops.d.ts +28 -0
- package/dist/platform/ops/orgs.ops.js +296 -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 +30 -0
- package/dist/platform/ops/platform.ops.js +231 -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/themes.ops.d.ts +14 -0
- package/dist/platform/ops/themes.ops.js +47 -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 +40 -0
- package/dist/platform/platform-ops.module.js +127 -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 +66 -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 -137
- 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 -237
- 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 -181
- 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/themes/render-css.d.ts +12 -0
- package/dist/themes/render-css.js +132 -0
- package/dist/themes/theme-delivery.service.d.ts +34 -0
- package/dist/themes/theme-delivery.service.js +111 -0
- package/dist/themes/theme-state.d.ts +95 -0
- package/dist/themes/theme-state.js +203 -0
- package/dist/themes/theme-usage.d.ts +61 -0
- package/dist/themes/theme-usage.js +98 -0
- package/dist/themes/themes-public.controller.d.ts +28 -0
- package/dist/themes/themes-public.controller.js +92 -0
- package/dist/themes/themes.controller.d.ts +13 -0
- package/dist/themes/themes.controller.js +38 -0
- package/dist/themes/themes.module.d.ts +3 -0
- package/dist/themes/themes.module.js +21 -0
- package/dist/themes/themes.schemas.d.ts +3 -0
- package/dist/themes/themes.schemas.js +2 -0
- package/dist/themes/themes.service.d.ts +50 -0
- package/dist/themes/themes.service.js +99 -0
- 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 +137 -37
- package/dist/tools/builtins/sandbox/common.js +222 -62
- 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 +13 -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/src/migrations/0102_themes.sql +64 -0
- package/src/migrations/0103_ui_theme_setting.sql +7 -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,25 +1,68 @@
|
|
|
1
|
-
|
|
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
|
+
// The platform plugin update (plugin and component management spec §7, plugin scope phase 2,
|
|
11
|
+
// Task 7): a platform plugin has one version for the deployment, so an update is previewed and
|
|
12
|
+
// confirmed once by the super admin, per component. The per-org upgrade routes are retired (ruling
|
|
13
|
+
// F2).
|
|
14
|
+
import { createHash } from "node:crypto";
|
|
15
|
+
import { SDK_VERSION } from "@capybara-hq/plugin-sdk";
|
|
16
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
2
17
|
import { sql } from "kysely";
|
|
3
|
-
import { putTemplateVersionIn } from "../agents/templates.js";
|
|
4
18
|
import { ApiError } from "../errors.js";
|
|
5
|
-
import {
|
|
19
|
+
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
20
|
+
import { ExtensionBlobs } from "../extensions/blobs.js";
|
|
21
|
+
import { permissionSetOfPackage, readExtensionPackage } from "../extensions/package.js";
|
|
22
|
+
import { blockingKeys, diffPermissions } from "../extensions/permission-set.js";
|
|
23
|
+
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
6
24
|
import { audit } from "../identity/audit.js";
|
|
7
|
-
import {
|
|
25
|
+
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
26
|
+
import { addOrgNotice, itemDisplayName, notifySharedUpdate } from "../inbox/org-notices.js";
|
|
27
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
28
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
29
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
30
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
31
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
32
|
+
import { LockService } from "../infra/lock/lock.service.js";
|
|
33
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
34
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
8
35
|
import { packagePath } from "../packages/tgz.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
36
|
+
import { StorageService } from "../storage/storage.service.js";
|
|
37
|
+
import { assertNotPlatformDefault, pickedByIn, themesPreview, } from "../themes/theme-usage.js";
|
|
38
|
+
import { canonicalJson } from "../tools/canonical-json.js";
|
|
39
|
+
import { ConnectorsService } from "../tools/connectors.service.js";
|
|
40
|
+
import { dirDigest, getPath, readCatalogAgentTemplates, readCatalogTemplates, readCatalogThemes, setPath, skillFilesDigest, templatePluginProblem, themeAssetsDigest, } from "./catalog-content.js";
|
|
41
|
+
import { markVersionApplied, versionUsable } from "./catalog-items.js";
|
|
42
|
+
import { agentsUsing, clashingOrgSkills, clashingPlatformSkills, componentOn, connectorsMadeFrom, connectorTemplatesOn, listedIn, loadComponents, loadScopeState, pluginFactsOf, switchOf, themeIdClashes, } from "./component-state.js";
|
|
43
|
+
import { CatalogItemLock } from "./locks.js";
|
|
44
|
+
import { itemPendingError, itemRemovedError } from "./ownership.js";
|
|
45
|
+
import { PlanStale, PlatformComponents } from "./platform-components.js";
|
|
46
|
+
import { catalogSkillNames, PluginInstaller } from "./plugin-install.js";
|
|
47
|
+
import { PluginScopeSync } from "./scope-sync.js";
|
|
48
|
+
import { compareVersions, satisfiesRange } from "./versions.js";
|
|
16
49
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
17
|
-
const installNotFound = () => new ApiError("plugin.install_not_found", "Plugin install not found");
|
|
18
|
-
const inProgress = () => new ApiError("plugin.install_in_progress", "This plugin install is being installed, upgraded or uninstalled; try again when it finishes");
|
|
19
|
-
const stale = () => new ApiError("plugin.upgrade_stale", "The upgrade preview is out of date (the catalog version or this install's components changed); preview the upgrade again");
|
|
20
|
-
const targetInvalid = (message, details) => new ApiError("plugin.upgrade_target_invalid", message, details);
|
|
21
|
-
const fail = (path, message) => new ApiError("validation_failed", "Request validation failed", [{ path, message }]);
|
|
22
50
|
const sha256 = (s) => createHash("sha256").update(s).digest("hex");
|
|
51
|
+
const itemNotFound = () => new ApiError("catalog.item_not_found", "Catalog item not found");
|
|
52
|
+
const stale = () => new ApiError("plugin.upgrade_stale", "The update preview is out of date (the catalog version, the platform components, a pin or a connector changed); preview the update again");
|
|
53
|
+
/** The pending version a super admin confirms was replaced by another upload (P3-11). */
|
|
54
|
+
const pendingStale = (name) => new ApiError("extension.approval_stale", `The pending upload of ${name} changed since it was reviewed; review it again`);
|
|
55
|
+
const targetInvalid = (message, details) => new ApiError("plugin.upgrade_target_invalid", message, details);
|
|
56
|
+
/** A version an org uploaded that was never applied or confirmed, or was rejected (P3-37, P3-52). */
|
|
57
|
+
const notApplied = (name, version) => targetInvalid(`Version ${version} of plugin ${name} was uploaded by an organization and never applied or confirmed (or was rejected); the generic update cannot apply it`, [{ reason: "org_version_not_applied", version }]);
|
|
58
|
+
const KIND_ORDER = {
|
|
59
|
+
skill: 0,
|
|
60
|
+
agent_template: 1,
|
|
61
|
+
connector_template: 2,
|
|
62
|
+
theme: 3,
|
|
63
|
+
};
|
|
64
|
+
/** How long one update holds its item (renewed while it runs). */
|
|
65
|
+
const UPDATE_LOCK_TTL_MS = 60_000;
|
|
23
66
|
/**
|
|
24
67
|
* What a credential of `auth` looks like: two auths with the same key take the same stored
|
|
25
68
|
* credential (static: the type family, ownership and header names; OAuth: any change re-enters).
|
|
@@ -40,660 +83,669 @@ function credentialKey(auth) {
|
|
|
40
83
|
}
|
|
41
84
|
}
|
|
42
85
|
/** The digest of all files of a catalog version. */
|
|
43
|
-
const filesDigest = (row) =>
|
|
44
|
-
.map((f) => `${f.path}\0${f.sha256}\n`)
|
|
45
|
-
.sort()
|
|
46
|
-
.join(""));
|
|
47
|
-
/** The digest of the files under `dir/` of a catalog version (paths relative to it). */
|
|
48
|
-
function dirDigest(row, dir) {
|
|
49
|
-
const prefix = `${dir}/`;
|
|
50
|
-
return sha256(row.files
|
|
51
|
-
.filter((f) => f.path.startsWith(prefix))
|
|
52
|
-
.map((f) => `${f.path.slice(prefix.length)}\0${f.sha256}\n`)
|
|
53
|
-
.sort()
|
|
54
|
-
.join(""));
|
|
55
|
-
}
|
|
86
|
+
const filesDigest = (row) => skillFilesDigest(row.files.map((f) => ({ path: f.path, sha256: f.sha256 })));
|
|
56
87
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* `
|
|
74
|
-
*
|
|
75
|
-
* the
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
88
|
+
* The platform plugin update (spec §7; ruling F2 retires the per-org upgrades):
|
|
89
|
+
* - **preview** diffs the platform's current components of the plugin (the version recorded in
|
|
90
|
+
* `catalog_items.platform_synced_version`, components updated on their own included) against a
|
|
91
|
+
* catalog version: each skill (by name, by its files' digest), agent template (by name, canonical
|
|
92
|
+
* definition) and connector template (by id, canonical file) is `added`, `removed`, `same`, or
|
|
93
|
+
* `upgrade` / `downgrade` (the target's direction from the component's catalog version). It marks
|
|
94
|
+
* components updated on their own, components with their own scope and the orgs whose linked
|
|
95
|
+
* copy is pinned; lists removed components agents still use (they stay, spec §7.3), the org
|
|
96
|
+
* connectors made from changed templates (all orgs, ruling E2; `credentialsReset` when the
|
|
97
|
+
* credential shape changed), the templates it turns on that will need an org's input (added, or
|
|
98
|
+
* no longer shipped off) and those it turns off (now shipped off, on only by default), the
|
|
99
|
+
* deployment's extension move, and a `diffHash`. Refused: same version, a disabled or deleted
|
|
100
|
+
* item, a target without the extension the deployment runs for it or moving a config-declared
|
|
101
|
+
* one, a template moving to another connector, a plugin another platform plugin depends on
|
|
102
|
+
* outside its range, and an added skill whose name is taken where the plugin is on (rule 10).
|
|
103
|
+
* - **update** runs under a Redis lock per item (another update -> `plugin.install_in_progress`):
|
|
104
|
+
* the extension first (`ExtensionAdminOps.install`, enabled when the update installs it; added
|
|
105
|
+
* permissions wait for the admin's approval as for any extension upgrade), then one transaction
|
|
106
|
+
* under the item name's lock that recomputes the diff (`plugin.upgrade_stale` on a difference)
|
|
107
|
+
* and writes the platform versions (`PlatformComponents.syncFromVersion`, which records
|
|
108
|
+
* `platform_synced_version`), the pinned suggestions of unchanged skills, the removals (a
|
|
109
|
+
* component no agent uses is soft-deleted, so unpinned linked copies go with it; pinned copies
|
|
110
|
+
* keep their own version; a removed connector template leaves its connectors as the orgs' own),
|
|
111
|
+
* clears the pins of linked copies, fans changed templates out to every connector made from them
|
|
112
|
+
* (`applyTemplateIn`, under each org's row lock, credentials cleared only for a changed
|
|
113
|
+
* credential shape), moves every org install to the version and audits
|
|
114
|
+
* `plugin.platform_updated`; the scope sync of the item and its dependencies is enqueued after
|
|
115
|
+
* the commit (orgs get new dependencies by rule 9). A failure rolls the transaction back and
|
|
116
|
+
* puts the extension back where it was (audit `plugin.platform_update_failed`, 502
|
|
117
|
+
* `plugin.upgrade_failed`); files copied to `deployment/platform/` stay unreferenced.
|
|
118
|
+
* Storage is never read or written inside the transaction: the target's contents (and the
|
|
119
|
+
* extension package, for `needsApproval`) are read and the platform files copied
|
|
120
|
+
* (`PlatformComponents.prepareSync`) after the Redis lock is taken and before the transaction,
|
|
121
|
+
* which reuses them and writes rows only (`applySyncIn`). The confirm-time diff treats the
|
|
122
|
+
* extension this update moved as expected (the install record must point at that package).
|
|
123
|
+
* Recovery: a process that dies between the extension step and the transaction leaves the
|
|
124
|
+
* deployment on the target's extension with the platform components unchanged; a new preview
|
|
125
|
+
* then shows the extension unchanged (`extension: null`) and the components still to move, and
|
|
126
|
+
* confirming it completes the update (or an update back to the old version moves it back).
|
|
127
|
+
* No in-process state.
|
|
80
128
|
*/
|
|
81
|
-
|
|
129
|
+
let PlatformPluginUpdater = class PlatformPluginUpdater {
|
|
130
|
+
kdb;
|
|
131
|
+
txHost;
|
|
132
|
+
adminLock;
|
|
133
|
+
itemLock;
|
|
134
|
+
orgLock;
|
|
135
|
+
locks;
|
|
136
|
+
storage;
|
|
137
|
+
registry;
|
|
138
|
+
ops;
|
|
139
|
+
blobs;
|
|
140
|
+
config;
|
|
141
|
+
platform;
|
|
82
142
|
installer;
|
|
83
|
-
|
|
84
|
-
|
|
143
|
+
connectors;
|
|
144
|
+
sync;
|
|
145
|
+
log;
|
|
146
|
+
constructor(kdb, txHost, adminLock, itemLock, orgLock, locks, storage, registry, ops,
|
|
147
|
+
/** Reads the target's extension package (its permissions, for `needsApproval`). */
|
|
148
|
+
blobs, config, platform,
|
|
149
|
+
/** Template dependencies (the deployed connector kinds). */
|
|
150
|
+
installer, connectors, sync, log) {
|
|
151
|
+
this.kdb = kdb;
|
|
152
|
+
this.txHost = txHost;
|
|
153
|
+
this.adminLock = adminLock;
|
|
154
|
+
this.itemLock = itemLock;
|
|
155
|
+
this.orgLock = orgLock;
|
|
156
|
+
this.locks = locks;
|
|
157
|
+
this.storage = storage;
|
|
158
|
+
this.registry = registry;
|
|
159
|
+
this.ops = ops;
|
|
160
|
+
this.blobs = blobs;
|
|
161
|
+
this.config = config;
|
|
162
|
+
this.platform = platform;
|
|
85
163
|
this.installer = installer;
|
|
86
|
-
this.
|
|
164
|
+
this.connectors = connectors;
|
|
165
|
+
this.sync = sync;
|
|
166
|
+
this.log = log;
|
|
87
167
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return
|
|
94
|
-
from: diff.from.version,
|
|
95
|
-
to: diff.to.version,
|
|
96
|
-
diffHash: diff.diffHash,
|
|
97
|
-
components: diff.components,
|
|
98
|
-
inputs: diff.inputs,
|
|
99
|
-
templates: diff.templates.flatMap((c) => c.target !== undefined &&
|
|
100
|
-
(diff.inputs.connectors.includes(c.id) || diff.inputs.credentialsChanged.includes(c.id))
|
|
101
|
-
? [orgTemplateView(c.id, c.target)]
|
|
102
|
-
: []),
|
|
103
|
-
};
|
|
168
|
+
get db() {
|
|
169
|
+
return this.kdb.db;
|
|
170
|
+
}
|
|
171
|
+
/** The update preview (see the class comment); writes nothing. */
|
|
172
|
+
async preview(itemId, version) {
|
|
173
|
+
return previewOf(await this.diff(itemId, version));
|
|
104
174
|
}
|
|
105
175
|
/**
|
|
106
|
-
* The
|
|
107
|
-
*
|
|
108
|
-
*
|
|
176
|
+
* The update preview of a new version of an org's own plugin (ruling P3-12): the item must be
|
|
177
|
+
* owned by `orgId` (else 404, as for any item the org cannot see), the target carries no
|
|
178
|
+
* extension (an extension-bearing version waits for the super admin, plan Task 6), and a target
|
|
179
|
+
* dropping the deployment's extension is allowed (P3-12'). `staged` is the target read from the
|
|
180
|
+
* org's staging (pre-flight F3); without it the imported version `version` is read. The route
|
|
181
|
+
* authorizes the org admin; writes nothing.
|
|
109
182
|
*/
|
|
110
|
-
async
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
throw
|
|
115
|
-
|
|
183
|
+
async previewForOwner(orgId, itemId, version, staged) {
|
|
184
|
+
// An internal invariant, not reachable from input: the only caller (OrgPluginUploads) passes
|
|
185
|
+
// the staged target together with its own version (PluginImport.stagedTarget)
|
|
186
|
+
if (staged !== undefined && staged.version !== version) {
|
|
187
|
+
throw new Error(`internal: previewForOwner got the staged target of version ${staged.version} for version ${version}`);
|
|
188
|
+
}
|
|
189
|
+
const preview = previewOf(await this.diff(itemId, version, {
|
|
190
|
+
owner: { orgId },
|
|
191
|
+
...(staged !== undefined && { target: staged }),
|
|
192
|
+
}));
|
|
193
|
+
// The owner sees the names of the orgs whose default a removed theme is (named like the other
|
|
194
|
+
// orgs the preview mentions, P3-14 / P3-19), but people only of its own org: other orgs'
|
|
195
|
+
// member counts were never disclosed to it. Display only: `diffHash` covers the full preview.
|
|
196
|
+
const themes = preview.themes === undefined
|
|
197
|
+
? undefined
|
|
198
|
+
: await Promise.all(preview.themes.map(async (t) => ({
|
|
199
|
+
...t,
|
|
200
|
+
pickedBy: await pickedByIn(this.db, t.id, new Set([orgId])),
|
|
201
|
+
})));
|
|
202
|
+
const owned = { ...preview, ...(themes !== undefined && { themes }) };
|
|
203
|
+
return { ...owned, orgNames: await this.orgNamesOf(owned) };
|
|
116
204
|
}
|
|
117
205
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
206
|
+
* Locks, in sorted order and before the item (ruling P3-50), every live org the update may
|
|
207
|
+
* write in: the orgs with connectors made from the plugin's connector templates and the item's
|
|
208
|
+
* owner org. `acting`: the owner org an owner update acts for, locked with its admin re-checked
|
|
209
|
+
* (`catalog.upload`; deleted -> 404 `org.not_found`). Returns the live orgs locked; another
|
|
210
|
+
* deleted one is skipped.
|
|
121
211
|
*/
|
|
122
|
-
async
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
212
|
+
async lockUpdateOrgs(itemId, acting) {
|
|
213
|
+
const item = await this.db
|
|
214
|
+
.selectFrom("catalog_items")
|
|
215
|
+
.select("owner_org_id")
|
|
216
|
+
.where("id", "=", itemId)
|
|
217
|
+
.executeTakeFirst();
|
|
218
|
+
const made = await this.db
|
|
219
|
+
.selectFrom("connectors as c")
|
|
220
|
+
.innerJoin("platform_connector_templates as t", "t.id", "c.platform_template_id")
|
|
221
|
+
.select("c.org_id")
|
|
222
|
+
.distinct()
|
|
223
|
+
.where("t.catalog_item_id", "=", itemId)
|
|
224
|
+
.where("c.deleted_at", "is", null)
|
|
225
|
+
.execute();
|
|
226
|
+
const ids = new Set(made.map((r) => r.org_id));
|
|
227
|
+
if (item?.owner_org_id)
|
|
228
|
+
ids.add(item.owner_org_id);
|
|
229
|
+
if (acting !== undefined)
|
|
230
|
+
ids.add(acting.orgId);
|
|
231
|
+
const live = new Set();
|
|
232
|
+
for (const orgId of [...ids].sort()) {
|
|
233
|
+
if (orgId === acting?.orgId) {
|
|
234
|
+
await this.orgLock.lockAndAuthorize(orgId, acting.actor, "catalog.upload");
|
|
235
|
+
live.add(orgId);
|
|
236
|
+
}
|
|
237
|
+
else if (await this.orgLock.tryLock(orgId)) {
|
|
238
|
+
live.add(orgId);
|
|
239
|
+
}
|
|
129
240
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
241
|
+
return live;
|
|
242
|
+
}
|
|
243
|
+
/** The names of the orgs a preview mentions, by id (an owner's preview, see `orgNames`). */
|
|
244
|
+
async orgNamesOf(p) {
|
|
245
|
+
const ids = new Set([
|
|
246
|
+
...(p.extension?.orgs ?? []),
|
|
247
|
+
...p.connectorOrgs.map((c) => c.orgId),
|
|
248
|
+
...p.components.flatMap((c) => [...c.pinnedOrgs, ...(c.kept ?? []).map((k) => k.orgId)]),
|
|
249
|
+
...(p.themes ?? []).flatMap((t) => t.orgDefaults.map((o) => o.orgId)),
|
|
250
|
+
]);
|
|
251
|
+
if (ids.size === 0)
|
|
252
|
+
return {};
|
|
253
|
+
const rows = await this.db
|
|
254
|
+
.selectFrom("orgs")
|
|
255
|
+
.select(["id", "name"])
|
|
256
|
+
.where("id", "in", [...ids])
|
|
257
|
+
.where("deleted_at", "is", null)
|
|
258
|
+
.execute();
|
|
259
|
+
return Object.fromEntries(rows.map((r) => [r.id, r.name]));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Applies a new version of an org's own plugin for its owner (ruling P3-12, see
|
|
263
|
+
* {@link previewForOwner}): the actor must be an admin of the owner org (`catalog.upload`,
|
|
264
|
+
* re-checked under the org row lock in the transaction), then the platform update as
|
|
265
|
+
* {@link update} does, also removing the extension when the target drops it. In the update's
|
|
266
|
+
* transaction the orgs using the shared plugin are told (`shared_item_updated`, one notice per
|
|
267
|
+
* plugin) and a pending version is cleared (pre-flight F7: the new version replaces it).
|
|
268
|
+
*/
|
|
269
|
+
async updateAsOwner(orgId, actor, itemId, version, diffHash, opts = {}) {
|
|
270
|
+
if (!UUID_RE.test(itemId))
|
|
271
|
+
throw itemNotFound();
|
|
272
|
+
await this.authorizeOwner(orgId, actor);
|
|
273
|
+
return this.locked(itemId, () => this.updateLocked(actor, itemId, { version, diffHash }, opts, { orgId }));
|
|
274
|
+
}
|
|
275
|
+
/** The actor is an admin of the owner org (a read of the membership under the org row lock). */
|
|
276
|
+
async authorizeOwner(orgId, actor) {
|
|
277
|
+
await this.orgLock.lockAndAuthorize(orgId, actor, "catalog.upload");
|
|
278
|
+
}
|
|
279
|
+
/** Runs `f` holding the item's update lock (another update -> `plugin.install_in_progress`). */
|
|
280
|
+
async locked(itemId, f) {
|
|
281
|
+
const handle = await this.locks.acquire(`plugin-update-${itemId}`, {
|
|
282
|
+
ttlMs: UPDATE_LOCK_TTL_MS,
|
|
283
|
+
});
|
|
284
|
+
if (!handle) {
|
|
285
|
+
throw new ApiError("plugin.install_in_progress", "This plugin is being updated; try again when that update finishes");
|
|
135
286
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
await
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
287
|
+
try {
|
|
288
|
+
return await f();
|
|
289
|
+
}
|
|
290
|
+
finally {
|
|
291
|
+
await handle.release();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* The super admin's confirmation of an org upload's pending new version (rulings P3-10, P3-21,
|
|
296
|
+
* pre-flight F8): the update to `version` as {@link update} does it (the super admin's, the
|
|
297
|
+
* extension installed or upgraded on the deployment), with the version allowed although it is
|
|
298
|
+
* pending. Its transaction re-reads the item under the row lock: removed meanwhile -> 409
|
|
299
|
+
* `catalog.item_removed`, the pending version replaced -> 409 `extension.approval_stale` (both
|
|
300
|
+
* undo the extension step); then the pending state is cleared and the owner told
|
|
301
|
+
* (`upload_confirmed`). The caller checked the digest of the version's package.
|
|
302
|
+
*/
|
|
303
|
+
async updateToPending(actor, itemId, version, opts = {}) {
|
|
304
|
+
if (!UUID_RE.test(itemId))
|
|
305
|
+
throw itemNotFound();
|
|
306
|
+
return this.locked(itemId, () => this.updateToPendingLocked(actor, itemId, version, opts));
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* {@link updateToPending} for a caller already holding the item's update lock
|
|
310
|
+
* ({@link withItemLock}): the super admin's confirmation runs all its steps under it (ruling
|
|
311
|
+
* P3-35).
|
|
312
|
+
*/
|
|
313
|
+
async updateToPendingLocked(actor, itemId, version, opts = {}) {
|
|
314
|
+
const d = await this.diff(itemId, version, { confirmPending: version });
|
|
315
|
+
return this.updateLocked(actor, itemId, { version, diffHash: d.diffHash }, opts, undefined, version);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Runs `f` holding the item's update lock (the one every platform update of the item takes;
|
|
319
|
+
* another holder -> 409 `plugin.install_in_progress`): the super admin's confirmation of an org
|
|
320
|
+
* upload runs every step under it (ruling P3-35).
|
|
321
|
+
*/
|
|
322
|
+
withItemLock(itemId, f) {
|
|
323
|
+
if (!UUID_RE.test(itemId))
|
|
324
|
+
throw itemNotFound();
|
|
325
|
+
return this.locked(itemId, f);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Runs an update confirmed with the preview's `diffHash` (see the class comment). A version an
|
|
329
|
+
* org upload waits with, or an item whose first version waits, -> 409 `catalog.item_pending`
|
|
330
|
+
* (confirmed in 待确认 instead, pre-flight F8).
|
|
331
|
+
*/
|
|
332
|
+
async update(actor, itemId, input, opts = {}) {
|
|
333
|
+
if (!UUID_RE.test(itemId))
|
|
334
|
+
throw itemNotFound();
|
|
335
|
+
return this.locked(itemId, () => this.updateLocked(actor, itemId, input, opts));
|
|
336
|
+
}
|
|
337
|
+
async updateLocked(actor, itemId, input, opts, owner, confirmPending) {
|
|
338
|
+
// Storage is read and written here, before any transaction (see the class comment)
|
|
339
|
+
const checked = await this.diff(itemId, input.version, {
|
|
340
|
+
...(owner && { owner }),
|
|
341
|
+
...(confirmPending !== undefined && { confirmPending }),
|
|
165
342
|
});
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.where(sql `upgrade->>'id'`, "=", upgradeId)
|
|
180
|
-
.executeTakeFirst();
|
|
181
|
-
if (r.numUpdatedRows === 0n)
|
|
182
|
-
throw cleanedUp();
|
|
183
|
-
unjournaled = undefined;
|
|
184
|
-
};
|
|
185
|
-
// Records a component in the ledger and the journal, in the given transaction
|
|
186
|
-
const record = async (c, t) => {
|
|
187
|
-
const inserted = await t
|
|
188
|
-
.insertInto("plugin_install_components")
|
|
189
|
-
.values({
|
|
190
|
-
install_id: installId,
|
|
191
|
-
kind: c.kind,
|
|
192
|
-
ref: c.ref,
|
|
193
|
-
created: c.created,
|
|
194
|
-
skill_version: c.skillVersion,
|
|
195
|
-
template_id: c.templateId ?? null,
|
|
196
|
-
})
|
|
197
|
-
.onConflict((oc) => oc.columns(["install_id", "kind", "ref"]).doNothing())
|
|
198
|
-
.returning("ref")
|
|
199
|
-
.executeTakeFirst();
|
|
200
|
-
if (c.created)
|
|
201
|
-
await journal({ op: "created", kind: c.kind, ref: c.ref }, t);
|
|
202
|
-
else if (inserted)
|
|
203
|
-
await journal({ op: "recorded", kind: c.kind, ref: c.ref }, t);
|
|
204
|
-
};
|
|
205
|
-
let step = "dependencies";
|
|
206
|
-
const disabled = [];
|
|
343
|
+
if (checked.diffHash !== input.diffHash)
|
|
344
|
+
throw stale();
|
|
345
|
+
const prepared = await this.platform.prepareSync(itemId, input.version);
|
|
346
|
+
const ext = checked.extension;
|
|
347
|
+
// The extension admin re-checks the actor: a super admin, or for an owner update the owner
|
|
348
|
+
// org's admin (and audits it with `ownerOrgId`)
|
|
349
|
+
const opsOwner = owner && { orgId: owner.orgId };
|
|
350
|
+
let step = "extension";
|
|
351
|
+
let extensionMoved = false;
|
|
352
|
+
let enabledHere = false;
|
|
353
|
+
let leftDisabled;
|
|
354
|
+
/** A removal: the extension was enabled before it (put back enabled on failure). */
|
|
355
|
+
let removedEnabled = false;
|
|
207
356
|
try {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
357
|
+
if (ext?.sha256 === null) {
|
|
358
|
+
// The target drops the extension (P3-12'): disabled (drained), then uninstalled
|
|
359
|
+
const row = await this.db
|
|
360
|
+
.selectFrom("extension_installs")
|
|
361
|
+
.select("desired_state")
|
|
362
|
+
.where("name", "=", checked.name)
|
|
363
|
+
.executeTakeFirst();
|
|
364
|
+
removedEnabled = row?.desired_state === "enabled";
|
|
365
|
+
await this.ops.disable(checked.name, actor, opts.actorTokenId, opsOwner);
|
|
366
|
+
extensionMoved = true;
|
|
367
|
+
await this.ops.uninstall(checked.name, actor, opts.actorTokenId, opsOwner);
|
|
368
|
+
}
|
|
369
|
+
else if (ext) {
|
|
370
|
+
const installed = await this.ops.install(checked.name, ext.sha256, actor, opts.actorTokenId, { catalogItemId: itemId, ...(opsOwner && { owner: opsOwner }) });
|
|
371
|
+
extensionMoved = true;
|
|
372
|
+
// A new version newly providing a held single-provider point: left disabled by the install
|
|
373
|
+
leftDisabled = installed.leftDisabled;
|
|
374
|
+
if (ext.previous === null) {
|
|
375
|
+
// An occupied single-provider point leaves it installed disabled
|
|
376
|
+
const r = await this.ops.enableUnlessOccupied(checked.name, actor, opts.actorTokenId, opsOwner);
|
|
377
|
+
enabledHere = r.enabled;
|
|
378
|
+
if (!r.enabled)
|
|
379
|
+
leftDisabled = r.note;
|
|
215
380
|
}
|
|
216
|
-
|
|
381
|
+
}
|
|
382
|
+
step = "components";
|
|
383
|
+
const diff = await this.commit(actor, itemId, input, opts, { contents: checked.contents, extension: ext }, prepared, owner, confirmPending);
|
|
384
|
+
return {
|
|
385
|
+
itemId,
|
|
386
|
+
version: diff.to.version,
|
|
387
|
+
components: diff.components,
|
|
388
|
+
extension: extensionView(diff.extension),
|
|
389
|
+
connectorOrgs: diff.connectorOrgs,
|
|
390
|
+
...(leftDisabled !== undefined && { extensionLeftDisabled: leftDisabled }),
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
catch (e) {
|
|
394
|
+
let rolledBack = true;
|
|
395
|
+
if (extensionMoved && ext) {
|
|
396
|
+
// An owner update was authorized at its start: the put-back is not checked again
|
|
397
|
+
const back = opsOwner && { ...opsOwner, rollback: true };
|
|
217
398
|
try {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
throw new InstallFailure(e.step, e.cause, [dep.name, ...e.dependency], e.rolledBack);
|
|
399
|
+
if (ext.sha256 === null) {
|
|
400
|
+
// Removed by this update: the previous package reinstalled (as it was)
|
|
401
|
+
await this.ops.install(checked.name, ext.previous, actor, opts.actorTokenId, {
|
|
402
|
+
catalogItemId: itemId,
|
|
403
|
+
...(back && { owner: back }),
|
|
404
|
+
});
|
|
405
|
+
if (removedEnabled)
|
|
406
|
+
await this.ops.enable(checked.name, actor, opts.actorTokenId, back);
|
|
227
407
|
}
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
408
|
+
else if (ext.previous !== null) {
|
|
409
|
+
await this.ops.install(checked.name, ext.previous, actor, opts.actorTokenId, {
|
|
410
|
+
...(back && { owner: back }),
|
|
411
|
+
});
|
|
412
|
+
// The install left the enabled extension disabled (a held single-provider point): the
|
|
413
|
+
// previous version, which did not provide it, runs again
|
|
414
|
+
if (leftDisabled !== undefined) {
|
|
415
|
+
await this.ops.enable(checked.name, actor, opts.actorTokenId, back);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
// Installed by this update: an uninstall needs it disabled first
|
|
420
|
+
if (enabledHere)
|
|
421
|
+
await this.ops.disable(checked.name, actor, opts.actorTokenId, back);
|
|
422
|
+
await this.ops.uninstall(checked.name, actor, opts.actorTokenId, back);
|
|
232
423
|
}
|
|
233
|
-
throw new InstallFailure("dependencies", e, [dep.name], true);
|
|
234
424
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (diff.extension?.change === "added") {
|
|
239
|
-
const name = diff.extension.name;
|
|
240
|
-
await this.d.orgConfigs.put(orgId, name, {
|
|
241
|
-
enabled: true,
|
|
242
|
-
...(input.extensionConfig !== undefined && { config: input.extensionConfig }),
|
|
243
|
-
}, actor, opts.actorTokenId, {
|
|
244
|
-
viaItem: itemId,
|
|
245
|
-
ifDisabled: { skipped: false },
|
|
246
|
-
inTransaction: (t, skipped) => record({ kind: "extension", ref: name, created: !skipped, skillVersion: null }, t),
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
step = "skills";
|
|
250
|
-
for (const s of diff.skills) {
|
|
251
|
-
if (s.change !== "added" && s.change !== "changed")
|
|
252
|
-
continue;
|
|
253
|
-
const files = await readCatalogFiles(this.d.storage, diff.to.object_prefix, diff.to.files, s.dir);
|
|
254
|
-
const r = await this.d.skills.createVersionFromFiles(orgId, actor, { ...skillOf(files), files }, {
|
|
255
|
-
catalog: {
|
|
425
|
+
catch (u) {
|
|
426
|
+
rolledBack = false;
|
|
427
|
+
this.log.error("putting a plugin's extension back after a failed update failed", {
|
|
256
428
|
itemId,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
suggestPinned: s.suggestPinned === true,
|
|
260
|
-
},
|
|
261
|
-
...opts,
|
|
262
|
-
});
|
|
263
|
-
await this.d.db.transaction().execute(async (t) => {
|
|
264
|
-
if (r.created) {
|
|
265
|
-
await record({ kind: "skill", ref: r.skill.id, created: true, skillVersion: null }, t);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
await journal({ op: "skill_version", ref: r.skill.id, version: r.version }, t);
|
|
269
|
-
await record({ kind: "skill", ref: r.skill.id, created: false, skillVersion: r.version }, t);
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
step = "agent_templates";
|
|
273
|
-
for (const a of diff.agentTemplates) {
|
|
274
|
-
if (a.change !== "added" && a.change !== "changed")
|
|
275
|
-
continue;
|
|
276
|
-
await this.d.db.transaction().execute(async (t) => {
|
|
277
|
-
await lockOrg(t, orgId);
|
|
278
|
-
const r = await putTemplateVersionIn(t, {
|
|
279
|
-
orgId,
|
|
280
|
-
plugin: diff.name,
|
|
281
|
-
catalogItemId: itemId,
|
|
282
|
-
catalogVersion: diff.to.version,
|
|
283
|
-
sourceFormat: diff.to.source_format,
|
|
284
|
-
}, a.template);
|
|
285
|
-
if (r.created) {
|
|
286
|
-
await record({ kind: "agent_template", ref: r.id, created: true, skillVersion: null }, t);
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
if (r.changed)
|
|
290
|
-
await journal({ op: "template_version", ref: r.id, version: r.version }, t);
|
|
291
|
-
await record({
|
|
292
|
-
kind: "agent_template",
|
|
293
|
-
ref: r.id,
|
|
294
|
-
created: false,
|
|
295
|
-
skillVersion: r.changed ? r.version : null,
|
|
296
|
-
}, t);
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
step = "connectors";
|
|
300
|
-
for (const [templateId, ci] of diff.creates) {
|
|
301
|
-
const r = await this.d.connectors.create(orgId, actor, ci, opts.actorTokenId);
|
|
302
|
-
await this.d.db.transaction().execute((t) => record({
|
|
303
|
-
kind: "connector",
|
|
304
|
-
ref: r.connector.id,
|
|
305
|
-
created: true,
|
|
306
|
-
skillVersion: null,
|
|
307
|
-
templateId,
|
|
308
|
-
}, t));
|
|
309
|
-
}
|
|
310
|
-
const prepared = [];
|
|
311
|
-
for (const tpl of diff.templates) {
|
|
312
|
-
const update = diff.updates.get(tpl.id);
|
|
313
|
-
if (!update || !tpl.connector)
|
|
314
|
-
continue;
|
|
315
|
-
try {
|
|
316
|
-
prepared.push({
|
|
317
|
-
connectorId: tpl.connector.id,
|
|
318
|
-
p: await this.d.connectors.prepareTemplateUpdate(actor, tpl.connector.connector, update),
|
|
429
|
+
plugin: checked.name,
|
|
430
|
+
err: u,
|
|
319
431
|
});
|
|
320
432
|
}
|
|
321
|
-
catch (e) {
|
|
322
|
-
throw under(e, `connectors.${tpl.id}`);
|
|
323
|
-
}
|
|
324
433
|
}
|
|
325
|
-
|
|
326
|
-
await this.
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if (dep.change !== "changed" || !dep.child)
|
|
343
|
-
continue;
|
|
344
|
-
const live = await t
|
|
345
|
-
.selectFrom("plugin_installs")
|
|
346
|
-
.select("version")
|
|
347
|
-
.where("id", "=", dep.child.installId)
|
|
348
|
-
.forShare()
|
|
349
|
-
.executeTakeFirst();
|
|
350
|
-
if (!live || !satisfiesRange(live.version, dep.range)) {
|
|
351
|
-
throw new ApiError("catalog.dependency_unresolved", `Dependency ${dep.name}@${dep.range} cannot be resolved: its install in this organization changed meanwhile; preview the upgrade again`, [{ dependency: dep.name, range: dep.range }]);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
const report = await this.removeIn(t, orgId, actor, diff, disabled);
|
|
355
|
-
// An unchanged skill gets no new version, so the target's pinned suggestion goes onto its
|
|
356
|
-
// current version (when that version is this plugin's) here, with the version switch.
|
|
357
|
-
for (const sk of diff.skills) {
|
|
358
|
-
if (sk.change !== "unchanged" || !sk.ledger)
|
|
359
|
-
continue;
|
|
360
|
-
await t
|
|
361
|
-
.updateTable("skill_versions as v")
|
|
362
|
-
.set({ suggest_pinned: sk.suggestPinned === true })
|
|
363
|
-
.from("skills as s")
|
|
364
|
-
.whereRef("s.id", "=", "v.skill_id")
|
|
365
|
-
.whereRef("s.current_version", "=", "v.version")
|
|
366
|
-
.where("s.id", "=", sk.ledger.ref)
|
|
367
|
-
.where("s.org_id", "=", orgId)
|
|
368
|
-
.where("v.catalog_item_id", "=", itemId)
|
|
369
|
-
.where("v.suggest_pinned", "<>", sk.suggestPinned === true)
|
|
370
|
-
.execute();
|
|
371
|
-
}
|
|
372
|
-
await t
|
|
373
|
-
.updateTable("plugin_installs")
|
|
374
|
-
.set({ version: diff.to.version, status: "installed", upgrade: null, error: null })
|
|
375
|
-
.where("id", "=", installId)
|
|
376
|
-
.execute();
|
|
377
|
-
await this.d.requests.resolveByInstall(t, orgId, itemId, actor, opts);
|
|
378
|
-
await audit(t, {
|
|
379
|
-
actorAccountId: actor,
|
|
380
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
381
|
-
orgId,
|
|
382
|
-
action: "plugin.org_upgraded",
|
|
383
|
-
target: installId,
|
|
384
|
-
detail: {
|
|
385
|
-
itemId,
|
|
386
|
-
name: diff.name,
|
|
387
|
-
from: diff.from.version,
|
|
388
|
-
to: diff.to.version,
|
|
389
|
-
components: diff.components,
|
|
390
|
-
removed: report.removed,
|
|
391
|
-
kept: report.kept,
|
|
392
|
-
},
|
|
393
|
-
});
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
catch (e) {
|
|
397
|
-
throw await this.failed(orgId, actor, installId, upgradeId, diff, { done, unjournaled }, step, e, opts);
|
|
434
|
+
const code = e instanceof ApiError ? e.code : "internal";
|
|
435
|
+
await this.auditFailure(actor, checked, { step, code, rolledBack }, opts);
|
|
436
|
+
// A refusal found under the lock (stale, disabled meanwhile, a conflict, a downgrade the
|
|
437
|
+
// extension's migrations refuse): returned as it is
|
|
438
|
+
if (e instanceof ApiError && e.status < 500 && rolledBack)
|
|
439
|
+
throw e;
|
|
440
|
+
throw new ApiError("plugin.upgrade_failed", rolledBack
|
|
441
|
+
? `Updating the plugin failed at step ${step} (${code}); the platform is back at version ${checked.from ?? "(none)"}`
|
|
442
|
+
: `Updating the plugin failed at step ${step} (${code}) and putting its extension back failed; check the extension in the admin console`, [
|
|
443
|
+
{
|
|
444
|
+
step,
|
|
445
|
+
code,
|
|
446
|
+
...(e instanceof ApiError && { message: e.message }),
|
|
447
|
+
...(e instanceof ApiError && e.details !== undefined && { causeDetails: e.details }),
|
|
448
|
+
rolledBack,
|
|
449
|
+
},
|
|
450
|
+
]);
|
|
398
451
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
452
|
+
}
|
|
453
|
+
/** `plugin.platform_update_failed`, in a transaction of its own. */
|
|
454
|
+
async auditFailure(actor, diff, f, opts) {
|
|
455
|
+
await audit(this.db, {
|
|
456
|
+
actorAccountId: actor,
|
|
457
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
458
|
+
action: "plugin.platform_update_failed",
|
|
459
|
+
target: diff.itemId,
|
|
460
|
+
detail: { name: diff.name, from: diff.from, to: diff.to.version, ...f },
|
|
461
|
+
});
|
|
405
462
|
}
|
|
406
463
|
/**
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
* is no longer this upgrade's (another request cleaned it up as interrupted and undid what it
|
|
410
|
-
* journaled), only the step whose journal write failed is undone and the install row is left as
|
|
411
|
-
* the cleanup set it. Returns the error to throw: 502 `plugin.upgrade_failed` (a dependency
|
|
412
|
-
* another install is still installing: its 409 as it is).
|
|
464
|
+
* The update's transaction (see the class comment): the super admin re-checked, the diff
|
|
465
|
+
* recomputed under the item name's lock, then every write. Returns the diff it applied.
|
|
413
466
|
*/
|
|
414
|
-
async
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
actorAccountId: actor,
|
|
444
|
-
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
445
|
-
orgId,
|
|
446
|
-
action: "plugin.org_upgrade_failed",
|
|
447
|
-
target: installId,
|
|
448
|
-
detail: {
|
|
449
|
-
itemId: diff.itemId,
|
|
450
|
-
name: diff.name,
|
|
451
|
-
from: diff.from.version,
|
|
452
|
-
to: diff.to.version,
|
|
453
|
-
step: at,
|
|
454
|
-
code,
|
|
455
|
-
rolledBack: undo,
|
|
456
|
-
...(!ours && { cleanedUpMeanwhile: true }),
|
|
457
|
-
},
|
|
458
|
-
});
|
|
459
|
-
return out;
|
|
460
|
-
});
|
|
461
|
-
for (const r of removed) {
|
|
462
|
-
if (r.kind === "extension")
|
|
463
|
-
await this.d.orgConfigs.afterDisable(orgId, r.ref);
|
|
464
|
-
}
|
|
467
|
+
async commit(actor, itemId, input, opts, pre, prepared, owner, confirmPending) {
|
|
468
|
+
if (owner === undefined)
|
|
469
|
+
await this.adminLock.lockAndAuthorize(actor);
|
|
470
|
+
// The global lock order (ruling P3-50): the orgs (sorted; the acting owner org's admin
|
|
471
|
+
// re-checked at its place), then the item, then its components; an org deletion locks its org
|
|
472
|
+
// row, then the items it owns
|
|
473
|
+
const liveOrgs = await this.lockUpdateOrgs(itemId, owner && { orgId: owner.orgId, actor });
|
|
474
|
+
const named = await this.db
|
|
475
|
+
.selectFrom("catalog_items")
|
|
476
|
+
.select("name")
|
|
477
|
+
.where("id", "=", itemId)
|
|
478
|
+
.executeTakeFirst();
|
|
479
|
+
if (!named)
|
|
480
|
+
throw itemNotFound();
|
|
481
|
+
await this.itemLock.lock(named.name);
|
|
482
|
+
let pendingOwner = null;
|
|
483
|
+
if (confirmPending !== undefined) {
|
|
484
|
+
// The super admin's confirmation (P3-21): still pending with the version they reviewed
|
|
485
|
+
const row = await this.db
|
|
486
|
+
.selectFrom("catalog_items")
|
|
487
|
+
.select(["deleted_at", "pending_version", "owner_org_id"])
|
|
488
|
+
.where("id", "=", itemId)
|
|
489
|
+
.forUpdate()
|
|
490
|
+
.executeTakeFirstOrThrow();
|
|
491
|
+
if (row.deleted_at !== null)
|
|
492
|
+
throw itemRemovedError(named.name);
|
|
493
|
+
if (row.pending_version !== confirmPending)
|
|
494
|
+
throw pendingStale(named.name);
|
|
495
|
+
pendingOwner = row.owner_org_id;
|
|
465
496
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
497
|
+
const diff = await this.diff(itemId, input.version, {
|
|
498
|
+
pre,
|
|
499
|
+
...(owner && { owner }),
|
|
500
|
+
...(confirmPending !== undefined && { confirmPending }),
|
|
501
|
+
});
|
|
502
|
+
if (diff.diffHash !== input.diffHash)
|
|
503
|
+
throw stale();
|
|
504
|
+
const t = this.db;
|
|
505
|
+
// The platform versions (files copied before the transaction; rows only here)
|
|
506
|
+
try {
|
|
507
|
+
await this.platform.applySyncIn(prepared);
|
|
474
508
|
}
|
|
475
|
-
|
|
476
|
-
|
|
509
|
+
catch (e) {
|
|
510
|
+
if (e instanceof PlanStale)
|
|
511
|
+
throw stale();
|
|
512
|
+
throw e;
|
|
477
513
|
}
|
|
478
|
-
const
|
|
479
|
-
const dep = dependency.length > 0 ? ` in dependency ${dependency.join(" > ")}` : "";
|
|
480
|
-
return new ApiError("plugin.upgrade_failed", rolledBack
|
|
481
|
-
? `Upgrading the plugin failed at step ${at}${dep} (${code}); this organization's components are back at version ${diff.from.version}`
|
|
482
|
-
: `Upgrading the plugin failed at step ${at}${dep} (${code}) and rolling back failed; it is undone after catalog.staleInstallMinutes`, [
|
|
483
|
-
{
|
|
484
|
-
step: at,
|
|
485
|
-
code,
|
|
486
|
-
...(dependency.length > 0 && { dependency: dependency.join(" > ") }),
|
|
487
|
-
...(cause instanceof ApiError && { message: cause.message }),
|
|
488
|
-
...(cause instanceof ApiError &&
|
|
489
|
-
cause.details !== undefined && { causeDetails: cause.details }),
|
|
490
|
-
rolledBack,
|
|
491
|
-
},
|
|
492
|
-
]);
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* An upgrade interrupted for longer than `catalog.staleInstallMinutes` (a replica crashed
|
|
496
|
-
* midway): its journal is undone, the install back `installed` at the old version (error step
|
|
497
|
-
* `interrupted`), audit `plugin.org_upgrade_failed`. Nothing to do otherwise.
|
|
498
|
-
*/
|
|
499
|
-
async recoverInterrupted(orgId, actor, installId) {
|
|
500
|
-
if (!UUID_RE.test(installId))
|
|
501
|
-
throw installNotFound();
|
|
502
|
-
const staleMinutes = this.d.staleInstallMinutes();
|
|
503
|
-
const removed = await this.d.db.transaction().execute(async (t) => {
|
|
504
|
-
const peek = await t
|
|
505
|
-
.selectFrom("plugin_installs")
|
|
506
|
-
.select("status")
|
|
507
|
-
.where("id", "=", installId)
|
|
508
|
-
.where("org_id", "=", orgId)
|
|
509
|
-
.executeTakeFirst();
|
|
510
|
-
if (peek?.status !== "upgrading")
|
|
511
|
-
return [];
|
|
512
|
-
await lockOrg(t, orgId);
|
|
513
|
-
const row = await t
|
|
514
|
-
.selectFrom("plugin_installs as a")
|
|
515
|
-
.innerJoin("catalog_items as i", "i.id", "a.item_id")
|
|
516
|
-
.select([
|
|
517
|
-
"a.status",
|
|
518
|
-
"a.upgrade",
|
|
519
|
-
"a.item_id",
|
|
520
|
-
"i.name",
|
|
521
|
-
sql `coalesce((a.upgrade->>'startedAt')::timestamptz < now() - make_interval(mins => ${staleMinutes}), false)`.as("stale"),
|
|
522
|
-
])
|
|
523
|
-
.where("a.id", "=", installId)
|
|
524
|
-
.where("a.org_id", "=", orgId)
|
|
525
|
-
.forUpdate("a")
|
|
526
|
-
.executeTakeFirst();
|
|
527
|
-
if (row?.status !== "upgrading" || !row.stale)
|
|
528
|
-
return [];
|
|
529
|
-
const steps = journalEntries(row.upgrade);
|
|
530
|
-
const out = await this.installer.undoUpgradeIn(t, orgId, actor, installId, steps, "plugin_upgrade_cleanup");
|
|
514
|
+
for (const [id, pinned] of diff.suggest) {
|
|
531
515
|
await t
|
|
532
|
-
.updateTable("
|
|
533
|
-
.set({
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
.where("id", "=", installId)
|
|
516
|
+
.updateTable("platform_skill_versions as v")
|
|
517
|
+
.set({ suggest_pinned: pinned })
|
|
518
|
+
.from("platform_skills as s")
|
|
519
|
+
.whereRef("s.id", "=", "v.skill_id")
|
|
520
|
+
.whereRef("s.current_version", "=", "v.version")
|
|
521
|
+
.where("s.id", "=", id)
|
|
539
522
|
.execute();
|
|
540
|
-
const j = row.upgrade;
|
|
541
|
-
await audit(t, {
|
|
542
|
-
actorAccountId: actor,
|
|
543
|
-
orgId,
|
|
544
|
-
action: "plugin.org_upgrade_failed",
|
|
545
|
-
target: installId,
|
|
546
|
-
detail: {
|
|
547
|
-
itemId: row.item_id,
|
|
548
|
-
name: row.name,
|
|
549
|
-
from: j?.from ?? null,
|
|
550
|
-
to: j?.to ?? null,
|
|
551
|
-
step: "interrupted",
|
|
552
|
-
code: "internal",
|
|
553
|
-
rolledBack: steps,
|
|
554
|
-
},
|
|
555
|
-
});
|
|
556
|
-
return out;
|
|
557
|
-
});
|
|
558
|
-
for (const r of removed) {
|
|
559
|
-
if (r.kind === "extension")
|
|
560
|
-
await this.d.orgConfigs.afterDisable(orgId, r.ref);
|
|
561
523
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
* else uses them; one still used (by an agent, a connector or another extension) stays in the
|
|
567
|
-
* ledger marked `dropped` ("no longer in the plugin", still this install's), every other removed
|
|
568
|
-
* component leaves the ledger; a dropped component the target brings back is un-dropped. A dependency
|
|
569
|
-
* install is uninstalled by the same rules (another install using it takes it over). Skills ->
|
|
570
|
-
* connectors -> extension -> dependencies.
|
|
571
|
-
*/
|
|
572
|
-
async removeIn(t, orgId, actor, diff, disabled) {
|
|
573
|
-
const report = { removed: [], kept: [] };
|
|
574
|
-
const reason = "plugin_upgrade";
|
|
575
|
-
const keep = (kind, ref, why) => report.kept.push({ kind, ref, reason: why });
|
|
576
|
-
const row = (kind, ref) => t
|
|
577
|
-
.updateTable("plugin_install_components")
|
|
578
|
-
.where("install_id", "=", diff.installId)
|
|
579
|
-
.where("kind", "=", kind)
|
|
580
|
-
.where("ref", "=", ref);
|
|
581
|
-
const dropRow = (kind, ref) => t
|
|
582
|
-
.deleteFrom("plugin_install_components")
|
|
583
|
-
.where("install_id", "=", diff.installId)
|
|
584
|
-
.where("kind", "=", kind)
|
|
585
|
-
.where("ref", "=", ref)
|
|
586
|
-
.execute();
|
|
587
|
-
const removed = [
|
|
588
|
-
...diff.skills.flatMap((x) => (x.change === "removed" && x.ledger ? [x.ledger] : [])),
|
|
589
|
-
...diff.agentTemplates.flatMap((x) => (x.change === "removed" && x.ledger ? [x.ledger] : [])),
|
|
590
|
-
...diff.templates.flatMap((x) => (x.change === "removed" && x.ledger ? [x.ledger] : [])),
|
|
591
|
-
...(diff.extension?.change === "removed"
|
|
592
|
-
? diff.ledger.filter((l) => l.kind === "extension" && l.ref === diff.extension?.name)
|
|
593
|
-
: []),
|
|
594
|
-
];
|
|
595
|
-
const agentRefs = await this.installer.agentRefs(t, orgId);
|
|
596
|
-
const self = new Set([diff.installId]);
|
|
597
|
-
for (const l of removed) {
|
|
598
|
-
if (!l.created) {
|
|
599
|
-
await dropRow(l.kind, l.ref);
|
|
600
|
-
keep(l.kind, l.ref, "pre_existing");
|
|
524
|
+
// Removals (spec §7.3): kept while agents use it; otherwise soft-deleted
|
|
525
|
+
const now = sql `now()`;
|
|
526
|
+
for (const c of diff.components) {
|
|
527
|
+
if (c.change !== "removed" || c.id === null || c.kept !== undefined)
|
|
601
528
|
continue;
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
529
|
+
const table = c.kind === "skill"
|
|
530
|
+
? "platform_skills"
|
|
531
|
+
: c.kind === "agent_template"
|
|
532
|
+
? "platform_agent_templates"
|
|
533
|
+
: c.kind === "theme"
|
|
534
|
+
? "platform_themes"
|
|
535
|
+
: "platform_connector_templates";
|
|
536
|
+
await t
|
|
537
|
+
.updateTable(table)
|
|
538
|
+
.set({ deleted_at: now, updated_at: now })
|
|
539
|
+
.where("id", "=", c.id)
|
|
540
|
+
.execute();
|
|
541
|
+
}
|
|
542
|
+
// Pins of linked copies: moved to the plugin's version (spec §7.1)
|
|
543
|
+
for (const c of diff.components) {
|
|
544
|
+
if (c.change === "removed" || c.id === null || c.pinnedOrgs.length === 0)
|
|
611
545
|
continue;
|
|
546
|
+
if (c.kind === "skill") {
|
|
547
|
+
await t
|
|
548
|
+
.updateTable("skills")
|
|
549
|
+
.set({ pinned_version: null, updated_at: now })
|
|
550
|
+
.where("platform_skill_id", "=", c.id)
|
|
551
|
+
.where("org_id", "in", c.pinnedOrgs)
|
|
552
|
+
.where("pinned_version", "is not", null)
|
|
553
|
+
.execute();
|
|
612
554
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
555
|
+
else if (c.kind === "agent_template") {
|
|
556
|
+
await t
|
|
557
|
+
.updateTable("agent_templates")
|
|
558
|
+
.set({ pinned_version: null, updated_at: now })
|
|
559
|
+
.where("platform_template_id", "=", c.id)
|
|
560
|
+
.where("org_id", "in", c.pinnedOrgs)
|
|
561
|
+
.where("pinned_version", "is not", null)
|
|
562
|
+
.execute();
|
|
618
563
|
}
|
|
619
|
-
else if (outcome !== "gone")
|
|
620
|
-
keep(l.kind, l.ref, outcome);
|
|
621
564
|
}
|
|
622
|
-
//
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
:
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
: []),
|
|
638
|
-
];
|
|
639
|
-
for (const b of back)
|
|
640
|
-
await row(b.kind, b.ref).set({ dropped: false }).execute();
|
|
641
|
-
for (const dep of diff.dependencies) {
|
|
642
|
-
if (dep.change !== "removed" || !dep.child)
|
|
643
|
-
continue;
|
|
644
|
-
const ref = dep.child.installId;
|
|
645
|
-
await dropRow("plugin", ref);
|
|
646
|
-
if (!dep.child.ledger.created) {
|
|
647
|
-
keep("plugin", ref, "pre_existing");
|
|
648
|
-
continue;
|
|
565
|
+
// Connectors made from changed templates, in every org (ruling E2)
|
|
566
|
+
const orgs = [...new Set(diff.connectors.map((c) => c.orgId))].sort();
|
|
567
|
+
for (const orgId of orgs) {
|
|
568
|
+
if (!liveOrgs.has(orgId)) {
|
|
569
|
+
// Locked before the item (P3-50): an org not locked then is deleted (its connectors go
|
|
570
|
+
// with it), or its connector was made since, which changes what the update does
|
|
571
|
+
const live = await t
|
|
572
|
+
.selectFrom("orgs")
|
|
573
|
+
.select("id")
|
|
574
|
+
.where("id", "=", orgId)
|
|
575
|
+
.where("deleted_at", "is", null)
|
|
576
|
+
.executeTakeFirst();
|
|
577
|
+
if (live === undefined)
|
|
578
|
+
continue;
|
|
579
|
+
throw stale();
|
|
649
580
|
}
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
581
|
+
for (const c of diff.connectors.filter((x) => x.orgId === orgId)) {
|
|
582
|
+
const prepared = await this.prepare(actor, itemId, diff.to.version, c);
|
|
583
|
+
await this.connectors.applyTemplateIn(orgId, c.id, actor, prepared, opts.actorTokenId);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
// One version for the deployment: every live org install of the plugin moves with it (one
|
|
587
|
+
// still installing too, and a legacy `upgrading` row; an install marked installed later
|
|
588
|
+
// records the platform version current at its commit, PluginInstaller.markInstalled)
|
|
589
|
+
await t
|
|
590
|
+
.updateTable("plugin_installs")
|
|
591
|
+
.set({ version: diff.to.version, error: null })
|
|
592
|
+
.where("item_id", "=", itemId)
|
|
593
|
+
.where("status", "in", ["installing", "installed", "upgrading"])
|
|
594
|
+
.execute();
|
|
595
|
+
if (owner !== undefined || confirmPending !== undefined) {
|
|
596
|
+
// An org's version becomes its latest once applied or confirmed (ruling P3-34)
|
|
597
|
+
await t
|
|
598
|
+
.updateTable("catalog_items")
|
|
599
|
+
.set({ latest_version: diff.to.version })
|
|
600
|
+
.where("id", "=", itemId)
|
|
601
|
+
.execute();
|
|
602
|
+
await markVersionApplied(t, itemId, diff.to.version);
|
|
603
|
+
// An owner's new version replaces a version waiting for the super admin (pre-flight F7):
|
|
604
|
+
// their confirmation of it is then refused (409 extension.not_pending); the super admin's
|
|
605
|
+
// confirmation applied it
|
|
606
|
+
await t
|
|
607
|
+
.updateTable("catalog_items")
|
|
608
|
+
.set({ pending_version: null, pending_by: null, pending_at: null })
|
|
609
|
+
.where("id", "=", itemId)
|
|
610
|
+
.where("pending_version", "is not", null)
|
|
611
|
+
.execute();
|
|
612
|
+
}
|
|
613
|
+
if (confirmPending !== undefined && pendingOwner !== null) {
|
|
614
|
+
await addOrgNotice(t, pendingOwner, "upload_confirmed", {
|
|
615
|
+
itemId,
|
|
616
|
+
name: diff.name,
|
|
617
|
+
displayName: await itemDisplayName(t, itemId),
|
|
618
|
+
version: diff.to.version,
|
|
658
619
|
});
|
|
659
|
-
for (const r of sub.removed)
|
|
660
|
-
if (r.kind === "extension")
|
|
661
|
-
disabled.push(r.ref);
|
|
662
|
-
if (outcome === "removed")
|
|
663
|
-
report.removed.push({ kind: "plugin", ref });
|
|
664
|
-
else if (outcome === "kept")
|
|
665
|
-
keep("plugin", ref, "used_by_other_install");
|
|
666
620
|
}
|
|
667
|
-
|
|
621
|
+
// The orgs using a shared org-owned plugin are told, one notice per plugin (a platform-owned
|
|
622
|
+
// plugin tells nobody); a plugin never synced before has no version to come from
|
|
623
|
+
if (diff.from !== null) {
|
|
624
|
+
await notifySharedUpdate(t, { kind: "plugin", id: itemId }, { name: diff.name, from: diff.from, to: diff.to.version });
|
|
625
|
+
}
|
|
626
|
+
await audit(t, {
|
|
627
|
+
actorAccountId: actor,
|
|
628
|
+
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
629
|
+
action: "plugin.platform_updated",
|
|
630
|
+
target: itemId,
|
|
631
|
+
detail: {
|
|
632
|
+
name: diff.name,
|
|
633
|
+
from: diff.from,
|
|
634
|
+
to: diff.to.version,
|
|
635
|
+
...(owner !== undefined && { ownerOrgId: owner.orgId }),
|
|
636
|
+
components: diff.components.map((c) => ({
|
|
637
|
+
kind: c.kind,
|
|
638
|
+
name: c.name,
|
|
639
|
+
change: c.change,
|
|
640
|
+
...(c.kept !== undefined && { kept: true }),
|
|
641
|
+
...(c.pinnedOrgs.length > 0 && c.change !== "removed" && { unpinned: c.pinnedOrgs }),
|
|
642
|
+
})),
|
|
643
|
+
...(diff.extension && { extension: extensionView(diff.extension) }),
|
|
644
|
+
connectors: diff.connectors.map((c) => ({
|
|
645
|
+
orgId: c.orgId,
|
|
646
|
+
id: c.id,
|
|
647
|
+
credentialsReset: c.credentialsReset,
|
|
648
|
+
})),
|
|
649
|
+
...opts.auditDetail,
|
|
650
|
+
},
|
|
651
|
+
});
|
|
652
|
+
const enqueue = [itemId, ...diff.dependencies];
|
|
653
|
+
afterCommit(async () => {
|
|
654
|
+
for (const id of enqueue) {
|
|
655
|
+
try {
|
|
656
|
+
await this.sync.enqueueItem(id);
|
|
657
|
+
}
|
|
658
|
+
catch (err) {
|
|
659
|
+
this.log.warn("enqueueing the scope sync after a platform update failed", {
|
|
660
|
+
itemId: id,
|
|
661
|
+
err,
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
return diff;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* The template update of one connector: the new endpoint preset with the org's values at the
|
|
670
|
+
* editable paths, the auth preset and default policies; credentials cleared (no new ones: they
|
|
671
|
+
* are the org's) when the credential shape changed.
|
|
672
|
+
*/
|
|
673
|
+
async prepare(actor, itemId, version, c) {
|
|
674
|
+
const template = c.file.template;
|
|
675
|
+
const endpoint = structuredClone(template.endpoint);
|
|
676
|
+
for (const e of template.editableEndpoint ?? []) {
|
|
677
|
+
const v = getPath(c.endpoint, e);
|
|
678
|
+
if (v !== undefined)
|
|
679
|
+
setPath(endpoint, e, v);
|
|
680
|
+
}
|
|
681
|
+
const input = {
|
|
682
|
+
endpoint,
|
|
683
|
+
auth: template.auth,
|
|
684
|
+
template: {
|
|
685
|
+
itemId,
|
|
686
|
+
version,
|
|
687
|
+
templateId: c.templateId,
|
|
688
|
+
...(template.defaultToolPolicies !== undefined && {
|
|
689
|
+
defaultToolPolicies: template.defaultToolPolicies,
|
|
690
|
+
}),
|
|
691
|
+
},
|
|
692
|
+
resetCredentials: false,
|
|
693
|
+
};
|
|
694
|
+
// Checked without credentials (nothing outbound); a changed shape then clears the old ones
|
|
695
|
+
const prepared = await this.connectors.prepareTemplateUpdate(actor, c.connector, input);
|
|
696
|
+
return c.credentialsReset
|
|
697
|
+
? { ...prepared, input: { ...prepared.input, resetCredentials: true } }
|
|
698
|
+
: prepared;
|
|
668
699
|
}
|
|
669
700
|
/**
|
|
670
|
-
* Computes an
|
|
671
|
-
*
|
|
701
|
+
* Computes an update (see the class comment). `target`: the target read from an org's staging
|
|
702
|
+
* instead of `catalog_item_versions` (pre-flight F3). `owner`: an owner update (P3-12): the item
|
|
703
|
+
* must be the org's, an extension-bearing target is refused, and a target dropping the
|
|
704
|
+
* extension removes it.
|
|
672
705
|
*/
|
|
673
|
-
async diff(
|
|
674
|
-
const db = this.
|
|
675
|
-
if (!UUID_RE.test(
|
|
676
|
-
throw
|
|
677
|
-
const
|
|
678
|
-
.selectFrom("
|
|
679
|
-
.
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
706
|
+
async diff(itemId, version, o = {}) {
|
|
707
|
+
const db = this.db;
|
|
708
|
+
if (!UUID_RE.test(itemId))
|
|
709
|
+
throw itemNotFound();
|
|
710
|
+
const item = await db
|
|
711
|
+
.selectFrom("catalog_items")
|
|
712
|
+
.select([
|
|
713
|
+
"id",
|
|
714
|
+
"name",
|
|
715
|
+
"disabled",
|
|
716
|
+
"builtin",
|
|
717
|
+
"deleted_at",
|
|
718
|
+
"platform_synced_version",
|
|
719
|
+
"owner_org_id",
|
|
720
|
+
"awaiting_confirmation",
|
|
721
|
+
"pending_version",
|
|
722
|
+
"latest_version",
|
|
723
|
+
])
|
|
724
|
+
.where("id", "=", itemId)
|
|
683
725
|
.executeTakeFirst();
|
|
684
|
-
if (!
|
|
685
|
-
throw
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
726
|
+
if (!item || item.deleted_at !== null)
|
|
727
|
+
throw itemNotFound();
|
|
728
|
+
// A version waiting for the super admin applies only through their confirmation (P3-9, F8)
|
|
729
|
+
if (o.confirmPending !== version) {
|
|
730
|
+
if (item.awaiting_confirmation)
|
|
731
|
+
throw itemPendingError(item.name);
|
|
732
|
+
if (item.pending_version !== null && item.pending_version === version) {
|
|
733
|
+
throw itemPendingError(item.name, version);
|
|
734
|
+
}
|
|
735
|
+
// The super admin's generic update of an org's plugin reaches only its applied version
|
|
736
|
+
// (`latest_version`, ruling P3-34/P3-37): one the org uploaded that was never applied or
|
|
737
|
+
// confirmed (a rejected or failed one) is not theirs to apply
|
|
738
|
+
if (o.owner === undefined && item.owner_org_id !== null && version !== item.latest_version) {
|
|
739
|
+
throw notApplied(item.name, version);
|
|
740
|
+
}
|
|
692
741
|
}
|
|
693
|
-
if (
|
|
694
|
-
throw
|
|
742
|
+
if (o.owner !== undefined && item.owner_org_id !== o.owner.orgId)
|
|
743
|
+
throw itemNotFound();
|
|
744
|
+
if (item.disabled) {
|
|
745
|
+
throw new ApiError("catalog.item_disabled", "This plugin is disabled on the deployment; enable it before updating");
|
|
695
746
|
}
|
|
696
|
-
const
|
|
747
|
+
const name = item.name;
|
|
748
|
+
const versions = (await db
|
|
697
749
|
.selectFrom("catalog_item_versions")
|
|
698
750
|
.select([
|
|
699
751
|
"version",
|
|
@@ -701,519 +753,773 @@ export class PluginUpgrader {
|
|
|
701
753
|
"object_prefix",
|
|
702
754
|
"files",
|
|
703
755
|
"extension_sha256",
|
|
704
|
-
"
|
|
705
|
-
"
|
|
756
|
+
"applied_at",
|
|
757
|
+
"rejected_at",
|
|
706
758
|
])
|
|
707
759
|
.where("item_id", "=", itemId)
|
|
708
|
-
.execute();
|
|
709
|
-
const
|
|
710
|
-
|
|
711
|
-
if (!fromRow) {
|
|
712
|
-
throw new ApiError("catalog.item_not_found", `The installed version ${install.version} is no longer in the enterprise catalog`);
|
|
713
|
-
}
|
|
714
|
-
if (!toRow)
|
|
760
|
+
.execute());
|
|
761
|
+
const to = o.target ?? versions.find((v) => v.version === version);
|
|
762
|
+
if (!to)
|
|
715
763
|
throw new ApiError("catalog.item_not_found", `Version ${version} of this item not found`);
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
764
|
+
// Whoever owns the item now (a transfer keeps the version rows), the generic update never
|
|
765
|
+
// reaches a version that was rejected or never applied (ruling P3-52)
|
|
766
|
+
const row = versions.find((v) => v.version === version);
|
|
767
|
+
if (o.owner === undefined && o.confirmPending !== version && row && !versionUsable(row)) {
|
|
768
|
+
throw notApplied(item.name, version);
|
|
769
|
+
}
|
|
770
|
+
if (o.owner !== undefined && to.manifest.extension) {
|
|
771
|
+
// An org's version with an extension waits for the super admin's confirmation (plan Task 6)
|
|
772
|
+
throw new ApiError("plugin.extension_upload_pending", `Version ${to.version} of plugin ${item.name} has an extension; it applies once a super admin confirms it`);
|
|
773
|
+
}
|
|
774
|
+
const from = item.platform_synced_version;
|
|
775
|
+
const fromRow = versions.find((v) => v.version === from);
|
|
776
|
+
if (from === to.version) {
|
|
777
|
+
// Confirming a preview whose update already ran (a concurrent confirm won): stale
|
|
778
|
+
if (o.pre)
|
|
721
779
|
throw stale();
|
|
722
|
-
throw targetInvalid(`
|
|
723
|
-
{ reason: "same_version", version: from
|
|
780
|
+
throw targetInvalid(`The platform already runs version ${from} of plugin ${name}`, [
|
|
781
|
+
{ reason: "same_version", version: from },
|
|
724
782
|
]);
|
|
725
783
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
784
|
+
const target = await this.extensionTarget(name, fromRow, to, o.owner !== undefined);
|
|
785
|
+
let extension;
|
|
786
|
+
if (o.pre) {
|
|
787
|
+
// The confirm's transaction: the extension this update moved is expected in place (a
|
|
788
|
+
// removed one gone)
|
|
789
|
+
if (o.pre.extension) {
|
|
790
|
+
const row = await db
|
|
791
|
+
.selectFrom("extension_installs")
|
|
792
|
+
.select("sha256")
|
|
793
|
+
.where("name", "=", name)
|
|
794
|
+
.executeTakeFirst();
|
|
795
|
+
if ((row?.sha256 ?? null) !== o.pre.extension.sha256)
|
|
796
|
+
throw stale();
|
|
797
|
+
extension = o.pre.extension;
|
|
740
798
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
.innerJoin("plugin_installs as a", "a.id", "c.install_id")
|
|
746
|
-
.innerJoin("catalog_item_versions as v", (j) => j.onRef("v.item_id", "=", "a.item_id").onRef("v.version", "=", "a.version"))
|
|
747
|
-
.innerJoin("catalog_items as i", "i.id", "a.item_id")
|
|
748
|
-
.select(["i.name", "v.manifest"])
|
|
749
|
-
.where("c.kind", "=", "plugin")
|
|
750
|
-
.where("c.ref", "=", installId)
|
|
751
|
-
.where("a.org_id", "=", orgId)
|
|
752
|
-
.where("a.status", "<>", "failed")
|
|
753
|
-
.execute();
|
|
754
|
-
for (const p of parents) {
|
|
755
|
-
const range = p.manifest.dependencies?.find((x) => x.name === name)?.version;
|
|
756
|
-
if (range !== undefined && !satisfiesRange(to.version, range)) {
|
|
757
|
-
throw targetInvalid(`Plugin ${p.name} installed in this organization depends on ${name}@${range}, which version ${to.version} does not satisfy`, [{ reason: "dependent_range", dependent: p.name, range, version: to.version }]);
|
|
799
|
+
else {
|
|
800
|
+
if (target !== null)
|
|
801
|
+
throw stale();
|
|
802
|
+
extension = null;
|
|
758
803
|
}
|
|
759
804
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const change = !from.manifest.extension
|
|
767
|
-
? "added"
|
|
768
|
-
: !to.manifest.extension
|
|
769
|
-
? "removed"
|
|
770
|
-
: from.extension_sha256 !== to.extension_sha256 ||
|
|
771
|
-
from.manifest.extension.manifest.version !== to.manifest.extension.manifest.version
|
|
772
|
-
? "changed"
|
|
773
|
-
: "unchanged";
|
|
774
|
-
extension = { change, name };
|
|
775
|
-
if (change === "added") {
|
|
776
|
-
await this.installer.planExtension(orgId, to.manifest);
|
|
777
|
-
extensionConfig = !(await isExtensionEnabled(db, orgId, name));
|
|
778
|
-
}
|
|
779
|
-
components.push({
|
|
780
|
-
kind: "extension",
|
|
781
|
-
ref: name,
|
|
782
|
-
change,
|
|
783
|
-
...(change === "changed" && {
|
|
784
|
-
detail: `${from.manifest.extension?.manifest.version} -> ${to.manifest.extension?.manifest.version}`,
|
|
785
|
-
}),
|
|
786
|
-
});
|
|
805
|
+
else {
|
|
806
|
+
extension = target && {
|
|
807
|
+
...target,
|
|
808
|
+
needsApproval: target.sha256 !== null && (await this.needsApproval(name, target.sha256)),
|
|
809
|
+
orgs: [],
|
|
810
|
+
};
|
|
787
811
|
}
|
|
788
|
-
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
const
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
});
|
|
812
|
+
const contents = o.pre?.contents ?? (await this.readContents(to));
|
|
813
|
+
const dependencies = await this.checkDependents(name, to);
|
|
814
|
+
// The platform's components of the plugin and the target's
|
|
815
|
+
const live = await this.liveComponents(itemId);
|
|
816
|
+
const components = [];
|
|
817
|
+
const suggest = new Map();
|
|
818
|
+
const direction = (fromVersion) => fromVersion === null || compareVersions(to.version, fromVersion) >= 0
|
|
819
|
+
? "upgrade"
|
|
820
|
+
: "downgrade";
|
|
821
|
+
const added = (kind, n) => ({
|
|
822
|
+
kind,
|
|
823
|
+
id: null,
|
|
824
|
+
name: n,
|
|
825
|
+
change: "added",
|
|
826
|
+
from: null,
|
|
827
|
+
to: to.version,
|
|
828
|
+
updatedOnOwn: false,
|
|
829
|
+
ownScope: false,
|
|
830
|
+
pinnedOrgs: [],
|
|
831
|
+
});
|
|
832
|
+
// Skills (by name, by their files' digest)
|
|
833
|
+
const toSkills = contents.skillNames.map((n, i) => {
|
|
834
|
+
const entry = (to.manifest.skills ?? [])[i];
|
|
835
|
+
return {
|
|
836
|
+
name: n,
|
|
837
|
+
digest: dirDigest(to, packagePath(entry?.path)),
|
|
838
|
+
pinned: entry?.pinned === true,
|
|
839
|
+
};
|
|
840
|
+
});
|
|
841
|
+
for (const s of toSkills) {
|
|
842
|
+
const l = live.skills.find((x) => x.name === s.name);
|
|
843
|
+
if (!l) {
|
|
844
|
+
components.push(added("skill", s.name));
|
|
822
845
|
continue;
|
|
823
846
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
847
|
+
const same = skillFilesDigest(l.manifest.files) === s.digest;
|
|
848
|
+
if (same && l.suggestPinned !== s.pinned)
|
|
849
|
+
suggest.set(l.id, s.pinned);
|
|
850
|
+
components.push({
|
|
851
|
+
kind: "skill",
|
|
852
|
+
id: l.id,
|
|
853
|
+
name: s.name,
|
|
854
|
+
change: same ? "same" : direction(l.catalogVersion),
|
|
855
|
+
from: l.catalogVersion,
|
|
856
|
+
to: to.version,
|
|
857
|
+
updatedOnOwn: l.updatedOnOwn,
|
|
858
|
+
ownScope: l.ownScope,
|
|
859
|
+
pinnedOrgs: [],
|
|
834
860
|
});
|
|
835
861
|
}
|
|
836
|
-
for (const
|
|
837
|
-
if (
|
|
862
|
+
for (const l of live.skills) {
|
|
863
|
+
if (toSkills.some((s) => s.name === l.name))
|
|
838
864
|
continue;
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
865
|
+
components.push({
|
|
866
|
+
kind: "skill",
|
|
867
|
+
id: l.id,
|
|
868
|
+
name: l.name,
|
|
842
869
|
change: "removed",
|
|
843
|
-
|
|
844
|
-
|
|
870
|
+
from: l.catalogVersion,
|
|
871
|
+
to: null,
|
|
872
|
+
updatedOnOwn: l.updatedOnOwn,
|
|
873
|
+
ownScope: l.ownScope,
|
|
874
|
+
pinnedOrgs: [],
|
|
845
875
|
});
|
|
846
876
|
}
|
|
847
|
-
|
|
877
|
+
// Agent templates (by name, canonical definition)
|
|
878
|
+
const toAgents = contents.agents;
|
|
879
|
+
for (const a of toAgents) {
|
|
880
|
+
const l = live.agentTemplates.find((x) => x.name === a.template.name);
|
|
881
|
+
if (!l) {
|
|
882
|
+
components.push(added("agent_template", a.template.name));
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
const same = canonicalJson(l.definition) === canonicalJson(a.template);
|
|
848
886
|
components.push({
|
|
849
|
-
kind: "
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
887
|
+
kind: "agent_template",
|
|
888
|
+
id: l.id,
|
|
889
|
+
name: l.name,
|
|
890
|
+
change: same ? "same" : direction(l.catalogVersion),
|
|
891
|
+
from: l.catalogVersion,
|
|
892
|
+
to: to.version,
|
|
893
|
+
updatedOnOwn: l.updatedOnOwn,
|
|
894
|
+
ownScope: l.ownScope,
|
|
895
|
+
pinnedOrgs: [],
|
|
856
896
|
});
|
|
857
897
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
const toNames = await catalogSkillNames(this.d.storage, to, to.manifest);
|
|
861
|
-
const dirOf = (m, i) => packagePath((m.skills ?? [])[i]?.path);
|
|
862
|
-
const fromSkills = new Map(fromNames.map((n, i) => [n, dirOf(from.manifest, i)]));
|
|
863
|
-
const toSkills = new Map(toNames.map((n, i) => [n, dirOf(to.manifest, i)]));
|
|
864
|
-
const toPinned = new Set(toNames.filter((_, i) => (to.manifest.skills ?? [])[i]?.pinned === true));
|
|
865
|
-
const skillRefs = ledger.filter((l) => l.kind === "skill").map((l) => l.ref);
|
|
866
|
-
const liveSkills = skillRefs.length === 0
|
|
867
|
-
? []
|
|
868
|
-
: await db
|
|
869
|
-
.selectFrom("skills")
|
|
870
|
-
.select(["id", "name"])
|
|
871
|
-
.where("id", "in", skillRefs)
|
|
872
|
-
.where("org_id", "=", orgId)
|
|
873
|
-
.where("deleted_at", "is", null)
|
|
874
|
-
.execute();
|
|
875
|
-
const ledgerOfSkill = (n) => {
|
|
876
|
-
const s = liveSkills.find((x) => x.name === n);
|
|
877
|
-
return s && ledger.find((l) => l.kind === "skill" && l.ref === s.id);
|
|
878
|
-
};
|
|
879
|
-
const skills = [];
|
|
880
|
-
for (const [n, dir] of toSkills) {
|
|
881
|
-
const before = fromSkills.get(n);
|
|
882
|
-
const l = ledgerOfSkill(n);
|
|
883
|
-
const change = before === undefined
|
|
884
|
-
? "added"
|
|
885
|
-
: dirDigest(from, before) === dirDigest(to, dir)
|
|
886
|
-
? "unchanged"
|
|
887
|
-
: "changed";
|
|
888
|
-
skills.push({
|
|
889
|
-
name: n,
|
|
890
|
-
change,
|
|
891
|
-
dir,
|
|
892
|
-
suggestPinned: toPinned.has(n),
|
|
893
|
-
...(l && { ledger: l }),
|
|
894
|
-
});
|
|
895
|
-
}
|
|
896
|
-
for (const n of fromSkills.keys()) {
|
|
897
|
-
if (toSkills.has(n))
|
|
898
|
+
for (const l of live.agentTemplates) {
|
|
899
|
+
if (toAgents.some((a) => a.template.name === l.name))
|
|
898
900
|
continue;
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
dependencies: dependencies
|
|
911
|
-
.filter((x) => x.change === "added")
|
|
912
|
-
.map((x) => ({ plan: x.plan ?? null })),
|
|
913
|
-
});
|
|
914
|
-
if (conflicts.length > 0)
|
|
915
|
-
throw skillConflictError(conflicts);
|
|
916
|
-
// Agent templates (by name; phase C)
|
|
917
|
-
const fromAgents = await readCatalogAgentTemplates(this.d.storage, from);
|
|
918
|
-
const toAgents = await readCatalogAgentTemplates(this.d.storage, to);
|
|
919
|
-
const templateRefs = ledger.filter((l) => l.kind === "agent_template").map((l) => l.ref);
|
|
920
|
-
const liveTemplates = templateRefs.length === 0
|
|
921
|
-
? []
|
|
922
|
-
: await db
|
|
923
|
-
.selectFrom("agent_templates")
|
|
924
|
-
.select(["id", "name"])
|
|
925
|
-
.where("id", "in", templateRefs)
|
|
926
|
-
.where("org_id", "=", orgId)
|
|
927
|
-
.where("deleted_at", "is", null)
|
|
928
|
-
.execute();
|
|
929
|
-
const ledgerOfTemplate = (n) => {
|
|
930
|
-
const r = liveTemplates.find((x) => x.name === n);
|
|
931
|
-
return r && ledger.find((l) => l.kind === "agent_template" && l.ref === r.id);
|
|
932
|
-
};
|
|
933
|
-
const agentTemplates = [];
|
|
934
|
-
for (const a of toAgents) {
|
|
935
|
-
const n = a.template.name;
|
|
936
|
-
const before = fromAgents.find((x) => x.template.name === n);
|
|
937
|
-
const l = ledgerOfTemplate(n);
|
|
938
|
-
const change = before === undefined
|
|
939
|
-
? "added"
|
|
940
|
-
: canonicalJson(before.template) === canonicalJson(a.template)
|
|
941
|
-
? "unchanged"
|
|
942
|
-
: "changed";
|
|
943
|
-
agentTemplates.push({ name: n, change, template: a.template, ...(l && { ledger: l }) });
|
|
944
|
-
}
|
|
945
|
-
for (const a of fromAgents) {
|
|
946
|
-
const n = a.template.name;
|
|
947
|
-
if (toAgents.some((x) => x.template.name === n))
|
|
948
|
-
continue;
|
|
949
|
-
const l = ledgerOfTemplate(n);
|
|
950
|
-
agentTemplates.push({ name: n, change: "removed", ...(l && { ledger: l }) });
|
|
951
|
-
}
|
|
952
|
-
for (const a of agentTemplates) {
|
|
953
|
-
components.push({ kind: "agent_template", ref: a.name, change: a.change });
|
|
901
|
+
components.push({
|
|
902
|
+
kind: "agent_template",
|
|
903
|
+
id: l.id,
|
|
904
|
+
name: l.name,
|
|
905
|
+
change: "removed",
|
|
906
|
+
from: l.catalogVersion,
|
|
907
|
+
to: null,
|
|
908
|
+
updatedOnOwn: l.updatedOnOwn,
|
|
909
|
+
ownScope: l.ownScope,
|
|
910
|
+
pinnedOrgs: [],
|
|
911
|
+
});
|
|
954
912
|
}
|
|
955
|
-
// Connector templates (by id)
|
|
956
|
-
const
|
|
957
|
-
const toTemplates = await readCatalogTemplates(this.d.storage, to);
|
|
958
|
-
// The install's connectors by template; a dropped one (kept only for the agents using it) counts
|
|
959
|
-
// only while its connector is live, so a template the target brings back maps onto it
|
|
960
|
-
const connectorRows = ledger.filter((l) => l.kind === "connector" && l.template_id !== null);
|
|
961
|
-
const liveConnectors = connectorRows.length === 0
|
|
962
|
-
? []
|
|
963
|
-
: await db
|
|
964
|
-
.selectFrom("connectors")
|
|
965
|
-
.select(["id", "connector", "endpoint", "auth"])
|
|
966
|
-
.where("id", "in", connectorRows.map((l) => l.ref))
|
|
967
|
-
.where("org_id", "=", orgId)
|
|
968
|
-
.where("deleted_at", "is", null)
|
|
969
|
-
.execute();
|
|
970
|
-
const connectorOf = (templateId) => {
|
|
971
|
-
const rows = connectorRows.filter((x) => x.template_id === templateId);
|
|
972
|
-
const l = rows.find((x) => !x.dropped) ??
|
|
973
|
-
rows.find((x) => liveConnectors.some((c) => c.id === x.ref));
|
|
974
|
-
const c = l && liveConnectors.find((x) => x.id === l.ref);
|
|
975
|
-
return {
|
|
976
|
-
...(l && { ledger: l }),
|
|
977
|
-
...(c && {
|
|
978
|
-
connector: {
|
|
979
|
-
id: c.id,
|
|
980
|
-
connector: c.connector,
|
|
981
|
-
endpoint: c.endpoint,
|
|
982
|
-
auth: c.auth,
|
|
983
|
-
},
|
|
984
|
-
}),
|
|
985
|
-
};
|
|
986
|
-
};
|
|
913
|
+
// Connector templates (by id, canonical file) and the connectors made from them
|
|
914
|
+
const toTemplates = contents.templates;
|
|
987
915
|
const deps = this.installer.templateDeps();
|
|
988
|
-
const
|
|
916
|
+
const connectors = [];
|
|
917
|
+
const shippedOff = (f) => f.defaultEnabled === false;
|
|
918
|
+
/** Templates whose `defaultEnabled` the target flips: id -> shipped off, and the platform id. */
|
|
919
|
+
const flipped = new Map();
|
|
920
|
+
const flippedIds = new Map();
|
|
989
921
|
for (const ct of toTemplates) {
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
if (!before && mapped.ledger?.dropped && mapped.connector) {
|
|
994
|
-
// Back in the plugin (an earlier upgrade dropped it, its connector was kept): the kept
|
|
995
|
-
// connector is updated to the template, not created again (its slug would be taken)
|
|
922
|
+
const l = live.templates.find((x) => x.name === ct.id);
|
|
923
|
+
if (!l) {
|
|
924
|
+
const problem = templatePluginProblem(deps, ct.file.template);
|
|
996
925
|
if (problem !== undefined)
|
|
997
926
|
throw new ApiError("catalog.not_deployed", problem);
|
|
998
|
-
|
|
999
|
-
throw targetInvalid(`Connector template ${ct.id} comes back for another connector (${ct.file.template.plugin} "${ct.file.template.connector}"); uninstall the plugin and install the new version instead`, [
|
|
1000
|
-
{
|
|
1001
|
-
reason: "template_connector",
|
|
1002
|
-
template: ct.id,
|
|
1003
|
-
plugin: ct.file.template.plugin,
|
|
1004
|
-
connector: ct.file.template.connector,
|
|
1005
|
-
},
|
|
1006
|
-
]);
|
|
1007
|
-
}
|
|
1008
|
-
const credentialsChanged = credentialKey(mapped.connector.auth) !==
|
|
1009
|
-
credentialKey(ct.file.template.auth);
|
|
1010
|
-
templates.push({
|
|
1011
|
-
id: ct.id,
|
|
1012
|
-
change: "changed",
|
|
1013
|
-
target: ct.file,
|
|
1014
|
-
...mapped,
|
|
1015
|
-
credentialsChanged,
|
|
1016
|
-
});
|
|
927
|
+
components.push(added("connector_template", ct.id));
|
|
1017
928
|
continue;
|
|
1018
929
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
930
|
+
const same = canonicalJson(l.file) === canonicalJson(ct.file);
|
|
931
|
+
components.push({
|
|
932
|
+
kind: "connector_template",
|
|
933
|
+
id: l.id,
|
|
934
|
+
name: ct.id,
|
|
935
|
+
change: same ? "same" : direction(l.version),
|
|
936
|
+
from: l.version,
|
|
937
|
+
to: to.version,
|
|
938
|
+
updatedOnOwn: false,
|
|
939
|
+
ownScope: l.ownScope,
|
|
940
|
+
pinnedOrgs: [],
|
|
941
|
+
});
|
|
942
|
+
if (same)
|
|
1023
943
|
continue;
|
|
944
|
+
if (shippedOff(l.file) !== shippedOff(ct.file)) {
|
|
945
|
+
flipped.set(ct.id, shippedOff(ct.file));
|
|
946
|
+
flippedIds.set(ct.id, l.id);
|
|
1024
947
|
}
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
948
|
+
const before = l.file.template;
|
|
949
|
+
const after = ct.file.template;
|
|
950
|
+
if (before.plugin !== after.plugin || before.connector !== after.connector) {
|
|
951
|
+
throw targetInvalid(`Connector template ${ct.id} moves to another connector (${after.plugin} "${after.connector}"); remove the plugin and import the new version as a new plugin instead`, [
|
|
952
|
+
{
|
|
953
|
+
reason: "template_connector",
|
|
954
|
+
template: ct.id,
|
|
955
|
+
plugin: after.plugin,
|
|
956
|
+
connector: after.connector,
|
|
957
|
+
},
|
|
958
|
+
]);
|
|
959
|
+
}
|
|
960
|
+
const made = await db
|
|
961
|
+
.selectFrom("connectors")
|
|
962
|
+
.select(["id", "org_id", "name", "connector", "endpoint", "auth"])
|
|
963
|
+
.where("platform_template_id", "=", l.id)
|
|
964
|
+
.where("deleted_at", "is", null)
|
|
965
|
+
.orderBy("org_id")
|
|
966
|
+
.orderBy("id")
|
|
967
|
+
.execute();
|
|
968
|
+
if (made.length > 0) {
|
|
969
|
+
const problem = templatePluginProblem(deps, after);
|
|
970
|
+
if (problem !== undefined)
|
|
1039
971
|
throw new ApiError("catalog.not_deployed", problem);
|
|
1040
|
-
}
|
|
1041
972
|
}
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
973
|
+
for (const c of made) {
|
|
974
|
+
connectors.push({
|
|
975
|
+
orgId: c.org_id,
|
|
976
|
+
id: c.id,
|
|
977
|
+
name: c.name,
|
|
978
|
+
connector: c.connector,
|
|
979
|
+
endpoint: c.endpoint,
|
|
980
|
+
templateId: ct.id,
|
|
981
|
+
file: ct.file,
|
|
982
|
+
credentialsReset: credentialKey(c.auth) !==
|
|
983
|
+
credentialKey(after.auth),
|
|
984
|
+
});
|
|
985
|
+
}
|
|
1047
986
|
}
|
|
1048
|
-
for (const
|
|
1049
|
-
if (toTemplates.some((x) => x.id ===
|
|
987
|
+
for (const l of live.templates) {
|
|
988
|
+
if (toTemplates.some((x) => x.id === l.name))
|
|
1050
989
|
continue;
|
|
1051
|
-
|
|
1052
|
-
|
|
990
|
+
components.push({
|
|
991
|
+
kind: "connector_template",
|
|
992
|
+
id: l.id,
|
|
993
|
+
name: l.name,
|
|
1053
994
|
change: "removed",
|
|
1054
|
-
|
|
1055
|
-
|
|
995
|
+
from: l.version,
|
|
996
|
+
to: null,
|
|
997
|
+
updatedOnOwn: false,
|
|
998
|
+
ownScope: l.ownScope,
|
|
999
|
+
pinnedOrgs: [],
|
|
1056
1000
|
});
|
|
1057
1001
|
}
|
|
1058
|
-
|
|
1002
|
+
// Themes (by id, canonical definition and their assets' digest)
|
|
1003
|
+
const toThemes = contents.themes;
|
|
1004
|
+
for (const th of toThemes) {
|
|
1005
|
+
const l = live.themes.find((x) => x.name === th.id);
|
|
1006
|
+
if (!l) {
|
|
1007
|
+
components.push(added("theme", th.id));
|
|
1008
|
+
continue;
|
|
1009
|
+
}
|
|
1010
|
+
const same = canonicalJson(l.definition) === canonicalJson(th.theme) &&
|
|
1011
|
+
l.assetsDigest === th.assetsDigest;
|
|
1059
1012
|
components.push({
|
|
1060
|
-
kind: "
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1013
|
+
kind: "theme",
|
|
1014
|
+
id: l.id,
|
|
1015
|
+
name: th.id,
|
|
1016
|
+
change: same ? "same" : direction(l.catalogVersion),
|
|
1017
|
+
from: l.catalogVersion,
|
|
1018
|
+
to: to.version,
|
|
1019
|
+
updatedOnOwn: false,
|
|
1020
|
+
ownScope: l.ownScope,
|
|
1021
|
+
pinnedOrgs: [],
|
|
1067
1022
|
});
|
|
1068
1023
|
}
|
|
1069
|
-
const
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1024
|
+
for (const l of live.themes) {
|
|
1025
|
+
if (toThemes.some((x) => x.id === l.name))
|
|
1026
|
+
continue;
|
|
1027
|
+
components.push({
|
|
1028
|
+
kind: "theme",
|
|
1029
|
+
id: l.id,
|
|
1030
|
+
name: l.name,
|
|
1031
|
+
change: "removed",
|
|
1032
|
+
from: l.catalogVersion,
|
|
1033
|
+
to: null,
|
|
1034
|
+
updatedOnOwn: false,
|
|
1035
|
+
ownScope: l.ownScope,
|
|
1036
|
+
pinnedOrgs: [],
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
// The orgs where the plugin is on (a live install; builtin: every org)
|
|
1040
|
+
const onOrgs = await this.pluginOrgs(itemId, item.builtin);
|
|
1041
|
+
if (extension)
|
|
1042
|
+
extension = { ...extension, orgs: onOrgs };
|
|
1043
|
+
// Rule 10: an added skill must not take a name already used where the plugin is on
|
|
1044
|
+
const conflicts = [];
|
|
1045
|
+
for (const c of components) {
|
|
1046
|
+
if (c.kind !== "skill" || c.change !== "added")
|
|
1047
|
+
continue;
|
|
1048
|
+
for (const orgId of onOrgs) {
|
|
1049
|
+
const ids = [
|
|
1050
|
+
...(await clashingOrgSkills(db, orgId, { id: "", itemId }, c.name)),
|
|
1051
|
+
...(await clashingPlatformSkills(db, orgId, { id: "" }, c.name)).map((x) => x.id),
|
|
1052
|
+
];
|
|
1053
|
+
if (ids.length > 0)
|
|
1054
|
+
conflicts.push({ skill: c.name, orgId, conflicts: ids.sort() });
|
|
1082
1055
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1056
|
+
}
|
|
1057
|
+
if (conflicts.length > 0) {
|
|
1058
|
+
throw new ApiError("plugin.skill_conflict", `The update adds skills whose names organizations already use where the plugin is on (${[...new Set(conflicts.map((c) => c.skill))].join(", ")}); remove or rename those skills first`, conflicts);
|
|
1059
|
+
}
|
|
1060
|
+
// Themes spec §7: an update never removes the platform default theme; rule 10 (§6): an added
|
|
1061
|
+
// theme must not take an id already on where the plugin is on
|
|
1062
|
+
const removedThemes = components
|
|
1063
|
+
.filter((c) => c.kind === "theme" && c.change === "removed" && c.id !== null)
|
|
1064
|
+
.map((c) => c.id);
|
|
1065
|
+
await assertNotPlatformDefault(db, removedThemes, () => "gone");
|
|
1066
|
+
const themeConflicts = [];
|
|
1067
|
+
for (const c of components) {
|
|
1068
|
+
if (c.kind !== "theme" || c.change !== "added")
|
|
1069
|
+
continue;
|
|
1070
|
+
for (const orgId of onOrgs) {
|
|
1071
|
+
const clash = await themeIdClashes(db, orgId, null, c.name);
|
|
1072
|
+
if (clash.length > 0) {
|
|
1073
|
+
themeConflicts.push({
|
|
1074
|
+
theme: c.name,
|
|
1075
|
+
orgId,
|
|
1076
|
+
themes: clash.map((x) => x.id),
|
|
1077
|
+
plugins: clash.map((x) => x.plugin ?? "platform"),
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1085
1080
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1081
|
+
}
|
|
1082
|
+
if (themeConflicts.length > 0) {
|
|
1083
|
+
throw new ApiError("theme.id_taken", `The update adds themes whose ids are already on in organizations where the plugin is on (${[...new Set(themeConflicts.map((c) => c.theme))].join(", ")}); switch those themes off there first`, themeConflicts);
|
|
1084
|
+
}
|
|
1085
|
+
const themes = await this.themesLost(removedThemes);
|
|
1086
|
+
// Pinned copies (in orgs where the component is on) and removed components agents use
|
|
1087
|
+
for (const kind of ["skill", "agent_template"]) {
|
|
1088
|
+
const mine = components.filter((c) => c.kind === kind && c.id !== null);
|
|
1089
|
+
if (mine.length === 0)
|
|
1090
|
+
continue;
|
|
1091
|
+
const pins = kind === "skill"
|
|
1092
|
+
? await db
|
|
1093
|
+
.selectFrom("skills")
|
|
1094
|
+
.select(["org_id", "platform_skill_id as platform_id"])
|
|
1095
|
+
.where("platform_skill_id", "in", mine.map((c) => c.id))
|
|
1096
|
+
.where("pinned_version", "is not", null)
|
|
1097
|
+
.where("deleted_at", "is", null)
|
|
1098
|
+
.execute()
|
|
1099
|
+
: await db
|
|
1100
|
+
.selectFrom("agent_templates")
|
|
1101
|
+
.select(["org_id", "platform_template_id as platform_id"])
|
|
1102
|
+
.where("platform_template_id", "in", mine.map((c) => c.id))
|
|
1103
|
+
.where("pinned_version", "is not", null)
|
|
1104
|
+
.where("deleted_at", "is", null)
|
|
1105
|
+
.execute();
|
|
1106
|
+
const facts = mine.map((c) => {
|
|
1107
|
+
const l = (kind === "skill" ? live.skills : live.agentTemplates).find((x) => x.id === c.id);
|
|
1108
|
+
return {
|
|
1109
|
+
id: c.id,
|
|
1110
|
+
itemId,
|
|
1111
|
+
scopeMode: l?.scopeMode ?? "follow",
|
|
1112
|
+
scope: l?.scope ?? "optional",
|
|
1113
|
+
disabled: l?.disabled ?? false,
|
|
1114
|
+
};
|
|
1115
|
+
});
|
|
1116
|
+
const st = await loadScopeState(db, kind, facts);
|
|
1117
|
+
for (const c of mine) {
|
|
1118
|
+
const f = facts.find((x) => x.id === c.id);
|
|
1119
|
+
if (!f)
|
|
1089
1120
|
continue;
|
|
1090
|
-
|
|
1091
|
-
|
|
1121
|
+
const orgsPinned = [
|
|
1122
|
+
...new Set(pins.filter((p) => p.platform_id === c.id).map((p) => p.org_id)),
|
|
1123
|
+
];
|
|
1124
|
+
c.pinnedOrgs = orgsPinned
|
|
1125
|
+
.filter((orgId) => componentOn(f, pluginFactsOf(st, itemId, orgId), listedIn(st, f.id, orgId), switchOf(st, f.id, orgId)))
|
|
1126
|
+
.sort();
|
|
1127
|
+
if (c.change !== "removed")
|
|
1092
1128
|
continue;
|
|
1093
|
-
|
|
1129
|
+
const kept = [];
|
|
1130
|
+
for (const orgId of await this.liveOrgs()) {
|
|
1131
|
+
const agents = await agentsUsing(db, orgId, kind, [c.id]);
|
|
1132
|
+
if (agents.length > 0) {
|
|
1133
|
+
kept.push({ orgId, agents: agents.map((a) => ({ id: a.id, name: a.name })) });
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
if (kept.length > 0)
|
|
1137
|
+
c.kept = kept;
|
|
1094
1138
|
}
|
|
1095
1139
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1140
|
+
// The org connectors: changed templates' connectors, templates turned on (needing input) or off
|
|
1141
|
+
const addedTemplates = components
|
|
1142
|
+
.filter((c) => c.kind === "connector_template" && c.change === "added")
|
|
1143
|
+
.map((c) => c.name)
|
|
1144
|
+
// an added template shipped off is on nowhere (no org can have switched it on yet)
|
|
1145
|
+
.filter((id) => {
|
|
1146
|
+
const f = toTemplates.find((x) => x.id === id)?.file;
|
|
1147
|
+
return item.builtin || f === undefined || !shippedOff(f);
|
|
1148
|
+
});
|
|
1149
|
+
const byOrg = new Map();
|
|
1150
|
+
const entry = (orgId) => {
|
|
1151
|
+
const e = byOrg.get(orgId) ?? { orgId, connectors: [], needsConfig: [] };
|
|
1152
|
+
byOrg.set(orgId, e);
|
|
1153
|
+
return e;
|
|
1154
|
+
};
|
|
1155
|
+
for (const c of connectors) {
|
|
1156
|
+
entry(c.orgId).connectors.push({
|
|
1157
|
+
id: c.id,
|
|
1158
|
+
name: c.name,
|
|
1159
|
+
templateId: c.templateId,
|
|
1160
|
+
credentialsReset: c.credentialsReset,
|
|
1161
|
+
});
|
|
1115
1162
|
}
|
|
1116
|
-
|
|
1163
|
+
if (addedTemplates.length > 0) {
|
|
1164
|
+
for (const orgId of onOrgs) {
|
|
1165
|
+
const on = await connectorTemplatesOn(db, orgId, itemId, addedTemplates);
|
|
1166
|
+
if (on.size > 0)
|
|
1167
|
+
entry(orgId).needsConfig.push(...on);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
if (flipped.size > 0) {
|
|
1171
|
+
const ids = [...flipped.keys()].sort();
|
|
1172
|
+
for (const orgId of onOrgs) {
|
|
1173
|
+
const before = await connectorTemplatesOn(db, orgId, itemId, ids);
|
|
1174
|
+
const after = await connectorTemplatesOn(db, orgId, itemId, ids, flipped);
|
|
1175
|
+
for (const id of ids) {
|
|
1176
|
+
const platformId = flippedIds.get(id);
|
|
1177
|
+
if (after.has(id) && !before.has(id)) {
|
|
1178
|
+
// connectors already made from it (it was on before) need no input
|
|
1179
|
+
if ((await connectorsMadeFrom(db, orgId, platformId)) === 0) {
|
|
1180
|
+
entry(orgId).needsConfig.push(id);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
else if (before.has(id) && !after.has(id)) {
|
|
1184
|
+
const agents = await agentsUsing(db, orgId, "connector_template", [platformId]);
|
|
1185
|
+
const e = entry(orgId);
|
|
1186
|
+
e.turnedOff = [
|
|
1187
|
+
...(e.turnedOff ?? []),
|
|
1188
|
+
{
|
|
1189
|
+
templateId: id,
|
|
1190
|
+
agents: agents.map((a) => ({ id: a.id, name: a.name })),
|
|
1191
|
+
connectorsKept: await connectorsMadeFrom(db, orgId, platformId),
|
|
1192
|
+
},
|
|
1193
|
+
];
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
const connectorOrgs = [...byOrg.values()]
|
|
1199
|
+
.map((e) => ({
|
|
1200
|
+
...e,
|
|
1201
|
+
needsConfig: e.needsConfig.sort(),
|
|
1202
|
+
connectors: e.connectors.sort((a, b) => `${a.templateId}\0${a.id}`.localeCompare(`${b.templateId}\0${b.id}`)),
|
|
1203
|
+
}))
|
|
1204
|
+
.sort((a, b) => a.orgId.localeCompare(b.orgId));
|
|
1205
|
+
components.sort((a, b) => KIND_ORDER[a.kind] - KIND_ORDER[b.kind] || a.name.localeCompare(b.name));
|
|
1117
1206
|
const diffHash = sha256(canonicalJson({
|
|
1118
|
-
|
|
1119
|
-
from
|
|
1207
|
+
itemId,
|
|
1208
|
+
from,
|
|
1120
1209
|
to: to.version,
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1210
|
+
manifest: to.manifest,
|
|
1211
|
+
files: filesDigest(to),
|
|
1212
|
+
// `needsApproval` is shown only: it does not change what the confirm does
|
|
1213
|
+
extension: extension && {
|
|
1214
|
+
from: extension.from,
|
|
1215
|
+
to: extension.to,
|
|
1216
|
+
orgs: extension.orgs,
|
|
1217
|
+
sha256: extension.sha256,
|
|
1218
|
+
},
|
|
1124
1219
|
components,
|
|
1125
|
-
|
|
1220
|
+
connectors: connectors.map((c) => ({
|
|
1221
|
+
id: c.id,
|
|
1222
|
+
endpoint: c.endpoint,
|
|
1223
|
+
reset: c.credentialsReset,
|
|
1224
|
+
})),
|
|
1225
|
+
connectorOrgs,
|
|
1226
|
+
// only when present: a diff without themes keeps the hash it had before themes
|
|
1227
|
+
...(themes !== undefined && { themes }),
|
|
1126
1228
|
}));
|
|
1127
1229
|
return {
|
|
1128
|
-
installId,
|
|
1129
1230
|
itemId,
|
|
1130
1231
|
name,
|
|
1131
1232
|
from,
|
|
1132
1233
|
to,
|
|
1133
|
-
|
|
1234
|
+
components,
|
|
1134
1235
|
extension,
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1236
|
+
connectors,
|
|
1237
|
+
connectorOrgs,
|
|
1238
|
+
...(themes !== undefined && { themes }),
|
|
1239
|
+
suggest,
|
|
1240
|
+
contents,
|
|
1138
1241
|
dependencies,
|
|
1139
|
-
components,
|
|
1140
|
-
inputs,
|
|
1141
1242
|
diffHash,
|
|
1142
|
-
ledgerHash: lh,
|
|
1143
|
-
actions: [...actions],
|
|
1144
|
-
creates,
|
|
1145
|
-
updates,
|
|
1146
1243
|
};
|
|
1147
1244
|
}
|
|
1148
1245
|
/**
|
|
1149
|
-
* The
|
|
1150
|
-
*
|
|
1151
|
-
* the credentials it needs changed (then the input must give what the template needs).
|
|
1246
|
+
* The target's skill names, agent templates, connector templates and themes, from object storage
|
|
1247
|
+
* (a theme failing its checks -> 400 `theme.invalid`, themes spec §6).
|
|
1152
1248
|
*/
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1249
|
+
async readContents(to) {
|
|
1250
|
+
return {
|
|
1251
|
+
skillNames: await catalogSkillNames(this.storage, to, to.manifest),
|
|
1252
|
+
agents: await readCatalogAgentTemplates(this.storage, to),
|
|
1253
|
+
templates: await readCatalogTemplates(this.storage, to),
|
|
1254
|
+
themes: await readCatalogThemes(this.storage, to),
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Whether the target's extension package asks for permissions the approved snapshot does not
|
|
1259
|
+
* cover (no snapshot, or a blocking addition): it then loads only once approved (§7.4).
|
|
1260
|
+
*/
|
|
1261
|
+
async needsApproval(name, sha) {
|
|
1262
|
+
if (this.config.get().extensionPermissions.autoApprove)
|
|
1263
|
+
return false;
|
|
1264
|
+
const pkg = await readExtensionPackage(await this.blobs.get(sha), {
|
|
1265
|
+
maxBytes: this.config.get().packages.maxBytes,
|
|
1266
|
+
hostSdkVersion: SDK_VERSION,
|
|
1267
|
+
});
|
|
1268
|
+
const snap = await this.db
|
|
1269
|
+
.selectFrom("extension_permission_snapshots")
|
|
1270
|
+
.select("permissions")
|
|
1271
|
+
.where("plugin", "=", name)
|
|
1272
|
+
.executeTakeFirst();
|
|
1273
|
+
if (!snap)
|
|
1274
|
+
return true;
|
|
1275
|
+
const { added } = diffPermissions(snap.permissions, permissionSetOfPackage(pkg));
|
|
1276
|
+
return blockingKeys(added).length > 0;
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* The deployment's extension step: none when the target carries the extension the deployment
|
|
1280
|
+
* runs; a version without the extension the deployment runs for the plugin is refused, except
|
|
1281
|
+
* for an owner update (`allowRemove`, ruling P3-12': removing code runs none), which removes an
|
|
1282
|
+
* installed one; a move of a config-declared extension is refused.
|
|
1283
|
+
*/
|
|
1284
|
+
async extensionTarget(name, from, to, allowRemove = false) {
|
|
1285
|
+
const want = to.manifest.extension;
|
|
1286
|
+
const row = await this.db
|
|
1287
|
+
.selectFrom("extension_installs")
|
|
1288
|
+
.select(["sha256", "version"])
|
|
1289
|
+
.where("name", "=", name)
|
|
1290
|
+
.executeTakeFirst();
|
|
1291
|
+
// Only an extension declared in the startup config runs without an install record; one this
|
|
1292
|
+
// replica still has loaded after its uninstall (until its reconcile) does not count
|
|
1293
|
+
const declared = this.registry.declared().get(name) === "config";
|
|
1294
|
+
const loaded = declared ? this.registry.manifests().find((m) => m.name === name) : undefined;
|
|
1295
|
+
if (!want) {
|
|
1296
|
+
if (allowRemove && from?.manifest.extension && row && !declared) {
|
|
1297
|
+
return { from: row.version, to: null, sha256: null, previous: row.sha256 };
|
|
1298
|
+
}
|
|
1299
|
+
if (from?.manifest.extension && (row || declared)) {
|
|
1300
|
+
throw targetInvalid(`Version ${to.version} of plugin ${name} has no extension, but the deployment runs it; uninstall the extension first`, [{ reason: "extension_removed", version: to.version }]);
|
|
1163
1301
|
}
|
|
1302
|
+
return null;
|
|
1164
1303
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
if (v !== undefined)
|
|
1169
|
-
setPath(endpoint, e, v);
|
|
1304
|
+
if (row) {
|
|
1305
|
+
if (row.sha256 === to.extension_sha256)
|
|
1306
|
+
return null;
|
|
1170
1307
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
}
|
|
1181
|
-
if (!oauth && given?.client !== undefined) {
|
|
1182
|
-
throw fail(`${path}.client`, "This connector does not use OAuth; provide credential instead");
|
|
1183
|
-
}
|
|
1308
|
+
else if (declared) {
|
|
1309
|
+
if (loaded?.version === want.manifest.version)
|
|
1310
|
+
return null;
|
|
1311
|
+
throw targetInvalid(`The extension of plugin ${name} is declared in the startup config at version ${loaded?.version ?? "(not loaded)"}; it cannot be moved to ${want.manifest.version} by an update`, [{ reason: "config_extension", deploymentVersion: loaded?.version ?? null }]);
|
|
1312
|
+
}
|
|
1313
|
+
if (to.extension_sha256 === null) {
|
|
1314
|
+
throw targetInvalid(`Version ${to.version} of plugin ${name} has no extension package`, [
|
|
1315
|
+
{ reason: "extension_package", version: to.version },
|
|
1316
|
+
]);
|
|
1184
1317
|
}
|
|
1185
|
-
const credential = oauth ? given?.client : given?.credential;
|
|
1186
1318
|
return {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
version,
|
|
1192
|
-
templateId: c.id,
|
|
1193
|
-
...(template.defaultToolPolicies !== undefined && {
|
|
1194
|
-
defaultToolPolicies: template.defaultToolPolicies,
|
|
1195
|
-
}),
|
|
1196
|
-
},
|
|
1197
|
-
resetCredentials: c.credentialsChanged,
|
|
1198
|
-
...(c.credentialsChanged && credential !== undefined && { credential }),
|
|
1319
|
+
from: row?.version ?? null,
|
|
1320
|
+
to: want.manifest.version,
|
|
1321
|
+
sha256: to.extension_sha256,
|
|
1322
|
+
previous: row?.sha256 ?? null,
|
|
1199
1323
|
};
|
|
1200
1324
|
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Other platform plugins depending on this one must accept the target (their platform version's
|
|
1327
|
+
* dependency range); returns the catalog items of the target's own dependencies (their scope
|
|
1328
|
+
* sync is enqueued after the update: rule 9).
|
|
1329
|
+
*/
|
|
1330
|
+
async checkDependents(name, to) {
|
|
1331
|
+
const rows = await this.db
|
|
1332
|
+
.selectFrom("catalog_items as i")
|
|
1333
|
+
.innerJoin("catalog_item_versions as v", (j) => j
|
|
1334
|
+
.onRef("v.item_id", "=", "i.id")
|
|
1335
|
+
.on(sql `v.version`, "=", sql `coalesce(i.platform_synced_version, i.latest_version)`))
|
|
1336
|
+
.select(["i.id", "i.name", "v.manifest"])
|
|
1337
|
+
.where("i.deleted_at", "is", null)
|
|
1338
|
+
.execute();
|
|
1339
|
+
for (const r of rows) {
|
|
1340
|
+
if (r.name === name)
|
|
1341
|
+
continue;
|
|
1342
|
+
const range = r.manifest.dependencies?.find((d) => d.name === name)?.version;
|
|
1343
|
+
if (range !== undefined && !satisfiesRange(to.version, range)) {
|
|
1344
|
+
throw targetInvalid(`Plugin ${r.name} depends on ${name}@${range}, which version ${to.version} does not satisfy`, [{ reason: "dependent_range", dependent: r.name, range, version: to.version }]);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
const wanted = new Set((to.manifest.dependencies ?? []).map((d) => d.name));
|
|
1348
|
+
return rows.filter((r) => wanted.has(r.name)).map((r) => r.id);
|
|
1349
|
+
}
|
|
1350
|
+
/** The plugin's live platform components with their current versions. */
|
|
1351
|
+
async liveComponents(itemId) {
|
|
1352
|
+
const db = this.db;
|
|
1353
|
+
const skills = (await db
|
|
1354
|
+
.selectFrom("platform_skills as p")
|
|
1355
|
+
.innerJoin("platform_skill_versions as v", (j) => j.onRef("v.skill_id", "=", "p.id").onRef("v.version", "=", "p.current_version"))
|
|
1356
|
+
.select([
|
|
1357
|
+
"p.id",
|
|
1358
|
+
"p.name",
|
|
1359
|
+
"p.scope_mode",
|
|
1360
|
+
"p.scope",
|
|
1361
|
+
"p.disabled",
|
|
1362
|
+
"v.manifest",
|
|
1363
|
+
"v.catalog_version",
|
|
1364
|
+
"v.updated_on_own",
|
|
1365
|
+
"v.suggest_pinned",
|
|
1366
|
+
])
|
|
1367
|
+
.where("p.catalog_item_id", "=", itemId)
|
|
1368
|
+
.where("p.deleted_at", "is", null)
|
|
1369
|
+
.execute()).map((r) => ({
|
|
1370
|
+
id: r.id,
|
|
1371
|
+
name: r.name,
|
|
1372
|
+
scopeMode: r.scope_mode,
|
|
1373
|
+
scope: r.scope,
|
|
1374
|
+
disabled: r.disabled,
|
|
1375
|
+
manifest: r.manifest,
|
|
1376
|
+
catalogVersion: r.catalog_version,
|
|
1377
|
+
updatedOnOwn: r.updated_on_own,
|
|
1378
|
+
ownScope: r.scope_mode === "own",
|
|
1379
|
+
suggestPinned: r.suggest_pinned,
|
|
1380
|
+
}));
|
|
1381
|
+
const agentTemplates = (await db
|
|
1382
|
+
.selectFrom("platform_agent_templates as p")
|
|
1383
|
+
.innerJoin("platform_agent_template_versions as v", (j) => j.onRef("v.template_id", "=", "p.id").onRef("v.version", "=", "p.current_version"))
|
|
1384
|
+
.select([
|
|
1385
|
+
"p.id",
|
|
1386
|
+
"p.name",
|
|
1387
|
+
"p.scope_mode",
|
|
1388
|
+
"p.scope",
|
|
1389
|
+
"p.disabled",
|
|
1390
|
+
"v.definition",
|
|
1391
|
+
"v.catalog_version",
|
|
1392
|
+
"v.updated_on_own",
|
|
1393
|
+
])
|
|
1394
|
+
.where("p.catalog_item_id", "=", itemId)
|
|
1395
|
+
.where("p.deleted_at", "is", null)
|
|
1396
|
+
.execute()).map((r) => ({
|
|
1397
|
+
id: r.id,
|
|
1398
|
+
name: r.name,
|
|
1399
|
+
scopeMode: r.scope_mode,
|
|
1400
|
+
scope: r.scope,
|
|
1401
|
+
disabled: r.disabled,
|
|
1402
|
+
definition: r.definition,
|
|
1403
|
+
catalogVersion: r.catalog_version,
|
|
1404
|
+
updatedOnOwn: r.updated_on_own,
|
|
1405
|
+
ownScope: r.scope_mode === "own",
|
|
1406
|
+
}));
|
|
1407
|
+
const templates = (await db
|
|
1408
|
+
.selectFrom("platform_connector_templates")
|
|
1409
|
+
.select(["id", "template_id", "current_version", "file", "scope_mode"])
|
|
1410
|
+
.where("catalog_item_id", "=", itemId)
|
|
1411
|
+
.where("deleted_at", "is", null)
|
|
1412
|
+
.execute()).map((r) => ({
|
|
1413
|
+
id: r.id,
|
|
1414
|
+
name: r.template_id,
|
|
1415
|
+
version: r.current_version,
|
|
1416
|
+
file: r.file,
|
|
1417
|
+
ownScope: r.scope_mode === "own",
|
|
1418
|
+
}));
|
|
1419
|
+
const themes = (await db
|
|
1420
|
+
.selectFrom("platform_themes as p")
|
|
1421
|
+
.innerJoin("platform_theme_versions as v", (j) => j.onRef("v.theme_id", "=", "p.id").onRef("v.version", "=", "p.current_version"))
|
|
1422
|
+
.leftJoin("catalog_item_versions as cv", (j) => j
|
|
1423
|
+
.onRef("cv.item_id", "=", "p.catalog_item_id")
|
|
1424
|
+
.onRef("cv.version", "=", "v.catalog_version"))
|
|
1425
|
+
.select(["p.id", "p.name", "p.scope_mode", "v.definition", "v.catalog_version", "cv.files"])
|
|
1426
|
+
.where("p.catalog_item_id", "=", itemId)
|
|
1427
|
+
.where("p.deleted_at", "is", null)
|
|
1428
|
+
.execute()).map((r) => ({
|
|
1429
|
+
id: r.id,
|
|
1430
|
+
name: r.name,
|
|
1431
|
+
definition: r.definition,
|
|
1432
|
+
catalogVersion: r.catalog_version,
|
|
1433
|
+
// no recorded files (should not happen): never equal, the update writes a new version
|
|
1434
|
+
assetsDigest: r.files === null ? null : themeAssetsDigest(r.files, r.definition),
|
|
1435
|
+
ownScope: r.scope_mode === "own",
|
|
1436
|
+
}));
|
|
1437
|
+
return { skills, agentTemplates, templates, themes };
|
|
1438
|
+
}
|
|
1439
|
+
/** The `themes` block of the preview: the orgs each of the removed themes `ids` is on in. */
|
|
1440
|
+
async themesLost(ids) {
|
|
1441
|
+
if (ids.length === 0)
|
|
1442
|
+
return undefined;
|
|
1443
|
+
const comps = await loadComponents(this.db, "theme", { ids });
|
|
1444
|
+
const st = await loadScopeState(this.db, "theme", comps);
|
|
1445
|
+
const orgs = await this.liveOrgs();
|
|
1446
|
+
const lost = new Map();
|
|
1447
|
+
for (const c of comps) {
|
|
1448
|
+
const on = orgs.filter((orgId) => componentOn(c, pluginFactsOf(st, c.itemId, orgId), listedIn(st, c.id, orgId), switchOf(st, c.id, orgId)));
|
|
1449
|
+
lost.set(c.id, new Set(on));
|
|
1450
|
+
}
|
|
1451
|
+
return themesPreview(this.db, lost);
|
|
1452
|
+
}
|
|
1453
|
+
/** The orgs where the plugin is on: a live install (builtin: every live org). */
|
|
1454
|
+
async pluginOrgs(itemId, builtin) {
|
|
1455
|
+
if (builtin)
|
|
1456
|
+
return this.liveOrgs();
|
|
1457
|
+
const rows = await this.db
|
|
1458
|
+
.selectFrom("plugin_installs as a")
|
|
1459
|
+
.innerJoin("orgs as o", "o.id", "a.org_id")
|
|
1460
|
+
.select("a.org_id")
|
|
1461
|
+
.distinct()
|
|
1462
|
+
.where("a.item_id", "=", itemId)
|
|
1463
|
+
.where("a.status", "in", ["installing", "installed", "upgrading"])
|
|
1464
|
+
.where("o.deleted_at", "is", null)
|
|
1465
|
+
.orderBy("a.org_id")
|
|
1466
|
+
.execute();
|
|
1467
|
+
return rows.map((r) => r.org_id);
|
|
1468
|
+
}
|
|
1469
|
+
async liveOrgs() {
|
|
1470
|
+
const rows = await this.db
|
|
1471
|
+
.selectFrom("orgs")
|
|
1472
|
+
.select("id")
|
|
1473
|
+
.where("deleted_at", "is", null)
|
|
1474
|
+
.orderBy("id")
|
|
1475
|
+
.execute();
|
|
1476
|
+
return rows.map((r) => r.id);
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
__decorate([
|
|
1480
|
+
Transactional()
|
|
1481
|
+
], PlatformPluginUpdater.prototype, "authorizeOwner", null);
|
|
1482
|
+
__decorate([
|
|
1483
|
+
Transactional({ propagation: "requires_new" })
|
|
1484
|
+
], PlatformPluginUpdater.prototype, "auditFailure", null);
|
|
1485
|
+
__decorate([
|
|
1486
|
+
Transactional({ propagation: "requires_new" })
|
|
1487
|
+
], PlatformPluginUpdater.prototype, "commit", null);
|
|
1488
|
+
PlatformPluginUpdater = __decorate([
|
|
1489
|
+
Injectable(),
|
|
1490
|
+
__param(0, Inject(KernelDb)),
|
|
1491
|
+
__param(1, Inject(TransactionHost)),
|
|
1492
|
+
__param(2, Inject(SuperAdminLock)),
|
|
1493
|
+
__param(3, Inject(CatalogItemLock)),
|
|
1494
|
+
__param(4, Inject(OrgLock)),
|
|
1495
|
+
__param(5, Inject(LockService)),
|
|
1496
|
+
__param(6, Inject(StorageService)),
|
|
1497
|
+
__param(7, Inject(ExtensionRegistry)),
|
|
1498
|
+
__param(8, Inject(ExtensionAdminOps)),
|
|
1499
|
+
__param(9, Inject(ExtensionBlobs)),
|
|
1500
|
+
__param(10, Inject(KernelConfigService)),
|
|
1501
|
+
__param(11, Inject(PlatformComponents)),
|
|
1502
|
+
__param(12, Inject(PluginInstaller)),
|
|
1503
|
+
__param(13, Inject(ConnectorsService)),
|
|
1504
|
+
__param(14, Inject(PluginScopeSync)),
|
|
1505
|
+
__param(15, Inject(KERNEL_LOGGER))
|
|
1506
|
+
], PlatformPluginUpdater);
|
|
1507
|
+
export { PlatformPluginUpdater };
|
|
1508
|
+
/** The preview of a diff. */
|
|
1509
|
+
function previewOf(d) {
|
|
1510
|
+
return {
|
|
1511
|
+
itemId: d.itemId,
|
|
1512
|
+
name: d.name,
|
|
1513
|
+
from: d.from,
|
|
1514
|
+
to: d.to.version,
|
|
1515
|
+
components: d.components,
|
|
1516
|
+
extension: extensionView(d.extension),
|
|
1517
|
+
connectorOrgs: d.connectorOrgs,
|
|
1518
|
+
...(d.themes !== undefined && { themes: d.themes }),
|
|
1519
|
+
diffHash: d.diffHash,
|
|
1520
|
+
};
|
|
1201
1521
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
return db
|
|
1206
|
-
.selectFrom("plugin_install_components")
|
|
1207
|
-
.select(["kind", "ref", "created", "skill_version", "template_id", "dropped"])
|
|
1208
|
-
.where("install_id", "=", installId)
|
|
1209
|
-
.orderBy("kind")
|
|
1210
|
-
.orderBy("ref")
|
|
1211
|
-
.execute();
|
|
1212
|
-
}
|
|
1213
|
-
/** A fingerprint of the ledger (order independent). */
|
|
1214
|
-
function ledgerHash(rows) {
|
|
1215
|
-
return sha256(rows
|
|
1216
|
-
.map((r) => `${r.kind}\0${r.ref}\0${r.created}\0${r.skill_version}\0${r.template_id}\0${r.dropped}\n`)
|
|
1217
|
-
.sort()
|
|
1218
|
-
.join(""));
|
|
1522
|
+
/** The extension step as the preview and the result show it. */
|
|
1523
|
+
function extensionView(e) {
|
|
1524
|
+
return e && { from: e.from, to: e.to, orgs: e.orgs, needsApproval: e.needsApproval };
|
|
1219
1525
|
}
|