@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.21
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 +94 -5
- package/dist/admin/admin-agents.controller.d.ts +28 -0
- package/dist/admin/admin-agents.controller.js +79 -0
- package/dist/admin/admin-connectors.controller.d.ts +29 -0
- package/dist/admin/admin-connectors.controller.js +79 -0
- package/dist/admin/admin-items.schemas.d.ts +42 -0
- package/dist/admin/admin-items.schemas.js +48 -0
- package/dist/admin/admin.controller.d.ts +52 -80
- package/dist/admin/admin.controller.js +112 -81
- package/dist/admin/admin.module.d.ts +4 -1
- package/dist/admin/admin.module.js +50 -4
- package/dist/admin/admin.schemas.d.ts +69 -0
- package/dist/admin/admin.schemas.js +53 -0
- package/dist/admin/audit.controller.d.ts +14 -0
- package/dist/admin/audit.controller.js +42 -0
- package/dist/admin/audit.schemas.d.ts +8 -0
- package/dist/admin/audit.schemas.js +17 -0
- package/dist/admin/extensions.controller.d.ts +34 -3
- package/dist/admin/extensions.controller.js +66 -8
- package/dist/admin/extensions.schemas.d.ts +7 -0
- package/dist/admin/extensions.schemas.js +10 -0
- package/dist/admin/health.service.d.ts +104 -0
- package/dist/admin/health.service.js +246 -0
- package/dist/admin/limit-defaults.d.ts +20 -0
- package/dist/admin/limit-defaults.js +10 -0
- package/dist/admin/overview.controller.d.ts +31 -0
- package/dist/admin/overview.controller.js +78 -0
- package/dist/admin/overview.schemas.d.ts +8 -0
- package/dist/admin/overview.schemas.js +13 -0
- package/dist/admin/overview.service.d.ts +112 -0
- package/dist/admin/overview.service.js +223 -0
- package/dist/admin/platform-audit.service.d.ts +41 -0
- package/dist/admin/platform-audit.service.js +70 -0
- package/dist/admin/setup-lock.d.ts +1 -1
- package/dist/admin/setup-lock.js +1 -1
- package/dist/admin/setup.controller.d.ts +1 -1
- package/dist/admin/setup.controller.js +1 -1
- package/dist/admin/setup.service.d.ts +4 -4
- package/dist/admin/setup.service.js +8 -8
- package/dist/admin/usage.service.d.ts +149 -0
- package/dist/admin/usage.service.js +321 -0
- package/dist/agents/admin-agents.d.ts +92 -0
- package/dist/agents/admin-agents.js +170 -0
- package/dist/agents/agent-lookup.d.ts +24 -0
- package/dist/agents/agent-lookup.js +46 -2
- 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 +53 -168
- package/dist/agents/agents.controller.js +163 -34
- package/dist/agents/agents.module.d.ts +6 -2
- package/dist/agents/agents.module.js +41 -7
- package/dist/agents/agents.schemas.d.ts +392 -0
- package/dist/agents/agents.schemas.js +126 -0
- package/dist/agents/agents.service.d.ts +121 -36
- package/dist/agents/agents.service.js +411 -121
- package/dist/agents/definition.d.ts +142 -21
- package/dist/agents/definition.js +389 -43
- 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 +876 -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 +77 -5
- package/dist/agents/templates.controller.js +153 -7
- package/dist/agents/templates.d.ts +127 -23
- package/dist/agents/templates.js +482 -44
- package/dist/agents/templates.schemas.d.ts +20 -0
- package/dist/agents/templates.schemas.js +45 -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 +109 -0
- package/dist/background/tasks.service.js +271 -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 +136 -52
- package/dist/catalog/admin-catalog.controller.js +275 -65
- package/dist/catalog/admin-catalog.schemas.d.ts +82 -0
- package/dist/catalog/admin-catalog.schemas.js +99 -0
- package/dist/catalog/appearance.schemas.d.ts +10 -0
- package/dist/catalog/appearance.schemas.js +20 -0
- package/dist/catalog/appearance.service.d.ts +105 -0
- package/dist/catalog/appearance.service.js +306 -0
- package/dist/catalog/catalog-content.d.ts +122 -35
- package/dist/catalog/catalog-content.js +122 -14
- package/dist/catalog/catalog-files.d.ts +42 -0
- package/dist/catalog/catalog-files.js +89 -0
- package/dist/catalog/catalog-import.module.d.ts +7 -0
- package/dist/catalog/catalog-import.module.js +63 -0
- package/dist/catalog/catalog-items.d.ts +122 -7
- package/dist/catalog/catalog-items.js +301 -13
- package/dist/catalog/catalog-scope.service.d.ts +293 -0
- package/dist/catalog/catalog-scope.service.js +1236 -0
- package/dist/catalog/catalog.module.d.ts +7 -9
- package/dist/catalog/catalog.module.js +47 -31
- package/dist/catalog/catalog.service.d.ts +122 -31
- package/dist/catalog/catalog.service.js +177 -105
- package/dist/catalog/claude/agents.js +15 -10
- package/dist/catalog/claude/translate.js +3 -0
- package/dist/catalog/cli.d.ts +11 -1
- package/dist/catalog/cli.js +29 -1
- package/dist/catalog/component-promotion.d.ts +96 -0
- package/dist/catalog/component-promotion.js +395 -0
- package/dist/catalog/component-scope.controller.d.ts +102 -0
- package/dist/catalog/component-scope.controller.js +257 -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 +394 -0
- package/dist/catalog/component-scope.service.js +1133 -0
- package/dist/catalog/component-state.d.ts +207 -0
- package/dist/catalog/component-state.js +484 -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 +30 -0
- package/dist/catalog/job-ids.js +25 -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 +50 -41
- package/dist/catalog/marketplaces.controller.js +130 -46
- package/dist/catalog/marketplaces.schemas.d.ts +48 -0
- package/dist/catalog/marketplaces.schemas.js +53 -0
- package/dist/catalog/marketplaces.service.d.ts +110 -17
- package/dist/catalog/marketplaces.service.js +337 -29
- package/dist/catalog/org-catalog.controller.d.ts +114 -62
- package/dist/catalog/org-catalog.controller.js +191 -98
- package/dist/catalog/org-catalog.schemas.d.ts +104 -0
- package/dist/catalog/org-catalog.schemas.js +107 -0
- package/dist/catalog/org-catalog.service.d.ts +72 -33
- package/dist/catalog/org-catalog.service.js +367 -158
- 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 +133 -0
- package/dist/catalog/org-extension.controller.js +313 -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 +254 -47
- package/dist/catalog/plugin-import.js +810 -112
- package/dist/catalog/plugin-install.d.ts +205 -42
- package/dist/catalog/plugin-install.js +828 -126
- package/dist/catalog/plugin-package.d.ts +43 -4
- package/dist/catalog/plugin-package.js +194 -7
- package/dist/catalog/plugin-upgrade.d.ts +308 -225
- package/dist/catalog/plugin-upgrade.js +1325 -1131
- package/dist/catalog/request-rules.d.ts +65 -0
- package/dist/catalog/request-rules.js +217 -0
- package/dist/catalog/requests.service.d.ts +194 -118
- package/dist/catalog/requests.service.js +530 -343
- package/dist/catalog/reserved-names.d.ts +8 -0
- package/dist/catalog/reserved-names.js +42 -0
- package/dist/catalog/scope-orgs.d.ts +21 -0
- package/dist/catalog/scope-orgs.js +67 -0
- package/dist/catalog/scope-state.d.ts +35 -0
- package/dist/catalog/scope-state.js +87 -0
- package/dist/catalog/scope-sync-workers.d.ts +7 -0
- package/dist/catalog/scope-sync-workers.js +29 -0
- package/dist/catalog/scope-sync.d.ts +176 -0
- package/dist/catalog/scope-sync.js +576 -0
- package/dist/catalog/scope.d.ts +42 -0
- package/dist/catalog/scope.js +42 -0
- package/dist/catalog/unshare.d.ts +22 -0
- package/dist/catalog/unshare.js +119 -0
- package/dist/channels/actions.js +10 -3
- package/dist/channels/cards.d.ts +36 -10
- package/dist/channels/cards.js +100 -25
- package/dist/channels/channels.module.js +13 -2
- package/dist/channels/channels.schemas.d.ts +41 -0
- package/dist/channels/channels.schemas.js +40 -0
- package/dist/channels/connections.controller.d.ts +46 -37
- package/dist/channels/connections.controller.js +76 -34
- package/dist/channels/connections.service.d.ts +102 -10
- package/dist/channels/connections.service.js +271 -24
- package/dist/channels/inbound.d.ts +11 -1
- package/dist/channels/inbound.js +87 -7
- package/dist/channels/outbound.d.ts +14 -1
- package/dist/channels/outbound.js +64 -15
- package/dist/channels/phrases.d.ts +33 -2
- package/dist/channels/phrases.js +29 -1
- package/dist/channels/supervisor.d.ts +2 -0
- package/dist/channels/supervisor.js +4 -0
- package/dist/channels/threads.d.ts +5 -0
- package/dist/channels/threads.js +8 -0
- package/dist/channels/webhook.d.ts +21 -1
- package/dist/channels/webhook.js +39 -4
- package/dist/client/client-access.service.d.ts +102 -0
- package/dist/client/client-access.service.js +303 -0
- package/dist/client/client-builds.service.d.ts +109 -0
- package/dist/client/client-builds.service.js +229 -0
- package/dist/client/client-delivery.controller.d.ts +25 -0
- package/dist/client/client-delivery.controller.js +66 -0
- package/dist/client/client-files.d.ts +48 -0
- package/dist/client/client-files.js +136 -0
- package/dist/client/client-reports.cron.d.ts +13 -0
- package/dist/client/client-reports.cron.js +42 -0
- package/dist/client/client-reports.service.d.ts +30 -0
- package/dist/client/client-reports.service.js +102 -0
- package/dist/client/client-sign-in.service.d.ts +21 -0
- package/dist/client/client-sign-in.service.js +49 -0
- package/dist/client/client.controller.d.ts +49 -0
- package/dist/client/client.controller.js +129 -0
- package/dist/client/client.module.d.ts +8 -0
- package/dist/client/client.module.js +28 -0
- package/dist/client/client.schemas.d.ts +61 -0
- package/dist/client/client.schemas.js +27 -0
- package/dist/config/docs.js +5 -1
- package/dist/config/schema.d.ts +35 -2
- package/dist/config/schema.js +216 -21
- package/dist/conversations/access.d.ts +6 -4
- package/dist/conversations/access.js +29 -5
- package/dist/conversations/agent-tree.d.ts +46 -0
- package/dist/conversations/agent-tree.js +92 -0
- package/dist/conversations/artifacts.d.ts +1 -1
- package/dist/conversations/artifacts.js +1 -1
- package/dist/conversations/attachments.service.d.ts +30 -0
- package/dist/conversations/attachments.service.js +130 -5
- package/dist/conversations/conversations.controller.d.ts +79 -44
- package/dist/conversations/conversations.controller.js +133 -82
- package/dist/conversations/conversations.module.d.ts +1 -1
- package/dist/conversations/conversations.module.js +10 -7
- package/dist/conversations/conversations.schemas.d.ts +52 -0
- package/dist/conversations/conversations.schemas.js +79 -0
- package/dist/conversations/conversations.service.d.ts +161 -13
- package/dist/conversations/conversations.service.js +329 -57
- package/dist/conversations/device-status.d.ts +24 -0
- package/dist/conversations/device-status.js +71 -0
- package/dist/conversations/event-log.d.ts +45 -9
- package/dist/conversations/event-log.js +113 -6
- package/dist/conversations/events.d.ts +255 -9
- package/dist/conversations/events.js +250 -34
- package/dist/conversations/message-context.d.ts +79 -0
- package/dist/conversations/message-context.js +145 -0
- package/dist/conversations/queue.d.ts +5 -2
- package/dist/conversations/queue.js +24 -4
- package/dist/conversations/queue.service.d.ts +2 -2
- package/dist/conversations/queue.service.js +21 -3
- package/dist/conversations/titles.d.ts +12 -3
- package/dist/conversations/titles.js +40 -16
- package/dist/conversations/tree.d.ts +17 -0
- package/dist/conversations/tree.js +42 -0
- package/dist/ctx/create-ctx.d.ts +48 -5
- package/dist/ctx/create-ctx.js +174 -34
- package/dist/db/kernel-schema.d.ts +668 -27
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +3 -0
- package/dist/devices/access.d.ts +66 -0
- package/dist/devices/access.js +113 -0
- package/dist/devices/conversation-devices.d.ts +75 -0
- package/dist/devices/conversation-devices.js +230 -0
- package/dist/devices/devices.controller.d.ts +36 -0
- package/dist/devices/devices.controller.js +124 -0
- package/dist/devices/devices.module.d.ts +8 -0
- package/dist/devices/devices.module.js +34 -0
- package/dist/devices/devices.schemas.d.ts +3 -0
- package/dist/devices/devices.schemas.js +14 -0
- package/dist/devices/devices.service.d.ts +251 -0
- package/dist/devices/devices.service.js +791 -0
- package/dist/devices/dto.d.ts +25 -0
- package/dist/devices/dto.js +12 -0
- package/dist/devices/label.d.ts +11 -0
- package/dist/devices/label.js +25 -0
- package/dist/devices/legacy-cleanup.job.d.ts +34 -0
- package/dist/devices/legacy-cleanup.job.js +141 -0
- package/dist/errors.d.ts +215 -3
- package/dist/errors.js +215 -3
- package/dist/evals/evals.module.js +11 -2
- package/dist/evals/evals.schemas.d.ts +110 -0
- package/dist/evals/evals.schemas.js +107 -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 +20 -3
- package/dist/evals/run-replay.js +78 -14
- package/dist/evals/runs.controller.d.ts +2 -57
- package/dist/evals/runs.controller.js +1 -42
- package/dist/evals/runs.service.d.ts +8 -7
- package/dist/evals/runs.service.js +45 -30
- package/dist/evals/sets.controller.d.ts +2 -28
- package/dist/evals/sets.controller.js +1 -31
- package/dist/evals/sets.service.d.ts +7 -7
- package/dist/evals/sets.service.js +23 -17
- package/dist/evals/snapshot.d.ts +3 -2
- package/dist/evals/snapshot.js +17 -4
- package/dist/evals/step-replay.d.ts +4 -6
- package/dist/evals/step-replay.js +16 -9
- package/dist/evals/trajectory.d.ts +5 -3
- package/dist/evals/trajectory.js +4 -1
- package/dist/evals/trajectory.service.d.ts +8 -3
- package/dist/evals/trajectory.service.js +26 -14
- package/dist/evals/worker.d.ts +5 -5
- package/dist/evals/worker.js +9 -3
- package/dist/extensions/admin-ops.d.ts +81 -14
- package/dist/extensions/admin-ops.js +181 -47
- package/dist/extensions/admin-view.d.ts +57 -10
- package/dist/extensions/admin-view.js +249 -27
- package/dist/extensions/approvals.d.ts +12 -2
- package/dist/extensions/blobs.d.ts +14 -1
- package/dist/extensions/blobs.js +49 -5
- package/dist/extensions/bootstrap.d.ts +85 -10
- package/dist/extensions/bootstrap.js +215 -36
- package/dist/extensions/cli.d.ts +12 -0
- package/dist/extensions/cli.js +11 -2
- package/dist/extensions/config-hash.d.ts +10 -0
- package/dist/extensions/config-hash.js +38 -0
- package/dist/extensions/config-issues.d.ts +13 -1
- package/dist/extensions/config-issues.js +22 -5
- 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 +6 -0
- package/dist/extensions/deployment-config.d.ts +94 -9
- package/dist/extensions/deployment-config.js +255 -34
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/effective-config.d.ts +133 -0
- package/dist/extensions/effective-config.js +379 -0
- package/dist/extensions/extensions.module.js +31 -12
- package/dist/extensions/guide-places.d.ts +68 -0
- package/dist/extensions/guide-places.js +152 -0
- package/dist/extensions/hooks.d.ts +37 -4
- package/dist/extensions/hooks.js +82 -16
- package/dist/extensions/host.d.ts +105 -12
- package/dist/extensions/host.js +372 -87
- package/dist/extensions/installs.d.ts +30 -9
- package/dist/extensions/installs.js +57 -16
- package/dist/extensions/instance.d.ts +17 -2
- package/dist/extensions/instance.js +21 -0
- package/dist/extensions/ledger.d.ts +1 -1
- package/dist/extensions/locks.d.ts +12 -0
- package/dist/extensions/locks.js +26 -0
- package/dist/extensions/org-config.d.ts +97 -7
- package/dist/extensions/org-config.js +215 -45
- 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 +18 -4
- package/dist/extensions/package.js +56 -3
- package/dist/extensions/permission-set.d.ts +35 -5
- package/dist/extensions/permission-set.js +36 -5
- package/dist/extensions/permission-view.d.ts +106 -13
- package/dist/extensions/permission-view.js +33 -15
- package/dist/extensions/plugin-guides.d.ts +282 -0
- package/dist/extensions/plugin-guides.js +554 -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 +1 -1
- package/dist/extensions/registry.js +2 -0
- 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 +13 -2
- package/dist/extensions/sources.js +2 -0
- package/dist/extensions/state.module.d.ts +9 -0
- package/dist/extensions/state.module.js +46 -0
- package/dist/extensions/unavailable.d.ts +50 -0
- package/dist/extensions/unavailable.js +115 -0
- package/dist/files/previewers.controller.js +2 -3
- package/dist/files/previewers.d.ts +10 -3
- package/dist/files/previewers.js +40 -11
- package/dist/files/previewers.schemas.d.ts +10 -0
- package/dist/files/previewers.schemas.js +9 -0
- package/dist/http/api.module.js +76 -4
- package/dist/http/app.d.ts +11 -2
- package/dist/http/app.js +31 -5
- package/dist/http/gateway-routes.d.ts +7 -3
- package/dist/http/gateway-routes.js +6 -3
- 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 +77 -31
- package/dist/identity/accounts.js +133 -52
- package/dist/identity/audit.d.ts +2 -1
- package/dist/identity/auth.controller.js +9 -5
- package/dist/identity/auth.guard.d.ts +13 -5
- package/dist/identity/auth.guard.js +35 -9
- package/dist/identity/cookies.d.ts +26 -5
- package/dist/identity/cookies.js +58 -6
- package/dist/identity/identity.module.d.ts +1 -1
- package/dist/identity/identity.module.js +7 -4
- 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 +17 -1
- package/dist/identity/me.controller.js +45 -4
- 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 +12 -0
- package/dist/identity/sessions.js +45 -0
- package/dist/identity/settings.d.ts +99 -12
- package/dist/identity/settings.js +234 -25
- package/dist/identity/{enterprise-admin.d.ts → super-admin.d.ts} +5 -5
- package/dist/identity/{enterprise-admin.js → super-admin.js} +24 -24
- package/dist/identity/write-actor.d.ts +11 -0
- package/dist/identity/write-actor.js +7 -0
- package/dist/inbox/inbox.module.d.ts +4 -1
- package/dist/inbox/inbox.module.js +7 -3
- package/dist/inbox/inbox.schemas.d.ts +8 -0
- package/dist/inbox/inbox.schemas.js +11 -0
- package/dist/inbox/inbox.service.d.ts +64 -4
- package/dist/inbox/inbox.service.js +74 -4
- package/dist/inbox/org-notices.d.ts +63 -0
- package/dist/inbox/org-notices.js +91 -0
- package/dist/inbox/platform-inbox.controller.d.ts +23 -0
- package/dist/inbox/platform-inbox.controller.js +58 -0
- package/dist/inbox/platform-inbox.service.d.ts +157 -0
- package/dist/inbox/platform-inbox.service.js +281 -0
- package/dist/inbox/platform-notices.d.ts +19 -0
- package/dist/inbox/platform-notices.js +9 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +7 -1
- package/dist/infra/cli/kernel-cli.module.js +9 -1
- package/dist/infra/config/kernel-config.service.js +32 -1
- package/dist/infra/database/database.module.js +1 -0
- package/dist/infra/database/xact-lock.d.ts +1 -1
- package/dist/infra/database/xact-lock.js +1 -1
- package/dist/infra/events/kernel-events.d.ts +31 -3
- package/dist/infra/lifecycle/process-guards.js +4 -0
- package/dist/infra/lock/lock.service.d.ts +8 -0
- package/dist/infra/lock/lock.service.js +27 -0
- package/dist/infra/logging/logging.module.d.ts +4 -2
- package/dist/infra/logging/logging.module.js +24 -6
- package/dist/infra/presence/presence.module.d.ts +6 -0
- package/dist/infra/presence/presence.module.js +22 -0
- package/dist/infra/presence/replica-presence.d.ts +87 -0
- package/dist/infra/presence/replica-presence.js +189 -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/redis-connection.d.ts +6 -0
- package/dist/infra/queue/redis-connection.js +7 -0
- package/dist/infra/redis/redis.module.js +6 -2
- package/dist/infra/throttler/named-throttlers.d.ts +12 -0
- package/dist/infra/throttler/named-throttlers.js +67 -0
- package/dist/infra/throttler/throttler.guard.js +1 -1
- package/dist/infra/tokens.d.ts +6 -1
- package/dist/infra/tokens.js +6 -1
- package/dist/kernel.module.js +15 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +9 -3
- package/dist/lifecycle/kernel-lifecycle.js +51 -11
- package/dist/local-devices/device-auth.controller.d.ts +42 -0
- package/dist/local-devices/device-auth.controller.js +116 -0
- package/dist/local-devices/device-auth.d.ts +119 -0
- package/dist/local-devices/device-auth.js +401 -0
- package/dist/local-devices/device-auth.module.d.ts +7 -0
- package/dist/local-devices/device-auth.module.js +25 -0
- package/dist/local-devices/device-routes.d.ts +36 -0
- package/dist/local-devices/device-routes.js +90 -0
- package/dist/local-devices/dto.d.ts +66 -0
- package/dist/local-devices/dto.js +44 -0
- package/dist/local-devices/keys.d.ts +25 -0
- package/dist/local-devices/keys.js +25 -0
- package/dist/local-devices/local-device-gateway.d.ts +134 -0
- package/dist/local-devices/local-device-gateway.js +542 -0
- package/dist/local-devices/local-device-provider.d.ts +89 -0
- package/dist/local-devices/local-device-provider.js +151 -0
- package/dist/local-devices/local-devices.module.d.ts +16 -0
- package/dist/local-devices/local-devices.module.js +44 -0
- package/dist/local-devices/machines.d.ts +118 -0
- package/dist/local-devices/machines.js +366 -0
- package/dist/local-devices/relay.d.ts +100 -0
- package/dist/local-devices/relay.js +373 -0
- package/dist/local-devices/targets.d.ts +28 -0
- package/dist/local-devices/targets.js +73 -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 +5 -1
- package/dist/models/models.module.js +16 -4
- 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 +8 -6
- package/dist/models/prices.js +11 -9
- package/dist/models/purposes.controller.d.ts +6 -4
- package/dist/models/purposes.controller.js +13 -7
- package/dist/models/purposes.d.ts +72 -14
- package/dist/models/purposes.js +115 -34
- package/dist/orgs/directory-sync.d.ts +14 -5
- package/dist/orgs/directory-sync.js +41 -17
- package/dist/orgs/offboarding.d.ts +12 -8
- package/dist/orgs/offboarding.js +54 -33
- package/dist/orgs/org-lock.d.ts +5 -0
- package/dist/orgs/org-lock.js +13 -0
- package/dist/orgs/org.guard.d.ts +10 -0
- package/dist/orgs/org.guard.js +43 -32
- package/dist/orgs/orgs.controller.d.ts +2 -5
- package/dist/orgs/orgs.controller.js +3 -6
- package/dist/orgs/orgs.module.js +3 -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 +23 -8
- package/dist/orgs/orgs.service.js +38 -16
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +5 -1
- package/dist/orgs/settings.controller.d.ts +1 -1
- package/dist/orgs/settings.service.d.ts +66 -6
- package/dist/orgs/settings.service.js +89 -10
- package/dist/overrides.d.ts +16 -1
- package/dist/overrides.js +10 -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 +774 -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 +102 -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-items.ops.d.ts +37 -0
- package/dist/platform/ops/admin-items.ops.js +278 -0
- package/dist/platform/ops/admin.ops.d.ts +38 -0
- package/dist/platform/ops/admin.ops.js +497 -0
- package/dist/platform/ops/agent-skills.ops.d.ts +50 -0
- package/dist/platform/ops/agent-skills.ops.js +509 -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 +730 -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 +92 -0
- package/dist/platform/ops/catalog-admin.ops.js +682 -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 +190 -0
- package/dist/platform/ops/conversations.ops.d.ts +30 -0
- package/dist/platform/ops/conversations.ops.js +470 -0
- package/dist/platform/ops/devices.ops.d.ts +26 -0
- package/dist/platform/ops/devices.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 +381 -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 +35 -0
- package/dist/platform/ops/org-plugins.ops.js +388 -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 +298 -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/setup.ops.d.ts +24 -0
- package/dist/platform/ops/setup.ops.js +212 -0
- package/dist/platform/ops/skills.ops.d.ts +17 -0
- package/dist/platform/ops/skills.ops.js +160 -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/ui.ops.d.ts +8 -0
- package/dist/platform/ops/ui.ops.js +41 -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 +43 -0
- package/dist/platform/platform-ops.module.js +142 -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 +85 -0
- package/dist/roles/gateway-role.d.ts +18 -3
- package/dist/roles/gateway-role.js +33 -5
- package/dist/roles/gateway.module.d.ts +2 -1
- package/dist/roles/gateway.module.js +6 -3
- package/dist/roles/worker-role.d.ts +6 -4
- package/dist/roles/worker-role.js +14 -7
- package/dist/roles/worker.module.d.ts +1 -1
- package/dist/roles/worker.module.js +21 -1
- 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/device-paths.d.ts +40 -0
- package/dist/runtime/context/device-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/hook-calls.d.ts +8 -1
- package/dist/runtime/hook-calls.js +40 -7
- package/dist/runtime/langgraph-loop.d.ts +3 -1
- package/dist/runtime/langgraph-loop.js +36 -17
- package/dist/runtime/loop.d.ts +35 -6
- package/dist/runtime/maintenance.d.ts +9 -4
- package/dist/runtime/maintenance.js +35 -8
- package/dist/runtime/model-call.d.ts +54 -11
- package/dist/runtime/model-call.js +105 -28
- package/dist/runtime/providers.d.ts +149 -29
- package/dist/runtime/providers.js +332 -63
- 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 +11 -1
- package/dist/runtime/run-control.js +12 -0
- package/dist/runtime/run-drafts.d.ts +85 -0
- package/dist/runtime/run-drafts.js +230 -0
- package/dist/runtime/run-finish.d.ts +1 -1
- package/dist/runtime/run-jobs.d.ts +3 -5
- package/dist/runtime/run-jobs.js +7 -9
- package/dist/runtime/run-queue.d.ts +62 -5
- package/dist/runtime/run-queue.js +313 -40
- package/dist/runtime/run-worker.d.ts +19 -8
- package/dist/runtime/run-worker.js +105 -44
- package/dist/runtime/runtime.module.js +13 -3
- package/dist/runtime/step-log.d.ts +15 -4
- package/dist/runtime/step-log.js +24 -7
- package/dist/runtime/stream.controller.d.ts +23 -1
- package/dist/runtime/stream.controller.js +60 -3
- package/dist/runtime/stream.d.ts +4 -1
- package/dist/runtime/stream.js +27 -3
- package/dist/runtime/subagents/child.d.ts +55 -7
- package/dist/runtime/subagents/child.js +105 -7
- package/dist/runtime/subagents/definition.d.ts +31 -26
- package/dist/runtime/subagents/definition.js +89 -142
- package/dist/runtime/subagents/deliveries.d.ts +71 -0
- package/dist/runtime/subagents/deliveries.js +228 -0
- package/dist/runtime/subagents/dispatch.d.ts +116 -27
- package/dist/runtime/subagents/dispatch.js +213 -142
- package/dist/runtime/subagents/limits.d.ts +24 -5
- package/dist/runtime/subagents/limits.js +40 -6
- package/dist/runtime/subagents/messages.d.ts +95 -0
- package/dist/runtime/subagents/messages.js +328 -0
- package/dist/runtime/subagents/org-agents.js +2 -1
- package/dist/runtime/subagents/preamble.d.ts +4 -4
- package/dist/runtime/subagents/preamble.js +9 -7
- package/dist/runtime/subagents/progress.d.ts +8 -6
- package/dist/runtime/subagents/progress.js +11 -6
- package/dist/runtime/subagents/render.d.ts +30 -0
- package/dist/runtime/subagents/render.js +53 -0
- package/dist/runtime/subagents/roster.d.ts +25 -8
- package/dist/runtime/subagents/roster.js +48 -12
- package/dist/runtime/subagents/skill-fork.d.ts +4 -3
- package/dist/runtime/subagents/skill-fork.js +9 -5
- 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 +9 -6
- package/dist/runtime/subagents/subagents.service.js +13 -8
- 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 +35 -39
- package/dist/runtime/usage-report.js +171 -97
- package/dist/runtime/waits.d.ts +148 -39
- package/dist/runtime/waits.js +426 -112
- package/dist/sandbox/jobs.d.ts +40 -13
- package/dist/sandbox/jobs.js +57 -20
- package/dist/sandbox/leases.d.ts +37 -54
- package/dist/sandbox/leases.js +71 -115
- package/dist/sandbox/providers.d.ts +34 -7
- package/dist/sandbox/providers.js +54 -9
- package/dist/sandbox/sandbox-file-reader.d.ts +35 -0
- package/dist/sandbox/sandbox-file-reader.js +98 -0
- package/dist/sandbox/sandbox.module.d.ts +3 -2
- package/dist/sandbox/sandbox.module.js +10 -4
- package/dist/sandbox/sandbox.service.d.ts +345 -132
- package/dist/sandbox/sandbox.service.js +883 -399
- package/dist/sandbox/unreachable.d.ts +30 -0
- package/dist/sandbox/unreachable.js +108 -0
- package/dist/setup/kernel-checks.d.ts +91 -0
- package/dist/setup/kernel-checks.js +295 -0
- package/dist/setup/oauth-token-probe.d.ts +47 -0
- package/dist/setup/oauth-token-probe.js +108 -0
- package/dist/setup/redact-check.d.ts +18 -0
- package/dist/setup/redact-check.js +46 -0
- package/dist/setup/setup-check-registry.d.ts +86 -0
- package/dist/setup/setup-check-registry.js +75 -0
- package/dist/setup/setup-checks.controller.d.ts +28 -0
- package/dist/setup/setup-checks.controller.js +78 -0
- package/dist/setup/setup-checks.schemas.d.ts +38 -0
- package/dist/setup/setup-checks.schemas.js +43 -0
- package/dist/setup/setup-checks.service.d.ts +144 -0
- package/dist/setup/setup-checks.service.js +683 -0
- package/dist/setup/setup-guides.controller.d.ts +18 -0
- package/dist/setup/setup-guides.controller.js +48 -0
- package/dist/setup/setup-guides.schemas.d.ts +10 -0
- package/dist/setup/setup-guides.schemas.js +6 -0
- package/dist/setup/setup-guides.service.d.ts +126 -0
- package/dist/setup/setup-guides.service.js +315 -0
- package/dist/setup/setup.module.d.ts +8 -0
- package/dist/setup/setup.module.js +31 -0
- package/dist/skills/agent-skills.controller.d.ts +48 -0
- package/dist/skills/agent-skills.controller.js +131 -0
- package/dist/skills/agent-skills.service.d.ts +262 -0
- package/dist/skills/agent-skills.service.js +996 -0
- package/dist/skills/catalog.d.ts +14 -11
- package/dist/skills/catalog.js +32 -50
- package/dist/skills/changes.controller.d.ts +12 -22
- package/dist/skills/changes.controller.js +27 -56
- package/dist/skills/changes.service.d.ts +69 -115
- package/dist/skills/changes.service.js +249 -598
- package/dist/skills/conversation-catalog.d.ts +53 -0
- package/dist/skills/conversation-catalog.js +149 -0
- package/dist/skills/invocable.controller.d.ts +1 -1
- package/dist/skills/invocable.controller.js +2 -2
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +3 -3
- package/dist/skills/invoke.js +21 -8
- package/dist/skills/package.d.ts +15 -1
- package/dist/skills/package.js +14 -1
- package/dist/skills/skills.controller.d.ts +32 -6
- package/dist/skills/skills.controller.js +64 -11
- package/dist/skills/skills.module.js +25 -3
- package/dist/skills/skills.schemas.d.ts +44 -0
- package/dist/skills/skills.schemas.js +68 -0
- package/dist/skills/skills.service.d.ts +123 -26
- package/dist/skills/skills.service.js +493 -76
- package/dist/skills/usable.d.ts +82 -0
- package/dist/skills/usable.js +388 -0
- package/dist/themes/render-css.d.ts +13 -0
- package/dist/themes/render-css.js +135 -0
- package/dist/themes/theme-delivery.service.d.ts +36 -0
- package/dist/themes/theme-delivery.service.js +116 -0
- package/dist/themes/theme-state.d.ts +116 -0
- package/dist/themes/theme-state.js +221 -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 +33 -0
- package/dist/themes/themes-public.controller.js +98 -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/admin-connectors.d.ts +69 -0
- package/dist/tools/admin-connectors.js +135 -0
- package/dist/tools/approvals.controller.js +2 -3
- package/dist/tools/approvals.schemas.d.ts +21 -0
- package/dist/tools/approvals.schemas.js +15 -0
- package/dist/tools/approvals.service.d.ts +26 -2
- package/dist/tools/approvals.service.js +44 -5
- package/dist/tools/builtin-names.d.ts +104 -0
- package/dist/tools/builtin-names.js +164 -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 +1 -1
- package/dist/tools/builtins/ask-user.js +5 -4
- package/dist/tools/builtins/builtin-tools.d.ts +23 -4
- package/dist/tools/builtins/builtin-tools.js +78 -12
- 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 +1 -1
- package/dist/tools/builtins/read-tool-output.js +2 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +5 -5
- package/dist/tools/builtins/sandbox/bash.js +291 -39
- package/dist/tools/builtins/sandbox/common.d.ts +135 -36
- 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 +19 -16
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +64 -50
- 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 +17 -12
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +153 -34
- 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 +29 -19
- 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 +51 -44
- 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 +29 -18
- package/dist/tools/builtins/skill-load.js +125 -73
- 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/connector-account-policies.d.ts +51 -0
- package/dist/tools/connector-account-policies.js +165 -0
- package/dist/tools/connectors.controller.d.ts +74 -9
- package/dist/tools/connectors.controller.js +133 -16
- package/dist/tools/connectors.schemas.d.ts +27 -0
- package/dist/tools/connectors.schemas.js +34 -0
- package/dist/tools/connectors.service.d.ts +101 -8
- package/dist/tools/connectors.service.js +266 -28
- package/dist/tools/credentials.d.ts +23 -0
- package/dist/tools/credentials.js +90 -1
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.js +5 -5
- 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 +61 -4
- package/dist/tools/info.js +119 -33
- 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 +114 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/oauth/flow.js +1 -1
- package/dist/tools/oauth/tokens.d.ts +54 -7
- package/dist/tools/oauth/tokens.js +87 -17
- package/dist/tools/org-tool-switches.d.ts +89 -0
- package/dist/tools/org-tool-switches.js +201 -0
- package/dist/tools/outputs.js +1 -1
- package/dist/tools/pipeline.d.ts +67 -47
- package/dist/tools/pipeline.js +319 -380
- package/dist/tools/policy.d.ts +30 -23
- package/dist/tools/policy.js +142 -64
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +1 -1
- package/dist/tools/questions.service.d.ts +23 -2
- package/dist/tools/questions.service.js +104 -2
- package/dist/tools/registry.d.ts +189 -68
- package/dist/tools/registry.js +318 -236
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/tools.module.js +31 -3
- package/dist/tools/validate.js +1 -1
- package/dist/ui/admin-ui.controller.d.ts +56 -0
- package/dist/ui/admin-ui.controller.js +192 -0
- package/dist/ui/arrangement.d.ts +65 -0
- package/dist/ui/arrangement.js +171 -0
- package/dist/ui/embed-token.d.ts +2 -2
- package/dist/ui/embed-token.js +30 -5
- package/dist/ui/registry.d.ts +42 -17
- package/dist/ui/registry.js +46 -14
- package/dist/ui/slots.controller.d.ts +11 -0
- package/dist/ui/slots.controller.js +25 -0
- package/dist/ui/ui-stream.d.ts +20 -3
- package/dist/ui/ui-stream.js +25 -7
- package/dist/ui/ui.schemas.d.ts +70 -0
- package/dist/ui/ui.schemas.js +65 -0
- package/dist/ui/views.controller.d.ts +35 -49
- package/dist/ui/views.controller.js +48 -70
- package/dist/ui/views.d.ts +112 -18
- package/dist/ui/views.js +254 -47
- package/package.json +6 -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/src/migrations/0104_connector_tool_account_policies.sql +16 -0
- package/src/migrations/0105_devices_rename.sql +136 -0
- package/src/migrations/0106_setup_guides_v2.sql +10 -0
- package/src/migrations/0107_extension_client_builds.sql +50 -0
- package/src/migrations/0108_question_skipped.sql +6 -0
- package/src/migrations/0109_audit_platform_idx.sql +5 -0
- package/src/migrations/0110_usage_time_idx.sql +8 -0
- package/src/migrations/0111_agent_skill_sharing.sql +22 -0
- package/src/migrations/0112_skill_share_requests.sql +4 -0
- package/dist/catalog/upgrade-targets.d.ts +0 -56
- package/dist/catalog/upgrade-targets.js +0 -90
- package/dist/conversations/sandbox-status.d.ts +0 -24
- package/dist/conversations/sandbox-status.js +0 -52
- package/dist/extensions/org-config.controller.d.ts +0 -24
- package/dist/extensions/org-config.controller.js +0 -62
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
- package/dist/tools/builtins/skill-write.d.ts +0 -59
- package/dist/tools/builtins/skill-write.js +0 -244
|
@@ -8,14 +8,18 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
8
8
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
9
|
};
|
|
10
10
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
|
-
import { PLUGIN_MANIFEST_FILE, parseSkillMd, SDK_VERSION, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
|
|
11
|
+
import { appearanceIssues, PLUGIN_MANIFEST_FILE, parseSkillMd, pluginDescription, SDK_VERSION, SKILL_ENTRY_FILE, } from "@capybara-hq/plugin-sdk";
|
|
12
|
+
import { getQueueToken } from "@nestjs/bullmq";
|
|
12
13
|
import { Inject, Injectable } from "@nestjs/common";
|
|
13
14
|
import { sql } from "kysely";
|
|
14
15
|
import semver from "semver";
|
|
16
|
+
import { ClientBuilds } from "../client/client-builds.service.js";
|
|
17
|
+
import { checkClientFiles } from "../client/client-files.js";
|
|
15
18
|
import { ApiError } from "../errors.js";
|
|
16
19
|
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
20
|
+
import { ExtensionAdmin } from "../extensions/admin-view.js";
|
|
17
21
|
import { writeSnapshot } from "../extensions/approvals.js";
|
|
18
|
-
import { ExtensionBlobs } from "../extensions/blobs.js";
|
|
22
|
+
import { blobKey, ExtensionBlobs } from "../extensions/blobs.js";
|
|
19
23
|
import { ExtensionInstalls } from "../extensions/installs.js";
|
|
20
24
|
import { PluginApproveLock, PluginInstallLock } from "../extensions/locks.js";
|
|
21
25
|
import { unrunMigrations } from "../extensions/migrate-lock.js";
|
|
@@ -24,28 +28,41 @@ import { diffPermissions, permissionKeys, WARNINGS_KEY_PREFIX, } from "../extens
|
|
|
24
28
|
import { reviewHash as extensionReviewHash, migrationWarnings, permissionGroups, permissionKeyItems, } from "../extensions/permission-view.js";
|
|
25
29
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
26
30
|
import { audit } from "../identity/audit.js";
|
|
27
|
-
import {
|
|
31
|
+
import { assertCustomAllowed } from "../identity/settings.js";
|
|
32
|
+
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
28
33
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
34
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
29
35
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
30
36
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
31
37
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
32
38
|
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
39
|
+
import { OrgLock } from "../orgs/org-lock.js";
|
|
33
40
|
import { packPackageTgz } from "../packages/tgz.js";
|
|
41
|
+
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
34
42
|
import { checkSkillFiles, SkillArchiveError } from "../skills/package.js";
|
|
35
43
|
import { StorageService } from "../storage/storage.service.js";
|
|
44
|
+
import { canonicalJson } from "../tools/canonical-json.js";
|
|
36
45
|
import { endpointCredentialIssues } from "../tools/endpoint.js";
|
|
37
|
-
import { canonicalJson } from "../tools/registry.js";
|
|
38
46
|
import { findConnectorIn } from "./catalog-content.js";
|
|
39
|
-
import {
|
|
47
|
+
import { displayFilePaths, putDisplayFiles, sweepDisplayFiles } from "./catalog-files.js";
|
|
48
|
+
import { assertOrgsExist, assertPluginNameOwner, catalogObjectPrefix, itemConfirmations, itemScopeFacts, itemView, markVersionApplied, permissionsMismatch, precheckCatalogImport, putCatalogFiles, templateProblems, unappliedOwnVersion, writeCatalogVersion, } from "./catalog-items.js";
|
|
40
49
|
import { CLAUDE_PLUGIN_FILE, claudeContentDigest, } from "./claude/manifest.js";
|
|
41
50
|
import { CLAUDE_MCP_CONNECTOR } from "./claude/mcp.js";
|
|
42
51
|
import { item as reportItem, sortItems, } from "./claude/report.js";
|
|
43
52
|
import { isClaudePluginTree, translateClaudePlugin } from "./claude/translate.js";
|
|
44
53
|
import { CatalogItemLock } from "./locks.js";
|
|
45
|
-
import {
|
|
54
|
+
import { assertNameFree, assertPackageFree, assertShareable, packageOwner, releaseExtensionClaim, shareGate, usableBy, } from "./ownership.js";
|
|
55
|
+
import { PlatformComponents } from "./platform-components.js";
|
|
56
|
+
import { PLATFORM_MIGRATION_JOB } from "./platform-migration.js";
|
|
57
|
+
import { PluginPackageError, packagePath, readPluginFiles, readPluginPackage, themeApiError, } from "./plugin-package.js";
|
|
58
|
+
import { hasImportRequests, importRequestOf, resolveImportRequests } from "./request-rules.js";
|
|
59
|
+
import { assertNameNotReserved } from "./reserved-names.js";
|
|
60
|
+
import { addScopeOrg } from "./scope-orgs.js";
|
|
46
61
|
import { maxSatisfying, satisfiesRange } from "./versions.js";
|
|
62
|
+
/** How long after a failed post-import platform sync the migration job runs for the item. */
|
|
63
|
+
export const PLATFORM_SYNC_RETRY_MS = 60_000;
|
|
47
64
|
/**
|
|
48
|
-
*
|
|
65
|
+
* Platform import of a plugin (package ecosystem spec §4.3): one review for every plugin, whatever
|
|
49
66
|
* it contains (an extension, skills, connector templates, dependencies), confirmed once.
|
|
50
67
|
*
|
|
51
68
|
* prepare: the tgz is always hostile input, and **nothing is written until every check passes**
|
|
@@ -55,27 +72,30 @@ import { maxSatisfying, satisfiesRange } from "./versions.js";
|
|
|
55
72
|
* refused; name ownership; a downgrade to a version with unrun migrations is refused), each skill by
|
|
56
73
|
* the skill package rules, each connector template against the connector loaded on this replica (or
|
|
57
74
|
* statically when the connector is provided by the plugin's own extension or by a dependency), the
|
|
58
|
-
* catalog name / version conflicts and the actor still
|
|
75
|
+
* catalog name / version conflicts and the actor still a super admin. Dependencies are only
|
|
59
76
|
* resolved against the imported catalog versions for the review (an unresolved one does not block
|
|
60
77
|
* the import, spec §4.1); they are never fetched. Only then is the extension handed to
|
|
61
|
-
* `ExtensionInstalls.ingest` (source `catalog`), the skill / template
|
|
62
|
-
* storage,
|
|
78
|
+
* `ExtensionInstalls.ingest` (source `catalog`), the skill / template files written to object
|
|
79
|
+
* storage, the display files (icons, setup guide files; `catalog-files.ts`) written to PG with a
|
|
80
|
+
* staging row (24 hours), and `catalog.plugin_staged` audited. A display file inside a skill
|
|
81
|
+
* directory or at a template's path goes to both places: each reader finds it where it looks.
|
|
63
82
|
*
|
|
64
83
|
* confirm: `reviewHash` must match the staging; in one transaction it deletes the staging row
|
|
65
84
|
* (confirm works once), locks the extension name and recomputes its deployment state (installed /
|
|
66
85
|
* upgraded / swapped after the review -> `plugin.review_stale`), writes the extension's permission
|
|
67
|
-
* snapshot when it is installed by this import (
|
|
68
|
-
* `extension.permissions_approved` carrying the plugin), and creates the item
|
|
69
|
-
* (`manifest` = the normalized plugin.json,
|
|
70
|
-
*
|
|
71
|
-
* deployment and enabled (`ExtensionAdminOps.install` + `enable`;
|
|
72
|
-
* restart); a failure is returned, not thrown, and an upgrade that was
|
|
73
|
-
* snapshot back.
|
|
86
|
+
* snapshot when it is installed or upgraded by this import (source web, audit
|
|
87
|
+
* `extension.permissions_approved` carrying the plugin), and creates the item (with the scope the
|
|
88
|
+
* admin chose, default `optional`) or adds the version (`manifest` = the normalized plugin.json,
|
|
89
|
+
* `extension_sha256`, the files under the staging prefix). After the commit the plugin's own
|
|
90
|
+
* extension is installed on the deployment and enabled (`ExtensionAdminOps.install` + `enable`;
|
|
91
|
+
* each replica reconciles, no restart); a failure is returned, not thrown, and an upgrade that was
|
|
92
|
+
* not installed gets its old snapshot back.
|
|
74
93
|
*
|
|
75
94
|
* Expired staging is cleaned by the maintenance job `app-staging-cleanup`
|
|
76
|
-
* ({@link PluginImport.cleanupExpired}): it deletes the staging row and its object prefix
|
|
77
|
-
*
|
|
78
|
-
*
|
|
95
|
+
* ({@link PluginImport.cleanupExpired}): it deletes the staging row and its object prefix, then the
|
|
96
|
+
* display files (`catalog_files`) nothing lists any more; a stored extension package stays in the
|
|
97
|
+
* content-addressed `extension_packages` (the same as importing the same tgz again; without an
|
|
98
|
+
* install record referencing it it is never loaded).
|
|
79
99
|
*/
|
|
80
100
|
/** How long a staged import is kept. */
|
|
81
101
|
export const PLUGIN_STAGING_TTL_MS = 24 * 3600_000;
|
|
@@ -94,12 +114,20 @@ const reviewStale = (review) => new ApiError("plugin.review_stale", `The review
|
|
|
94
114
|
const mismatch = (what) => new ApiError("marketplace.package_mismatch", `The downloaded package does not match the marketplace entry: ${what}`);
|
|
95
115
|
/**
|
|
96
116
|
* The API error of a plugin package that cannot be read in a catalog path: the pre-0.1.0 format ->
|
|
97
|
-
* `catalog.legacy_format
|
|
117
|
+
* `catalog.legacy_format`; undeclared client code -> `client.undeclared`; a failing theme (themes
|
|
118
|
+
* spec §5) -> `theme.invalid` (details `[{ theme, errors }]`) or `theme.unreadable` (details
|
|
119
|
+
* `[{ theme, issues }]`, the failing pairs); anything else -> `catalog.invalid_manifest` (issues as
|
|
120
|
+
* details).
|
|
98
121
|
*/
|
|
99
122
|
export function catalogPackageError(e) {
|
|
100
123
|
const legacy = e.code === "catalog.legacy_format" || e.code === "extension.legacy_format";
|
|
101
124
|
if (legacy)
|
|
102
125
|
return new ApiError("catalog.legacy_format", e.message, e.issues);
|
|
126
|
+
if (e.code === "client.undeclared")
|
|
127
|
+
return new ApiError("client.undeclared", e.message);
|
|
128
|
+
if (e.code === "theme.invalid" || e.code === "theme.unreadable") {
|
|
129
|
+
return themeApiError(e);
|
|
130
|
+
}
|
|
103
131
|
return invalid(e.issues);
|
|
104
132
|
}
|
|
105
133
|
/** Runs a package read, mapping its errors with {@link catalogPackageError}. */
|
|
@@ -123,16 +151,21 @@ const fileOf = (path, data) => ({
|
|
|
123
151
|
let PluginImport = class PluginImport {
|
|
124
152
|
kdb;
|
|
125
153
|
adminLock;
|
|
154
|
+
orgLock;
|
|
126
155
|
installLock;
|
|
127
156
|
approveLock;
|
|
128
157
|
itemLock;
|
|
129
158
|
config;
|
|
130
159
|
installs;
|
|
131
160
|
ops;
|
|
161
|
+
admin;
|
|
132
162
|
blobs;
|
|
133
163
|
registry;
|
|
134
164
|
log;
|
|
135
165
|
txHost;
|
|
166
|
+
platform;
|
|
167
|
+
maintenance;
|
|
168
|
+
clientBuilds;
|
|
136
169
|
/** Where plugin files go (the kernel's object storage; the CLI's own, see {@link useCliStorage}). */
|
|
137
170
|
files;
|
|
138
171
|
/**
|
|
@@ -142,24 +175,37 @@ let PluginImport = class PluginImport {
|
|
|
142
175
|
*/
|
|
143
176
|
connectorsLoaded = true;
|
|
144
177
|
constructor(kdb,
|
|
145
|
-
/** The
|
|
146
|
-
adminLock,
|
|
178
|
+
/** The super admin lock (identity/super-admin.ts): joins the caller's transaction. */
|
|
179
|
+
adminLock,
|
|
180
|
+
/** The owner org's lock: an org upload re-checks its admin under it (ruling P3-7). */
|
|
181
|
+
orgLock, installLock, approveLock, itemLock, config, storage, installs, ops, admin,
|
|
147
182
|
/** Reads a package from the package store (confirm recomputes the permission set). */
|
|
148
183
|
blobs,
|
|
149
184
|
/** Config-declared names, loaded connectors and extension versions (the extension registry). */
|
|
150
|
-
registry, log, txHost
|
|
185
|
+
registry, log, txHost,
|
|
186
|
+
/** The platform rows of a new item's components, written after the confirm's commit. */
|
|
187
|
+
platform,
|
|
188
|
+
/** A failed platform sync enqueues a run of the migration job here (it heals the item). */
|
|
189
|
+
maintenance,
|
|
190
|
+
/** The client build of a dropped org upload's package is deleted with it. */
|
|
191
|
+
clientBuilds) {
|
|
151
192
|
this.kdb = kdb;
|
|
152
193
|
this.adminLock = adminLock;
|
|
194
|
+
this.orgLock = orgLock;
|
|
153
195
|
this.installLock = installLock;
|
|
154
196
|
this.approveLock = approveLock;
|
|
155
197
|
this.itemLock = itemLock;
|
|
156
198
|
this.config = config;
|
|
157
199
|
this.installs = installs;
|
|
158
200
|
this.ops = ops;
|
|
201
|
+
this.admin = admin;
|
|
159
202
|
this.blobs = blobs;
|
|
160
203
|
this.registry = registry;
|
|
161
204
|
this.log = log;
|
|
162
205
|
this.txHost = txHost;
|
|
206
|
+
this.platform = platform;
|
|
207
|
+
this.maintenance = maintenance;
|
|
208
|
+
this.clientBuilds = clientBuilds;
|
|
163
209
|
this.files = storage;
|
|
164
210
|
}
|
|
165
211
|
/** The kernel-schema handle of the current context (the transaction, else the pool). */
|
|
@@ -174,21 +220,29 @@ let PluginImport = class PluginImport {
|
|
|
174
220
|
useCliStorage(storage) {
|
|
175
221
|
this.files = storage;
|
|
176
222
|
this.connectorsLoaded = false;
|
|
223
|
+
this.platform.useCliStorage(storage);
|
|
177
224
|
}
|
|
178
225
|
/**
|
|
179
|
-
* The
|
|
226
|
+
* The super-admin re-check under the lock, in the caller's transaction. `actor` null is the
|
|
180
227
|
* CLI (the operator of the deployment: no account to re-check, audits carry no actor), like
|
|
181
|
-
* `ExtensionInstalls.ingest`.
|
|
228
|
+
* `ExtensionInstalls.ingest`. An org upload (`owner`) re-checks the actor as an admin of the
|
|
229
|
+
* owner org under the org row lock instead (`catalog.upload`; an org deleted meanwhile -> 404
|
|
230
|
+
* `org.not_found`).
|
|
182
231
|
*/
|
|
183
|
-
async authorizeActor(actor) {
|
|
184
|
-
if (
|
|
232
|
+
async authorizeActor(actor, owner) {
|
|
233
|
+
if (owner !== undefined) {
|
|
234
|
+
if (actor === null)
|
|
235
|
+
throw new Error("an org upload has an actor");
|
|
236
|
+
await this.orgLock.lockAndAuthorize(owner.orgId, actor, "catalog.upload");
|
|
237
|
+
}
|
|
238
|
+
else if (actor === null)
|
|
185
239
|
await this.adminLock.lock();
|
|
186
240
|
else
|
|
187
241
|
await this.adminLock.lockAndAuthorize(actor);
|
|
188
242
|
}
|
|
189
243
|
/** The re-check alone, in a transaction of its own (before anything is written). */
|
|
190
|
-
async authorize(actor) {
|
|
191
|
-
await this.authorizeActor(actor);
|
|
244
|
+
async authorize(actor, owner) {
|
|
245
|
+
await this.authorizeActor(actor, owner);
|
|
192
246
|
}
|
|
193
247
|
/**
|
|
194
248
|
* Reads, checks and stages a plugin (see the file header). Returns the staging id and review.
|
|
@@ -279,6 +333,10 @@ let PluginImport = class PluginImport {
|
|
|
279
333
|
*/
|
|
280
334
|
async prepareContents(actor, pkg, tgz, source, opts) {
|
|
281
335
|
const maxBytes = this.config.get().packages.maxBytes;
|
|
336
|
+
const owner = opts.owner;
|
|
337
|
+
if (owner !== undefined && source.kind !== "file") {
|
|
338
|
+
throw new Error("an org upload is a file (ruling P3-7)");
|
|
339
|
+
}
|
|
282
340
|
// 1. Every check (nothing written)
|
|
283
341
|
const m = pkg.manifest;
|
|
284
342
|
const packageName = packageNameOf(pkg);
|
|
@@ -292,14 +350,50 @@ let PluginImport = class PluginImport {
|
|
|
292
350
|
? await readingPackage(() => readExtensionPackage(bytes, { maxBytes, hostSdkVersion: SDK_VERSION }))
|
|
293
351
|
: undefined;
|
|
294
352
|
const content = this.checkContent(pkg, format);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
353
|
+
// suggestedAppearance.theme against the themes the scan found (the manifest may not list them)
|
|
354
|
+
const appearance = appearanceIssues(m, pkg.themes.map((t) => t.id));
|
|
355
|
+
if (appearance.length > 0)
|
|
356
|
+
throw invalid(appearance);
|
|
357
|
+
// Client code (client extensions spec §9.1): the section re-checked and every file against it
|
|
358
|
+
// (keys, listed = present, sizes, sha384 recomputed, the CSS layer wrap); delivered from object
|
|
359
|
+
// storage, so refused without one. The store checks the bytes it writes again. A bootstrap
|
|
360
|
+
// plugin never carries it: a bootstrap run may have no object store (it may be a bootstrap
|
|
361
|
+
// plugin itself), and a required entry failing on that would stop the start.
|
|
362
|
+
if (ext?.section.client !== undefined) {
|
|
363
|
+
if (source.kind === "bootstrap") {
|
|
364
|
+
throw new ApiError("client.invalid", `Bootstrap plugin ${m.name} ships client code (extension.client), which a bootstrap plugin may not carry: its files are kept in object storage, which a bootstrap run may not have (the object store may be a bootstrap plugin itself); take ${m.name} out of bootstrap.json and import it into the catalog instead`);
|
|
365
|
+
}
|
|
366
|
+
checkClientFiles(ext.section.client, pkg.files);
|
|
367
|
+
this.files.assertAvailable();
|
|
368
|
+
}
|
|
369
|
+
// A name live for another owner (an org's for the super admin; the platform's or another
|
|
370
|
+
// org's for an org) -> 409 plugin.name_taken naming it (P3-14); the same owner adds a version
|
|
371
|
+
await assertNameFree(this.db, m.name, owner?.orgId ?? null);
|
|
372
|
+
if (owner !== undefined) {
|
|
373
|
+
// a bootstrap or marketplace plugin's name stays free for the platform (ruling P3-28)
|
|
374
|
+
await assertNameNotReserved(this.db, m.name);
|
|
375
|
+
// its npm package is an identity of this org only (ruling P3-51)
|
|
376
|
+
await assertPackageFree(this.db, packageName, owner.orgId);
|
|
377
|
+
await assertCustomContent(this.db, content);
|
|
378
|
+
}
|
|
379
|
+
// An org's own version imported but not applied: its update is retried (pre-flight F4)
|
|
380
|
+
const retry = owner !== undefined && !m.extension
|
|
381
|
+
? await unappliedOwnVersion(this.db, m.name, owner.orgId, {
|
|
382
|
+
packageName,
|
|
383
|
+
version: m.version,
|
|
384
|
+
contentDigest: pkg.contentDigest,
|
|
385
|
+
})
|
|
386
|
+
: undefined;
|
|
387
|
+
const { existing, version } = retry !== undefined
|
|
388
|
+
? { existing: { id: retry.itemId }, version: retry.version }
|
|
389
|
+
: await precheckCatalogImport(this.db, m.name, {
|
|
390
|
+
packageName,
|
|
391
|
+
version: m.version,
|
|
392
|
+
contentDigest: pkg.contentDigest,
|
|
393
|
+
...(source.integrity !== undefined && { integrity: source.integrity }),
|
|
394
|
+
...(source.detail !== undefined && { detail: source.detail }),
|
|
395
|
+
...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
|
|
396
|
+
});
|
|
303
397
|
// The catalog name space is the extension name space: a declarative plugin cannot take a
|
|
304
398
|
// config-declared or another package's extension name either
|
|
305
399
|
this.assertNotDeclared(m.name);
|
|
@@ -309,8 +403,17 @@ let PluginImport = class PluginImport {
|
|
|
309
403
|
extension = await this.reviewExtension(ext, await this.extensionState(m.name, packageName));
|
|
310
404
|
await assertDowngradable(this.db, extension, ext.migrationSql);
|
|
311
405
|
}
|
|
312
|
-
|
|
406
|
+
// Display files go to PG with the staging row; skills and templates need object storage, which a
|
|
407
|
+
// bootstrap import never has (the object store may be a bootstrap plugin itself). A file that is
|
|
408
|
+
// both (an icon inside a skill directory) goes to both: the readers of each look only there
|
|
409
|
+
const displayFiles = content.files.filter((f) => content.displayPaths.has(f.path));
|
|
410
|
+
const objectFiles = content.files.filter((f) => content.objectPaths.has(f.path));
|
|
411
|
+
if (objectFiles.length > 0 && retry === undefined) {
|
|
412
|
+
if (source.kind === "bootstrap" && !this.files.available) {
|
|
413
|
+
throw new ApiError("storage.unavailable", `Bootstrap plugin ${m.name} ships skills, connector templates, agent templates or themes, which are kept in object storage, and object storage is not running yet (it may be a bootstrap plugin itself); a required bootstrap plugin may ship only an icon and setup guides, an optional one is retried once the extensions have loaded`);
|
|
414
|
+
}
|
|
313
415
|
this.files.assertAvailable();
|
|
416
|
+
}
|
|
314
417
|
const src = {
|
|
315
418
|
kind: source.kind,
|
|
316
419
|
ref: source.ref,
|
|
@@ -318,7 +421,7 @@ let PluginImport = class PluginImport {
|
|
|
318
421
|
...(source.marketplaceId !== undefined && { marketplaceId: source.marketplaceId }),
|
|
319
422
|
...(source.detail !== undefined && { detail: source.detail }),
|
|
320
423
|
};
|
|
321
|
-
const dependencies = await this.resolveDependencies(m);
|
|
424
|
+
const dependencies = await this.resolveDependencies(m, owner);
|
|
322
425
|
let translation;
|
|
323
426
|
if (opts.claude !== undefined) {
|
|
324
427
|
const added = [
|
|
@@ -348,7 +451,8 @@ let PluginImport = class PluginImport {
|
|
|
348
451
|
contentDigest: pkg.contentDigest,
|
|
349
452
|
packageName,
|
|
350
453
|
publisher: m.publisher,
|
|
351
|
-
description: m.description,
|
|
454
|
+
description: pluginDescription(m.description).en,
|
|
455
|
+
descriptionZh: pluginDescription(m.description).zh ?? null,
|
|
352
456
|
...(m.displayName !== undefined && { displayName: m.displayName }),
|
|
353
457
|
...(m.license !== undefined && { license: m.license }),
|
|
354
458
|
...(m.homepage !== undefined && { homepage: m.homepage }),
|
|
@@ -356,6 +460,7 @@ let PluginImport = class PluginImport {
|
|
|
356
460
|
skills: content.skills,
|
|
357
461
|
connectorTemplates: content.templates,
|
|
358
462
|
...(content.agentTemplates.length > 0 && { agentTemplates: content.agentTemplates }),
|
|
463
|
+
...(content.themes.length > 0 && { themes: content.themes }),
|
|
359
464
|
dependencies,
|
|
360
465
|
source: src,
|
|
361
466
|
provenance: (opts.provenance ?? NOT_NPM).provenance,
|
|
@@ -364,8 +469,9 @@ let PluginImport = class PluginImport {
|
|
|
364
469
|
reviewHash: "",
|
|
365
470
|
};
|
|
366
471
|
review.reviewHash = pluginReviewHash(review, content.files);
|
|
367
|
-
// Re-check under the lock that the actor is still an
|
|
368
|
-
|
|
472
|
+
// Re-check under the lock that the actor is still a super admin (an org upload: an admin of
|
|
473
|
+
// the owner org) before writing
|
|
474
|
+
await this.authorize(actor, owner);
|
|
369
475
|
// 2. Write: the extension into the package store, files into object storage, the staging row
|
|
370
476
|
const stagingId = randomUUID();
|
|
371
477
|
const itemId = existing?.id ?? randomUUID();
|
|
@@ -379,12 +485,14 @@ let PluginImport = class PluginImport {
|
|
|
379
485
|
}, {
|
|
380
486
|
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
381
487
|
...(bootstrap && { store: "pg" }),
|
|
488
|
+
// an org upload only stores the package (nothing runs until the super admin confirms)
|
|
489
|
+
...(owner !== undefined && { owner }),
|
|
382
490
|
});
|
|
383
491
|
}
|
|
384
492
|
let objectPrefix = null;
|
|
385
|
-
if (
|
|
493
|
+
if (objectFiles.length > 0 && retry === undefined) {
|
|
386
494
|
objectPrefix = catalogObjectPrefix(itemId, version, stagingId);
|
|
387
|
-
await putCatalogFiles(this.files, objectPrefix,
|
|
495
|
+
await putCatalogFiles(this.files, objectPrefix, objectFiles);
|
|
388
496
|
}
|
|
389
497
|
const keys = ext
|
|
390
498
|
? permissionKeys(permissionSetOfPackage(ext))
|
|
@@ -392,28 +500,34 @@ let PluginImport = class PluginImport {
|
|
|
392
500
|
.sort()
|
|
393
501
|
: [];
|
|
394
502
|
const mismatch = permissionsMismatch(opts.expect?.marketplace?.permissions, ext ? keys : undefined);
|
|
503
|
+
const manifest = normalizedManifest(pkg);
|
|
504
|
+
const replacements = manifest.suggestedAppearance?.replacements;
|
|
395
505
|
const staged = {
|
|
396
506
|
itemId,
|
|
397
507
|
packageName,
|
|
398
508
|
version,
|
|
399
509
|
contentDigest: pkg.contentDigest,
|
|
400
510
|
size: tgz.size,
|
|
401
|
-
manifest
|
|
511
|
+
manifest,
|
|
512
|
+
...(replacements !== undefined && { appearanceOrder: Object.keys(replacements) }),
|
|
402
513
|
files: content.files.map(({ path, size, sha256 }) => ({ path, size, sha256 })),
|
|
403
514
|
...(mismatch !== null && { permissionsMismatch: mismatch }),
|
|
404
515
|
sourceFormat: format,
|
|
405
516
|
...(translation !== undefined && { translation }),
|
|
406
517
|
...(license.text !== undefined && { licenseText: license.text }),
|
|
407
518
|
...(license.truncated && { licenseTruncated: true }),
|
|
519
|
+
...(retry !== undefined && { retry: true }),
|
|
408
520
|
};
|
|
409
|
-
await this.writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts);
|
|
521
|
+
await this.writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts, owner, displayFiles);
|
|
410
522
|
return { stagingId, review, permissionKeys: keys, permissionsMismatch: mismatch };
|
|
411
523
|
}
|
|
412
524
|
/** The staging row and the `catalog.plugin_staged` audit, the actor re-checked under the lock. */
|
|
413
|
-
async writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts) {
|
|
525
|
+
async writeStaging(actor, stagingId, review, staged, objectPrefix, src, opts, owner, displayFiles) {
|
|
414
526
|
const { extension } = review;
|
|
415
527
|
const t = this.db;
|
|
416
|
-
await this.authorizeActor(actor);
|
|
528
|
+
await this.authorizeActor(actor, owner);
|
|
529
|
+
// committed with the staging row that lists them (the sweep keeps what a staging lists)
|
|
530
|
+
await putDisplayFiles(t, displayFiles);
|
|
417
531
|
await t
|
|
418
532
|
.insertInto("plugin_import_staging")
|
|
419
533
|
.values({
|
|
@@ -424,6 +538,8 @@ let PluginImport = class PluginImport {
|
|
|
424
538
|
source: JSON.stringify(src),
|
|
425
539
|
created_by: actor,
|
|
426
540
|
expires_at: new Date(Date.now() + PLUGIN_STAGING_TTL_MS),
|
|
541
|
+
// the org's own staging (P3-8); null = the super admin's
|
|
542
|
+
org_id: owner?.orgId ?? null,
|
|
427
543
|
})
|
|
428
544
|
.execute();
|
|
429
545
|
await audit(t, {
|
|
@@ -443,6 +559,8 @@ let PluginImport = class PluginImport {
|
|
|
443
559
|
...(extension && {
|
|
444
560
|
extension: { sha256: extension.sha256, action: extension.action },
|
|
445
561
|
}),
|
|
562
|
+
...(owner !== undefined && { orgId: owner.orgId }),
|
|
563
|
+
...opts.auditDetail,
|
|
446
564
|
},
|
|
447
565
|
});
|
|
448
566
|
}
|
|
@@ -465,9 +583,10 @@ let PluginImport = class PluginImport {
|
|
|
465
583
|
/**
|
|
466
584
|
* A staged import's review, as prepare returned it, with a marketplace import's permission
|
|
467
585
|
* mismatch when there is one (the import page loads `?staging=<id>` with it). Unknown, expired or
|
|
468
|
-
* already confirmed -> 404 `plugin.staging_not_found`.
|
|
586
|
+
* already confirmed -> 404 `plugin.staging_not_found`. Each sees only its own staging (P3-8):
|
|
587
|
+
* the super admin's routes the platform's (no `owner`), an org's routes that org's.
|
|
469
588
|
*/
|
|
470
|
-
async staged(stagingId) {
|
|
589
|
+
async staged(stagingId, owner) {
|
|
471
590
|
if (!UUID_RE.test(stagingId))
|
|
472
591
|
throw notFound();
|
|
473
592
|
const row = await this.db
|
|
@@ -475,6 +594,7 @@ let PluginImport = class PluginImport {
|
|
|
475
594
|
.select(["id", "review", "manifest"])
|
|
476
595
|
.where("id", "=", stagingId)
|
|
477
596
|
.where("expires_at", ">", sql `now()`)
|
|
597
|
+
.where(ownStaging(owner))
|
|
478
598
|
.executeTakeFirst();
|
|
479
599
|
if (!row)
|
|
480
600
|
throw notFound();
|
|
@@ -486,17 +606,117 @@ let PluginImport = class PluginImport {
|
|
|
486
606
|
};
|
|
487
607
|
}
|
|
488
608
|
/**
|
|
489
|
-
*
|
|
490
|
-
*
|
|
609
|
+
* What an org's staged upload targets (P3-12, pre-flight F3): its item, version and review hash,
|
|
610
|
+
* whether the item exists (a new version of the org's own plugin) or the version is imported
|
|
611
|
+
* already (F4), and the target as the platform updater reads it: the staged manifest and files,
|
|
612
|
+
* or the imported version's for a retry. Another org's staging -> 404 `plugin.staging_not_found`.
|
|
613
|
+
*/
|
|
614
|
+
async stagedTarget(stagingId, owner) {
|
|
615
|
+
if (!UUID_RE.test(stagingId))
|
|
616
|
+
throw notFound();
|
|
617
|
+
const row = await this.db
|
|
618
|
+
.selectFrom("plugin_import_staging")
|
|
619
|
+
.select(["review", "manifest", "object_prefix"])
|
|
620
|
+
.where("id", "=", stagingId)
|
|
621
|
+
.where("expires_at", ">", sql `now()`)
|
|
622
|
+
.where(ownStaging(owner))
|
|
623
|
+
.executeTakeFirst();
|
|
624
|
+
if (!row)
|
|
625
|
+
throw notFound();
|
|
626
|
+
const review = row.review;
|
|
627
|
+
const staged = row.manifest;
|
|
628
|
+
const item = await this.db
|
|
629
|
+
.selectFrom("catalog_items")
|
|
630
|
+
.select(["id", "awaiting_confirmation"])
|
|
631
|
+
.where("id", "=", staged.itemId)
|
|
632
|
+
.where("deleted_at", "is", null)
|
|
633
|
+
.where("owner_org_id", "=", owner.orgId)
|
|
634
|
+
.executeTakeFirst();
|
|
635
|
+
const imported = staged.retry === true
|
|
636
|
+
? await this.db
|
|
637
|
+
.selectFrom("catalog_item_versions")
|
|
638
|
+
.select(["version", "manifest", "object_prefix", "files", "extension_sha256"])
|
|
639
|
+
.where("item_id", "=", staged.itemId)
|
|
640
|
+
.where("version", "=", staged.version)
|
|
641
|
+
.executeTakeFirst()
|
|
642
|
+
: undefined;
|
|
643
|
+
return {
|
|
644
|
+
itemId: staged.itemId,
|
|
645
|
+
version: staged.version,
|
|
646
|
+
reviewHash: review.reviewHash,
|
|
647
|
+
extension: review.extension !== undefined,
|
|
648
|
+
existing: item !== undefined,
|
|
649
|
+
awaiting: item?.awaiting_confirmation === true,
|
|
650
|
+
retry: staged.retry === true,
|
|
651
|
+
target: imported !== undefined
|
|
652
|
+
? {
|
|
653
|
+
version: imported.version,
|
|
654
|
+
manifest: imported.manifest,
|
|
655
|
+
object_prefix: imported.object_prefix,
|
|
656
|
+
files: imported.files,
|
|
657
|
+
extension_sha256: imported.extension_sha256,
|
|
658
|
+
}
|
|
659
|
+
: {
|
|
660
|
+
version: staged.version,
|
|
661
|
+
manifest: staged.manifest,
|
|
662
|
+
object_prefix: row.object_prefix,
|
|
663
|
+
files: staged.files,
|
|
664
|
+
extension_sha256: review.extension?.sha256 ?? null,
|
|
665
|
+
},
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
/** The catalog item's view (as a confirm returns it). */
|
|
669
|
+
async view(itemId) {
|
|
670
|
+
return this.itemView(itemId);
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Confirms a staged import (see the file header). Returns the committed catalog item and the
|
|
674
|
+
* extension's deploy result (a failed deploy is returned, not thrown). `scope` (default
|
|
675
|
+
* `optional`) and `orgs` (only with `named`; each an existing org, else `validation_failed`) are
|
|
676
|
+
* written when this confirm creates the item; a new version of an existing item keeps its scope.
|
|
677
|
+
* The caller enqueues the scope sync of the item after this returns.
|
|
678
|
+
*
|
|
679
|
+
* An org upload (`opts.owner`, spec §14): only that org's staging; the actor re-checked as its
|
|
680
|
+
* admin; `scope` / `orgs` are not taken: a new item is owned by the org, scope `named: [owner]`,
|
|
681
|
+
* not shown to other orgs, `shareable` as given (default false). Custom deny, the name owner and
|
|
682
|
+
* the dependencies are checked again under the item name's lock. A package with an extension
|
|
683
|
+
* is stored and its extension name claimed, nothing approved or installed: the version waits
|
|
684
|
+
* for the super admin (`pending`, ruling P3-10; see {@link commit}).
|
|
491
685
|
*/
|
|
492
686
|
async confirm(actor, stagingId, input, opts = {}) {
|
|
493
687
|
if (!UUID_RE.test(stagingId))
|
|
494
688
|
throw notFound();
|
|
689
|
+
const owner = opts.owner;
|
|
690
|
+
if (owner !== undefined && (input.scope !== undefined || input.orgs !== undefined)) {
|
|
691
|
+
throw new Error("an org upload's scope is its owner's");
|
|
692
|
+
}
|
|
693
|
+
// A staging prepared by approving an org's `import` request defaults to that org (spec §5.1
|
|
694
|
+
// rule 3); the admin may still choose any scope
|
|
695
|
+
const linked = input.scope === undefined && owner === undefined
|
|
696
|
+
? await importRequestOf(this.db, stagingId)
|
|
697
|
+
: undefined;
|
|
698
|
+
const scope = owner !== undefined
|
|
699
|
+
? "named"
|
|
700
|
+
: (input.scope ?? (linked !== undefined ? "named" : "optional"));
|
|
701
|
+
const orgs = owner !== undefined
|
|
702
|
+
? [owner.orgId]
|
|
703
|
+
: (input.orgs ?? (linked !== undefined ? [linked.orgId] : undefined));
|
|
704
|
+
if (input.orgs !== undefined && scope !== "named") {
|
|
705
|
+
throw new ApiError("validation_failed", "orgs: only allowed with scope named", [
|
|
706
|
+
{ path: "orgs", message: "only allowed with scope named" },
|
|
707
|
+
]);
|
|
708
|
+
}
|
|
709
|
+
if (scope === "named" && (orgs ?? []).length === 0) {
|
|
710
|
+
throw new ApiError("validation_failed", "orgs: scope named needs at least one organization", [
|
|
711
|
+
{ path: "orgs", message: "scope named needs at least one organization" },
|
|
712
|
+
]);
|
|
713
|
+
}
|
|
495
714
|
const row = await this.db
|
|
496
715
|
.selectFrom("plugin_import_staging")
|
|
497
716
|
.selectAll()
|
|
498
717
|
.where("id", "=", stagingId)
|
|
499
718
|
.where("expires_at", ">", sql `now()`)
|
|
719
|
+
.where(ownStaging(owner))
|
|
500
720
|
.executeTakeFirst();
|
|
501
721
|
if (!row)
|
|
502
722
|
throw notFound();
|
|
@@ -507,34 +727,108 @@ let PluginImport = class PluginImport {
|
|
|
507
727
|
throw reviewStale(review);
|
|
508
728
|
const manifest = withPinned(staged.manifest, review, input.pinnedSuggestions);
|
|
509
729
|
const reviewed = review.extension;
|
|
510
|
-
// Read the stored package outside the transaction (unless it was already installed as is
|
|
511
|
-
|
|
512
|
-
const
|
|
730
|
+
// Read the stored package outside the transaction (unless it was already installed as is, or
|
|
731
|
+
// an org upload, which approves nothing)
|
|
732
|
+
const stored = reviewed && reviewed.action !== "keep" && owner === undefined
|
|
733
|
+
? await this.readStored(reviewed.sha256)
|
|
734
|
+
: undefined;
|
|
735
|
+
const committed = await this.commit(actor, { stagingId, review, staged, src, manifest, objectPrefix: row.object_prefix }, {
|
|
736
|
+
scope,
|
|
737
|
+
orgs: [...new Set(orgs ?? [])].sort(),
|
|
738
|
+
...(owner !== undefined && { owner, shareable: input.shareable ?? false }),
|
|
739
|
+
}, stored, opts);
|
|
513
740
|
const { now } = committed;
|
|
514
|
-
|
|
741
|
+
if (committed.pending) {
|
|
742
|
+
// Waits for the super admin (P3-10): no platform components, nothing deployed
|
|
743
|
+
return {
|
|
744
|
+
item: await this.itemView(committed.itemId),
|
|
745
|
+
created: committed.created,
|
|
746
|
+
deploy: null,
|
|
747
|
+
pending: true,
|
|
748
|
+
firstVersion: false,
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
// A new item's skills, agent templates and connector templates become platform components
|
|
752
|
+
// (plugin scope phase 2); a new version of an existing item leaves them to the platform
|
|
753
|
+
// update. After the commit: it copies files in object storage
|
|
754
|
+
if (committed.firstVersion)
|
|
755
|
+
await this.syncPlatform(committed.itemId, staged.version);
|
|
756
|
+
const deploy = now && now.action !== "keep"
|
|
515
757
|
? await this.deploy(actor, review, committed.itemId, now, committed.previous, opts, input.enable ?? true)
|
|
516
758
|
: null;
|
|
517
|
-
return {
|
|
759
|
+
return {
|
|
760
|
+
item: await this.itemView(committed.itemId),
|
|
761
|
+
created: committed.created,
|
|
762
|
+
deploy,
|
|
763
|
+
pending: false,
|
|
764
|
+
firstVersion: committed.firstVersion,
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Writes the platform components of an item's first usable version after a commit made
|
|
769
|
+
* elsewhere (the super admin's confirmation of an org upload, `CatalogScopeService`); a failure
|
|
770
|
+
* is logged and retried by the migration job (see {@link syncPlatform}).
|
|
771
|
+
*/
|
|
772
|
+
async writePlatformComponents(itemId, version) {
|
|
773
|
+
await this.syncPlatform(itemId, version);
|
|
518
774
|
}
|
|
519
775
|
/**
|
|
520
776
|
* The confirm's transaction: the staging row consumed, the extension's action recomputed under
|
|
521
777
|
* its install lock (stale -> `plugin.review_stale`), its snapshot approved, and the catalog
|
|
522
778
|
* version written under the item name's lock.
|
|
779
|
+
*
|
|
780
|
+
* An org upload with an extension (ruling P3-10) approves nothing: under the install lock it
|
|
781
|
+
* claims the extension name for its package (another package's -> 409
|
|
782
|
+
* `extension.name_conflict` naming its owner, before anything is written), and the version
|
|
783
|
+
* written becomes the item's pending one (`pending_version` / `_by` / `_at`; a first version
|
|
784
|
+
* also `awaiting_confirmation`). A later upload replaces the pending version (P3-11). An org
|
|
785
|
+
* upload without an extension for an item whose first version still waits (plan Task 6) replaces
|
|
786
|
+
* that upload and applies at once: the item stops waiting and the claim is released (nothing
|
|
787
|
+
* was installed under it).
|
|
523
788
|
*/
|
|
524
|
-
async commit(actor, c,
|
|
789
|
+
async commit(actor, c, scope, stored, opts) {
|
|
525
790
|
const { stagingId, review, staged, src, manifest } = c;
|
|
526
791
|
const reviewed = review.extension;
|
|
527
792
|
const stale = () => reviewStale(review);
|
|
528
|
-
|
|
793
|
+
const { owner } = scope;
|
|
794
|
+
await this.authorizeActor(actor, owner);
|
|
529
795
|
const t = this.db;
|
|
530
796
|
const used = await t
|
|
531
797
|
.deleteFrom("plugin_import_staging")
|
|
532
798
|
.where("id", "=", stagingId)
|
|
533
799
|
.where("expires_at", ">", sql `now()`)
|
|
800
|
+
.where(ownStaging(owner))
|
|
534
801
|
.returning("id")
|
|
535
802
|
.executeTakeFirst();
|
|
536
803
|
if (!used)
|
|
537
804
|
throw notFound();
|
|
805
|
+
if (owner !== undefined) {
|
|
806
|
+
await assertCustomContent(t, {
|
|
807
|
+
skills: review.skills,
|
|
808
|
+
agentTemplates: review.agentTemplates ?? [],
|
|
809
|
+
templates: review.connectorTemplates,
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
await assertOrgsExist(t, scope.orgs);
|
|
813
|
+
// Checked again before this upload claims anything (ruling P3-51)
|
|
814
|
+
if (owner !== undefined)
|
|
815
|
+
await assertPackageFree(t, staged.packageName, owner.orgId);
|
|
816
|
+
// The item's name lock and its live row before the extension's install lock: the global lock
|
|
817
|
+
// order is the item, then the install lock (ruling P3-50; ExtensionAdminOps.install locks the
|
|
818
|
+
// source item row before the install lock, an org deletion its items before it). Taken after
|
|
819
|
+
// the install lock instead, a confirmation of an org upload racing a replacement upload
|
|
820
|
+
// deadlocks (40P01).
|
|
821
|
+
const m = manifest;
|
|
822
|
+
await this.itemLock.lock(m.name);
|
|
823
|
+
// The scope the audit records: the review's for a new item, the item's own for a new version
|
|
824
|
+
// of a live item (which keeps its scope)
|
|
825
|
+
const existing = await t
|
|
826
|
+
.selectFrom("catalog_items")
|
|
827
|
+
.select(["id", "scope", "awaiting_confirmation", "package_name"])
|
|
828
|
+
.where("name", "=", m.name)
|
|
829
|
+
.where("deleted_at", "is", null)
|
|
830
|
+
.forUpdate()
|
|
831
|
+
.executeTakeFirst();
|
|
538
832
|
let now;
|
|
539
833
|
let previous;
|
|
540
834
|
if (reviewed) {
|
|
@@ -544,23 +838,73 @@ let PluginImport = class PluginImport {
|
|
|
544
838
|
await this.installLock.lock(reviewed.name);
|
|
545
839
|
now = {
|
|
546
840
|
...reviewed,
|
|
547
|
-
...actionOf(await this.extensionState(reviewed.name, staged.packageName), reviewed.sha256),
|
|
841
|
+
...actionOf(await this.extensionState(reviewed.name, staged.packageName), reviewed.sha256, reviewed.version),
|
|
548
842
|
};
|
|
549
843
|
if (pluginReviewHash({ ...review, extension: now }, staged.files) !== review.reviewHash) {
|
|
550
844
|
throw stale();
|
|
551
845
|
}
|
|
846
|
+
if (owner !== undefined) {
|
|
847
|
+
// An org upload only claims the name (P3-10): the super admin approves and installs it
|
|
848
|
+
await t
|
|
849
|
+
.insertInto("extension_name_owners")
|
|
850
|
+
.values({ name: reviewed.name, package_name: staged.packageName })
|
|
851
|
+
.onConflict((oc) => oc.column("name").doNothing())
|
|
852
|
+
.execute();
|
|
853
|
+
await assertPluginNameOwner(t, reviewed.name, staged.packageName);
|
|
854
|
+
}
|
|
552
855
|
// A foreseeable deploy failure (a downgrade to a version with unrun migrations) is refused
|
|
553
856
|
// before anything is written
|
|
554
|
-
if (
|
|
857
|
+
if (now.action === "upgrade" && stored) {
|
|
555
858
|
await assertDowngradable(t, now, stored.migrationSql);
|
|
556
859
|
}
|
|
557
|
-
if (now.action === "install" ||
|
|
860
|
+
if (owner === undefined && (now.action === "install" || now.action === "upgrade")) {
|
|
558
861
|
previous = await this.approve(actor, review, staged, now, stored, opts);
|
|
559
862
|
}
|
|
560
863
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
864
|
+
// Under the name's lock: the first confirm of a name wins, a later one of another owner is
|
|
865
|
+
// refused naming it, before anything of it is written (P3-14)
|
|
866
|
+
await assertNameFree(t, m.name, owner?.orgId ?? null);
|
|
867
|
+
if (owner !== undefined) {
|
|
868
|
+
await assertNameNotReserved(t, m.name);
|
|
869
|
+
await this.resolveDependencies(m, owner);
|
|
870
|
+
}
|
|
871
|
+
const actual = existing === undefined
|
|
872
|
+
? scope
|
|
873
|
+
: {
|
|
874
|
+
scope: existing.scope,
|
|
875
|
+
orgs: (await t
|
|
876
|
+
.selectFrom("catalog_item_scope_orgs")
|
|
877
|
+
.select("org_id")
|
|
878
|
+
.where("item_id", "=", existing.id)
|
|
879
|
+
.orderBy("org_id")
|
|
880
|
+
.execute()).map((r) => r.org_id),
|
|
881
|
+
};
|
|
882
|
+
if (staged.retry === true) {
|
|
883
|
+
// An org's own version imported already (pre-flight F4): nothing to write, the caller
|
|
884
|
+
// retries its update; it must still be there as reviewed
|
|
885
|
+
const v = existing === undefined
|
|
886
|
+
? undefined
|
|
887
|
+
: await t
|
|
888
|
+
.selectFrom("catalog_item_versions")
|
|
889
|
+
.select("version")
|
|
890
|
+
.where("item_id", "=", existing.id)
|
|
891
|
+
.where("version", "=", staged.version)
|
|
892
|
+
.where("content_digest", "=", staged.contentDigest)
|
|
893
|
+
.executeTakeFirst();
|
|
894
|
+
if (existing === undefined || existing.id !== staged.itemId || v === undefined)
|
|
895
|
+
throw stale();
|
|
896
|
+
return {
|
|
897
|
+
itemId: existing.id,
|
|
898
|
+
created: false,
|
|
899
|
+
firstVersion: false,
|
|
900
|
+
pending: false,
|
|
901
|
+
now,
|
|
902
|
+
previous,
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
const { id: itemId, created } = await writeCatalogVersion(t, {
|
|
906
|
+
// an org's version becomes its latest only when applied or confirmed (P3-34)
|
|
907
|
+
...(owner !== undefined && { keepLatest: true }),
|
|
564
908
|
actor,
|
|
565
909
|
...(opts.actorTokenId !== undefined && { actorTokenId: opts.actorTokenId }),
|
|
566
910
|
name: m.name,
|
|
@@ -568,9 +912,10 @@ let PluginImport = class PluginImport {
|
|
|
568
912
|
version: staged.version,
|
|
569
913
|
contentDigest: staged.contentDigest,
|
|
570
914
|
manifest: m,
|
|
915
|
+
appearanceOrder: staged.appearanceOrder ?? null,
|
|
571
916
|
listing: {
|
|
572
917
|
publisher: m.publisher,
|
|
573
|
-
description: m.description,
|
|
918
|
+
description: pluginDescription(m.description).en,
|
|
574
919
|
displayName: m.displayName ?? null,
|
|
575
920
|
},
|
|
576
921
|
newItemId: staged.itemId,
|
|
@@ -591,12 +936,144 @@ let PluginImport = class PluginImport {
|
|
|
591
936
|
licenseTruncated: staged.licenseTruncated === true,
|
|
592
937
|
auditDetail: {
|
|
593
938
|
stagingId,
|
|
594
|
-
|
|
939
|
+
scope: actual.scope,
|
|
940
|
+
...(actual.scope === "named" && { orgs: actual.orgs }),
|
|
595
941
|
suggestedPinned: pinnedNames(manifest, review),
|
|
596
942
|
...(now && { extension: { name: now.name, version: now.version, action: now.action } }),
|
|
597
943
|
},
|
|
598
944
|
});
|
|
599
|
-
|
|
945
|
+
// A new item gets the scope chosen in the review; a new version keeps the item's scope, its
|
|
946
|
+
// org list and its scope version (prepare reuses the live item's id, so the id cannot tell)
|
|
947
|
+
if (created) {
|
|
948
|
+
await t
|
|
949
|
+
.updateTable("catalog_items")
|
|
950
|
+
.set({
|
|
951
|
+
scope: scope.scope,
|
|
952
|
+
// an org upload: the org owns it, nobody else sees it until shared and shown (P3-16)
|
|
953
|
+
...(owner !== undefined && {
|
|
954
|
+
owner_org_id: owner.orgId,
|
|
955
|
+
shareable: scope.shareable === true,
|
|
956
|
+
shown_to_others: false,
|
|
957
|
+
}),
|
|
958
|
+
})
|
|
959
|
+
.where("id", "=", itemId)
|
|
960
|
+
.execute();
|
|
961
|
+
if (scope.scope === "named" && scope.orgs.length > 0) {
|
|
962
|
+
await t
|
|
963
|
+
.insertInto("catalog_item_scope_orgs")
|
|
964
|
+
.values(scope.orgs.map((org_id) => ({ item_id: itemId, org_id })))
|
|
965
|
+
.onConflict((oc) => oc.doNothing())
|
|
966
|
+
.execute();
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
// The org requests this staging answers resolve with the confirm; on an item that existed
|
|
970
|
+
// already (imported meanwhile) a `named` scope gains their orgs. An org-owned item held back by
|
|
971
|
+
// the share gate fails closed before any request is marked (ruling P3-26; P3-14 refuses a
|
|
972
|
+
// super admin import of an org-owned name, so this should not be reached)
|
|
973
|
+
const item = created
|
|
974
|
+
? undefined
|
|
975
|
+
: await t
|
|
976
|
+
.selectFrom("catalog_items")
|
|
977
|
+
.select(["id", "name", "scope", "builtin", "owner_org_id", "shareable"])
|
|
978
|
+
.where("id", "=", itemId)
|
|
979
|
+
.forUpdate()
|
|
980
|
+
.executeTakeFirstOrThrow();
|
|
981
|
+
if (item !== undefined && !shareGate(item) && (await hasImportRequests(t, stagingId))) {
|
|
982
|
+
assertShareable(item);
|
|
983
|
+
}
|
|
984
|
+
const requestOrgs = await resolveImportRequests(t, stagingId, itemId, actor, opts);
|
|
985
|
+
if (item !== undefined) {
|
|
986
|
+
for (const org of requestOrgs)
|
|
987
|
+
await addScopeOrg(t, actor, item, org, opts);
|
|
988
|
+
}
|
|
989
|
+
const pending = owner !== undefined && reviewed !== undefined;
|
|
990
|
+
// An org's first version without an extension is installed at once: applied (P3-52)
|
|
991
|
+
if (owner !== undefined && created && !pending)
|
|
992
|
+
await markVersionApplied(t, itemId, staged.version);
|
|
993
|
+
if (pending) {
|
|
994
|
+
// Waits for the super admin; a later upload replaces the pending version (P3-10, P3-11)
|
|
995
|
+
await t
|
|
996
|
+
.updateTable("catalog_items")
|
|
997
|
+
.set({
|
|
998
|
+
...(created && { awaiting_confirmation: true }),
|
|
999
|
+
pending_version: staged.version,
|
|
1000
|
+
pending_by: actor,
|
|
1001
|
+
pending_at: sql `now()`,
|
|
1002
|
+
})
|
|
1003
|
+
.where("id", "=", itemId)
|
|
1004
|
+
.execute();
|
|
1005
|
+
}
|
|
1006
|
+
// A first version still waiting replaced by one without an extension: applied at once
|
|
1007
|
+
const replacedAwaiting = owner !== undefined && !pending && existing?.awaiting_confirmation === true;
|
|
1008
|
+
if (replacedAwaiting) {
|
|
1009
|
+
await t
|
|
1010
|
+
.updateTable("catalog_items")
|
|
1011
|
+
.set({
|
|
1012
|
+
awaiting_confirmation: false,
|
|
1013
|
+
pending_version: null,
|
|
1014
|
+
pending_by: null,
|
|
1015
|
+
pending_at: null,
|
|
1016
|
+
latest_version: staged.version,
|
|
1017
|
+
})
|
|
1018
|
+
.where("id", "=", itemId)
|
|
1019
|
+
.execute();
|
|
1020
|
+
await markVersionApplied(t, itemId, staged.version);
|
|
1021
|
+
await releaseExtensionClaim(t, m.name, existing.package_name);
|
|
1022
|
+
}
|
|
1023
|
+
return {
|
|
1024
|
+
itemId,
|
|
1025
|
+
created,
|
|
1026
|
+
firstVersion: (created && !pending) || replacedAwaiting,
|
|
1027
|
+
pending,
|
|
1028
|
+
now,
|
|
1029
|
+
previous,
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* The platform components of a new item. The item is committed already, so a failure is logged
|
|
1034
|
+
* and not thrown (like a failed deploy, the import itself succeeded); a run of the platform
|
|
1035
|
+
* components migration job (which writes what is missing) is enqueued on `cap-kernel-maintenance`
|
|
1036
|
+
* after {@link PLATFORM_SYNC_RETRY_MS}, one per item (deterministic job id). If that run fails
|
|
1037
|
+
* too, its `itemsFailed` shows in the super admin's inbox; the daily run and every worker start
|
|
1038
|
+
* try again.
|
|
1039
|
+
*/
|
|
1040
|
+
async syncPlatform(itemId, version) {
|
|
1041
|
+
try {
|
|
1042
|
+
await this.platform.syncFromVersion(itemId, version, { initial: true });
|
|
1043
|
+
}
|
|
1044
|
+
catch (err) {
|
|
1045
|
+
// Removed meanwhile (an org deletion racing a confirmation, P3-20): nothing to write
|
|
1046
|
+
const live = await this.db
|
|
1047
|
+
.selectFrom("catalog_items")
|
|
1048
|
+
.select("id")
|
|
1049
|
+
.where("id", "=", itemId)
|
|
1050
|
+
.where("deleted_at", "is", null)
|
|
1051
|
+
.executeTakeFirst();
|
|
1052
|
+
if (live === undefined) {
|
|
1053
|
+
this.log.info("catalog item removed before its platform components were written", {
|
|
1054
|
+
itemId,
|
|
1055
|
+
version,
|
|
1056
|
+
});
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
this.log.error("writing the platform components of a new catalog item failed", {
|
|
1060
|
+
itemId,
|
|
1061
|
+
version,
|
|
1062
|
+
err,
|
|
1063
|
+
});
|
|
1064
|
+
try {
|
|
1065
|
+
await this.maintenance.add(PLATFORM_MIGRATION_JOB, {}, {
|
|
1066
|
+
jobId: `${PLATFORM_MIGRATION_JOB}-retry-${itemId}`,
|
|
1067
|
+
delay: PLATFORM_SYNC_RETRY_MS,
|
|
1068
|
+
attempts: 1,
|
|
1069
|
+
removeOnComplete: true,
|
|
1070
|
+
removeOnFail: { age: 86_400 },
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
catch (e) {
|
|
1074
|
+
this.log.warn("cannot enqueue the platform components migration", { itemId, err: e });
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
600
1077
|
}
|
|
601
1078
|
/**
|
|
602
1079
|
* Writes the extension's permission snapshot for the version being imported (source web; cli
|
|
@@ -644,7 +1121,9 @@ let PluginImport = class PluginImport {
|
|
|
644
1121
|
}
|
|
645
1122
|
/**
|
|
646
1123
|
* Deploys the plugin's extension after the commit: `install` (a new install is disabled, a version
|
|
647
|
-
* change keeps the desired state) then `enable
|
|
1124
|
+
* change keeps the desired state) then `enable`, unless another enabled extension provides one of
|
|
1125
|
+
* its single-provider extension points: then it stays disabled (result `installed` with code
|
|
1126
|
+
* `extension.single_provider_enabled`). Nothing is thrown; the result says what happened.
|
|
648
1127
|
* When an upgrade was not installed, the snapshot overwritten at confirm is restored (the old
|
|
649
1128
|
* version keeps running, F-O; audit `extension.permissions_restored`). Retry through the extension
|
|
650
1129
|
* admin (the package is already in the package store) with the sha256 from the result.
|
|
@@ -659,8 +1138,9 @@ let PluginImport = class PluginImport {
|
|
|
659
1138
|
const failure = (e) => e instanceof ApiError
|
|
660
1139
|
? { code: e.code, message: e.message }
|
|
661
1140
|
: { code: "internal", message: "Internal error" };
|
|
1141
|
+
let installed;
|
|
662
1142
|
try {
|
|
663
|
-
await this.ops.install(p.name, p.sha256, actor, opts.actorTokenId, {
|
|
1143
|
+
installed = await this.ops.install(p.name, p.sha256, actor, opts.actorTokenId, {
|
|
664
1144
|
catalogItemId: itemId,
|
|
665
1145
|
});
|
|
666
1146
|
}
|
|
@@ -686,11 +1166,19 @@ let PluginImport = class PluginImport {
|
|
|
686
1166
|
}
|
|
687
1167
|
return result;
|
|
688
1168
|
}
|
|
1169
|
+
// An upgrade of an enabled extension that newly provides a held single-provider point: left
|
|
1170
|
+
// disabled by the install, and why
|
|
1171
|
+
if (installed.leftDisabled !== undefined) {
|
|
1172
|
+
return { ...base, result: "installed", ...installed.leftDisabled };
|
|
1173
|
+
}
|
|
689
1174
|
if (!enable)
|
|
690
1175
|
return { ...base, result: "installed" };
|
|
691
1176
|
try {
|
|
692
|
-
await this.ops.
|
|
693
|
-
|
|
1177
|
+
const r = await this.ops.enableUnlessOccupied(p.name, actor, opts.actorTokenId);
|
|
1178
|
+
if (r.enabled)
|
|
1179
|
+
return { ...base, result: "enabled" };
|
|
1180
|
+
// A single-provider point another enabled extension provides: installed disabled, and why
|
|
1181
|
+
return { ...base, result: "installed", ...r.note };
|
|
694
1182
|
}
|
|
695
1183
|
catch (e) {
|
|
696
1184
|
this.log.warn("enabling a plugin's extension failed", { plugin: p.name, err: e });
|
|
@@ -745,11 +1233,24 @@ let PluginImport = class PluginImport {
|
|
|
745
1233
|
return true;
|
|
746
1234
|
}
|
|
747
1235
|
/**
|
|
748
|
-
* Deletes expired staging rows and their object prefixes (maintenance job `app-staging-cleanup`)
|
|
749
|
-
* Row by row: objects first, then the
|
|
750
|
-
*
|
|
1236
|
+
* Deletes expired staging rows and their object prefixes (maintenance job `app-staging-cleanup`),
|
|
1237
|
+
* then the unused display files ({@link sweepDisplayFiles}). Row by row: objects first, then the
|
|
1238
|
+
* row (a failed object delete keeps the row for the next round); concurrent replicas skip each
|
|
1239
|
+
* other's rows (`SKIP LOCKED`). Returns the rows deleted.
|
|
751
1240
|
*/
|
|
752
1241
|
async cleanupExpired() {
|
|
1242
|
+
const total = await this.cleanupStagingRows();
|
|
1243
|
+
// display files no version or staging lists (an abandoned import's), older than a staging
|
|
1244
|
+
try {
|
|
1245
|
+
await sweepDisplayFiles(this.db, PLUGIN_STAGING_TTL_MS);
|
|
1246
|
+
}
|
|
1247
|
+
catch (err) {
|
|
1248
|
+
this.log.warn("cannot sweep unused catalog display files", { err });
|
|
1249
|
+
}
|
|
1250
|
+
return total;
|
|
1251
|
+
}
|
|
1252
|
+
/** The expired staging rows, batch by batch; returns the rows deleted. */
|
|
1253
|
+
async cleanupStagingRows() {
|
|
753
1254
|
let total = 0;
|
|
754
1255
|
for (;;) {
|
|
755
1256
|
const batch = await this.db
|
|
@@ -786,7 +1287,7 @@ let PluginImport = class PluginImport {
|
|
|
786
1287
|
const t = this.db;
|
|
787
1288
|
const locked = await t
|
|
788
1289
|
.selectFrom("plugin_import_staging")
|
|
789
|
-
.select("id")
|
|
1290
|
+
.select(["id", "org_id", "review", "manifest"])
|
|
790
1291
|
.where("id", "=", r.id)
|
|
791
1292
|
.where("expires_at", "<=", sql `now()`)
|
|
792
1293
|
.forUpdate()
|
|
@@ -797,8 +1298,86 @@ let PluginImport = class PluginImport {
|
|
|
797
1298
|
if (r.object_prefix)
|
|
798
1299
|
await this.files.deployment().deletePrefix(r.object_prefix);
|
|
799
1300
|
await t.deleteFrom("plugin_import_staging").where("id", "=", r.id).execute();
|
|
1301
|
+
await this.dropOrgPackage(locked);
|
|
800
1302
|
return true;
|
|
801
1303
|
}
|
|
1304
|
+
/**
|
|
1305
|
+
* An expired org staging's extension package (an org upload stores it at prepare, P3-10): removed
|
|
1306
|
+
* with the staging unless something else uses it — an install (running or migrated), a catalog
|
|
1307
|
+
* version, another staging — or it was stored by anyone else (the package row's source must be
|
|
1308
|
+
* this staging's own `catalog` ref). A platform staging keeps its package, as before. Its object
|
|
1309
|
+
* is deleted after the commit.
|
|
1310
|
+
*/
|
|
1311
|
+
async dropOrgPackage(row) {
|
|
1312
|
+
const sha = row.review.extension?.sha256;
|
|
1313
|
+
if (row.org_id === null || sha === undefined)
|
|
1314
|
+
return;
|
|
1315
|
+
const staged = row.manifest;
|
|
1316
|
+
const t = this.db;
|
|
1317
|
+
const pkg = await t
|
|
1318
|
+
.selectFrom("extension_packages")
|
|
1319
|
+
.select("blob_store")
|
|
1320
|
+
.where("sha256", "=", sha)
|
|
1321
|
+
.where("source", "=", "catalog")
|
|
1322
|
+
.where("source_ref", "=", `${staged.itemId}@${staged.version}`)
|
|
1323
|
+
.forUpdate()
|
|
1324
|
+
.executeTakeFirst();
|
|
1325
|
+
if (!pkg)
|
|
1326
|
+
return;
|
|
1327
|
+
const used = (await t
|
|
1328
|
+
.selectFrom("extension_installs")
|
|
1329
|
+
.select("name")
|
|
1330
|
+
.where((eb) => eb.or([eb("sha256", "=", sha), eb("migrated_sha", "=", sha)]))
|
|
1331
|
+
.executeTakeFirst()) ??
|
|
1332
|
+
(await t
|
|
1333
|
+
.selectFrom("catalog_item_versions")
|
|
1334
|
+
.select("version")
|
|
1335
|
+
.where("extension_sha256", "=", sha)
|
|
1336
|
+
.executeTakeFirst()) ??
|
|
1337
|
+
(await t
|
|
1338
|
+
.selectFrom("plugin_import_staging")
|
|
1339
|
+
.select("id")
|
|
1340
|
+
.where(sql `review->'extension'->>'sha256' = ${sha}`)
|
|
1341
|
+
.executeTakeFirst());
|
|
1342
|
+
if (used !== undefined)
|
|
1343
|
+
return;
|
|
1344
|
+
const build = await t
|
|
1345
|
+
.selectFrom("extension_client_builds")
|
|
1346
|
+
.select("object_prefix")
|
|
1347
|
+
.where("package_sha256", "=", sha)
|
|
1348
|
+
.executeTakeFirst();
|
|
1349
|
+
// extension_blobs (a PG-stored package) and extension_client_builds go with the row (ON
|
|
1350
|
+
// DELETE CASCADE)
|
|
1351
|
+
await t.deleteFrom("extension_packages").where("sha256", "=", sha).execute();
|
|
1352
|
+
if (build !== undefined) {
|
|
1353
|
+
afterCommit(async () => {
|
|
1354
|
+
try {
|
|
1355
|
+
await this.clientBuilds.deleteFiles(sha, build.object_prefix);
|
|
1356
|
+
}
|
|
1357
|
+
catch (err) {
|
|
1358
|
+
this.log.warn("cannot delete an expired org upload's client build objects", {
|
|
1359
|
+
sha256: sha,
|
|
1360
|
+
err,
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
// The object only once the row is gone for good: a failure leaves an unreferenced object
|
|
1366
|
+
// (harmless; a later upload of the same bytes rewrites it), never a row without its bytes
|
|
1367
|
+
if (pkg.blob_store === "object") {
|
|
1368
|
+
afterCommit(async () => {
|
|
1369
|
+
try {
|
|
1370
|
+
await this.files.deployment().delete(blobKey(sha));
|
|
1371
|
+
}
|
|
1372
|
+
catch (err) {
|
|
1373
|
+
this.log.warn("cannot delete an expired org upload's extension package object", {
|
|
1374
|
+
sha256: sha,
|
|
1375
|
+
err,
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
802
1381
|
// ---------------------------------------------------------------------------------------------
|
|
803
1382
|
/** npm / marketplace imports: the package must be the one that was asked for. */
|
|
804
1383
|
checkExpected(pkg, expect, format = "capybara") {
|
|
@@ -845,8 +1424,16 @@ let PluginImport = class PluginImport {
|
|
|
845
1424
|
if (data !== undefined && !stored.has(path))
|
|
846
1425
|
stored.set(path, fileOf(path, data));
|
|
847
1426
|
};
|
|
848
|
-
|
|
849
|
-
|
|
1427
|
+
const objectPaths = new Set();
|
|
1428
|
+
const keepObject = (path) => {
|
|
1429
|
+
keep(path);
|
|
1430
|
+
if (stored.has(path))
|
|
1431
|
+
objectPaths.add(path);
|
|
1432
|
+
};
|
|
1433
|
+
// The plugin icon and the setup guide documents (rendered by PluginGuides): display files
|
|
1434
|
+
const displayPaths = displayFilePaths(m, pkg.connectorTemplates.flatMap((c) => (c.file.icon === undefined ? [] : [c.file.icon])));
|
|
1435
|
+
for (const path of displayPaths)
|
|
1436
|
+
keep(path);
|
|
850
1437
|
const skills = [];
|
|
851
1438
|
for (const s of pkg.skills) {
|
|
852
1439
|
const files = s.files.map((f) => fileOf(f, pkg.files.get(`${s.dir}/${f}`)));
|
|
@@ -865,7 +1452,7 @@ let PluginImport = class PluginImport {
|
|
|
865
1452
|
suggestPinned: pinned.get(s.dir) === true,
|
|
866
1453
|
});
|
|
867
1454
|
for (const f of s.files)
|
|
868
|
-
|
|
1455
|
+
keepObject(`${s.dir}/${f}`);
|
|
869
1456
|
}
|
|
870
1457
|
catch (e) {
|
|
871
1458
|
if (!(e instanceof SkillArchiveError))
|
|
@@ -909,10 +1496,8 @@ let PluginImport = class PluginImport {
|
|
|
909
1496
|
else {
|
|
910
1497
|
problems.push(`${at}.connector: extension ${t.plugin} providing connector "${t.connector}" is not loaded in this deployment and is neither this plugin's extension nor a dependency`);
|
|
911
1498
|
}
|
|
912
|
-
|
|
1499
|
+
keepObject(c.path);
|
|
913
1500
|
templatePaths.set(c.id, c.path);
|
|
914
|
-
if (c.file.icon !== undefined)
|
|
915
|
-
keep(packagePath(c.file.icon));
|
|
916
1501
|
return {
|
|
917
1502
|
id: c.id,
|
|
918
1503
|
displayName: c.file.displayName,
|
|
@@ -926,43 +1511,89 @@ let PluginImport = class PluginImport {
|
|
|
926
1511
|
};
|
|
927
1512
|
});
|
|
928
1513
|
const agentTemplates = pkg.agentTemplates.map((a) => {
|
|
929
|
-
|
|
1514
|
+
keepObject(a.path);
|
|
930
1515
|
const { name, description, instructions, model, ...rest } = a.template;
|
|
931
1516
|
return { name, path: a.path, description, instructions, model: model ?? "inherit", ...rest };
|
|
932
1517
|
});
|
|
1518
|
+
// Themes: the file as written, the assets as sanitized by the reader (never the uploaded
|
|
1519
|
+
// originals: a shared path, e.g. the plugin icon, is stored sanitized too)
|
|
1520
|
+
const themes = pkg.themes.map((t) => {
|
|
1521
|
+
keepObject(t.path);
|
|
1522
|
+
for (const [path, data] of t.assets) {
|
|
1523
|
+
stored.set(path, fileOf(path, data));
|
|
1524
|
+
objectPaths.add(path);
|
|
1525
|
+
}
|
|
1526
|
+
const logo = t.theme.logo;
|
|
1527
|
+
return {
|
|
1528
|
+
id: t.id,
|
|
1529
|
+
name: t.theme.name,
|
|
1530
|
+
schemes: ["dark", "light"].filter((k) => t.theme.schemes[k] !== undefined),
|
|
1531
|
+
fonts: t.theme.fonts?.length ?? 0,
|
|
1532
|
+
logo: logo !== undefined && Object.keys(logo).length > 0,
|
|
1533
|
+
};
|
|
1534
|
+
});
|
|
933
1535
|
if (problems.length > 0)
|
|
934
1536
|
throw invalid(problems);
|
|
935
1537
|
return {
|
|
936
1538
|
files: [...stored.values()],
|
|
1539
|
+
displayPaths,
|
|
1540
|
+
objectPaths,
|
|
937
1541
|
templates,
|
|
938
1542
|
skills,
|
|
939
1543
|
agentTemplates,
|
|
1544
|
+
themes,
|
|
940
1545
|
notLoaded,
|
|
941
1546
|
templatePaths,
|
|
942
1547
|
};
|
|
943
1548
|
}
|
|
944
1549
|
/**
|
|
945
1550
|
* The highest imported, non-deleted catalog version satisfying each dependency's range (null when
|
|
946
|
-
* none does).
|
|
1551
|
+
* none does). An org upload (`owner`, P3-13) resolves only against items the org can use
|
|
1552
|
+
* ({@link usableBy}: confirmed, not disabled, offered to it), and any dependency left unresolved
|
|
1553
|
+
* -> 409 `plugin.dependency_unavailable` (details `[{ dependencies }]`, their names): an org
|
|
1554
|
+
* upload never brings in anything the org could not install itself.
|
|
947
1555
|
*/
|
|
948
|
-
async resolveDependencies(m) {
|
|
1556
|
+
async resolveDependencies(m, owner) {
|
|
949
1557
|
const deps = m.dependencies ?? [];
|
|
950
1558
|
if (deps.length === 0)
|
|
951
1559
|
return [];
|
|
952
|
-
const
|
|
1560
|
+
const names = deps.map((d) => d.name);
|
|
1561
|
+
const versions = this.db
|
|
953
1562
|
.selectFrom("catalog_items as i")
|
|
954
1563
|
.innerJoin("catalog_item_versions as v", "v.item_id", "i.id")
|
|
955
|
-
.select(["i.name", "v.version", "v.imported_at"])
|
|
956
1564
|
.where("i.deleted_at", "is", null)
|
|
957
|
-
.where("i.name", "in",
|
|
958
|
-
|
|
959
|
-
|
|
1565
|
+
.where("i.name", "in", names);
|
|
1566
|
+
const rows = owner === undefined
|
|
1567
|
+
? await versions.select(["i.name", "v.version", "v.imported_at"]).execute()
|
|
1568
|
+
: (await versions
|
|
1569
|
+
// the org's own row of a `named` list (usableBy reads whether it is listed)
|
|
1570
|
+
.leftJoin("catalog_item_scope_orgs as so", (j) => j.onRef("so.item_id", "=", "i.id").on("so.org_id", "=", owner.orgId))
|
|
1571
|
+
.select([
|
|
1572
|
+
"i.name",
|
|
1573
|
+
"v.version",
|
|
1574
|
+
"v.imported_at",
|
|
1575
|
+
"i.scope",
|
|
1576
|
+
"i.builtin",
|
|
1577
|
+
"i.disabled",
|
|
1578
|
+
"i.deleted_at",
|
|
1579
|
+
"i.awaiting_confirmation",
|
|
1580
|
+
"i.owner_org_id",
|
|
1581
|
+
"i.shareable",
|
|
1582
|
+
"so.org_id as listed",
|
|
1583
|
+
])
|
|
1584
|
+
.execute()).filter((r) => usableBy(r, owner.orgId, r.listed !== null));
|
|
1585
|
+
const resolved = deps.map((d) => ({
|
|
960
1586
|
name: d.name,
|
|
961
1587
|
range: d.version,
|
|
962
1588
|
resolved: maxSatisfying(rows
|
|
963
1589
|
.filter((r) => r.name === d.name)
|
|
964
1590
|
.map((r) => ({ version: r.version, importedAt: r.imported_at })), d.version)?.version ?? null,
|
|
965
1591
|
}));
|
|
1592
|
+
const missing = resolved.filter((d) => d.resolved === null).map((d) => d.name);
|
|
1593
|
+
if (owner !== undefined && missing.length > 0) {
|
|
1594
|
+
throw new ApiError("plugin.dependency_unavailable", `Dependencies not available to this organization: ${missing.join(", ")}`, [{ dependencies: missing }]);
|
|
1595
|
+
}
|
|
1596
|
+
return resolved;
|
|
966
1597
|
}
|
|
967
1598
|
/**
|
|
968
1599
|
* The extension's state on the deployment; installed from another npm package ->
|
|
@@ -980,7 +1611,7 @@ let PluginImport = class PluginImport {
|
|
|
980
1611
|
.where("extension_installs.name", "=", name)
|
|
981
1612
|
.executeTakeFirst();
|
|
982
1613
|
if (r && r.package_name !== packageName) {
|
|
983
|
-
throw new ApiError("extension.name_conflict", `Extension ${name} is already installed from package ${r.package_name}; package ${packageName} cannot use it
|
|
1614
|
+
throw new ApiError("extension.name_conflict", `Extension ${name} is already installed from package ${r.package_name}; package ${packageName} cannot use it`, [{ owner: await packageOwner(this.db, r.package_name, name) }]);
|
|
984
1615
|
}
|
|
985
1616
|
return r
|
|
986
1617
|
? { kind: "installed", version: r.version, sha256: r.sha256, packageName: r.package_name }
|
|
@@ -1002,7 +1633,7 @@ let PluginImport = class PluginImport {
|
|
|
1002
1633
|
name,
|
|
1003
1634
|
version: pkg.section.version,
|
|
1004
1635
|
sha256: pkg.sha256,
|
|
1005
|
-
...actionOf(state, pkg.sha256),
|
|
1636
|
+
...actionOf(state, pkg.sha256, pkg.section.version),
|
|
1006
1637
|
permissions,
|
|
1007
1638
|
added,
|
|
1008
1639
|
addedItems: permissionKeyItems(added),
|
|
@@ -1010,6 +1641,7 @@ let PluginImport = class PluginImport {
|
|
|
1010
1641
|
warnings,
|
|
1011
1642
|
reviewHash: extensionReviewHash(set, warnings),
|
|
1012
1643
|
sensitive: permissions.some((g) => g.sensitive) || warnings.length > 0,
|
|
1644
|
+
...(pkg.section.client !== undefined && { client: reviewClient(pkg) }),
|
|
1013
1645
|
};
|
|
1014
1646
|
}
|
|
1015
1647
|
async readStored(sha256) {
|
|
@@ -1027,10 +1659,11 @@ let PluginImport = class PluginImport {
|
|
|
1027
1659
|
.executeTakeFirstOrThrow();
|
|
1028
1660
|
const versions = await this.db
|
|
1029
1661
|
.selectFrom("catalog_item_versions")
|
|
1030
|
-
.select(["version", "source", "imported_at"])
|
|
1662
|
+
.select(["version", "source", "imported_at", "extension_sha256", "manifest", "source_format"])
|
|
1031
1663
|
.where("item_id", "=", itemId)
|
|
1032
1664
|
.execute();
|
|
1033
|
-
|
|
1665
|
+
const facts = await itemScopeFacts(this.db, [item], await itemConfirmations(this.admin, [item], new Map([[item.id, versions]])));
|
|
1666
|
+
return itemView(item, versions, 0, undefined, facts.get(item.id));
|
|
1034
1667
|
}
|
|
1035
1668
|
};
|
|
1036
1669
|
__decorate([
|
|
@@ -1054,21 +1687,29 @@ __decorate([
|
|
|
1054
1687
|
__decorate([
|
|
1055
1688
|
Transactional()
|
|
1056
1689
|
], PluginImport.prototype, "cleanupOne", null);
|
|
1690
|
+
__decorate([
|
|
1691
|
+
Transactional({ propagation: "mandatory" })
|
|
1692
|
+
], PluginImport.prototype, "dropOrgPackage", null);
|
|
1057
1693
|
PluginImport = __decorate([
|
|
1058
1694
|
Injectable(),
|
|
1059
1695
|
__param(0, Inject(KernelDb)),
|
|
1060
|
-
__param(1, Inject(
|
|
1061
|
-
__param(2, Inject(
|
|
1062
|
-
__param(3, Inject(
|
|
1063
|
-
__param(4, Inject(
|
|
1064
|
-
__param(5, Inject(
|
|
1065
|
-
__param(6, Inject(
|
|
1066
|
-
__param(7, Inject(
|
|
1067
|
-
__param(8, Inject(
|
|
1068
|
-
__param(9, Inject(
|
|
1069
|
-
__param(10, Inject(
|
|
1070
|
-
__param(11, Inject(
|
|
1071
|
-
__param(12, Inject(
|
|
1696
|
+
__param(1, Inject(SuperAdminLock)),
|
|
1697
|
+
__param(2, Inject(OrgLock)),
|
|
1698
|
+
__param(3, Inject(PluginInstallLock)),
|
|
1699
|
+
__param(4, Inject(PluginApproveLock)),
|
|
1700
|
+
__param(5, Inject(CatalogItemLock)),
|
|
1701
|
+
__param(6, Inject(KernelConfigService)),
|
|
1702
|
+
__param(7, Inject(StorageService)),
|
|
1703
|
+
__param(8, Inject(ExtensionInstalls)),
|
|
1704
|
+
__param(9, Inject(ExtensionAdminOps)),
|
|
1705
|
+
__param(10, Inject(ExtensionAdmin)),
|
|
1706
|
+
__param(11, Inject(ExtensionBlobs)),
|
|
1707
|
+
__param(12, Inject(ExtensionRegistry)),
|
|
1708
|
+
__param(13, Inject(KERNEL_LOGGER)),
|
|
1709
|
+
__param(14, Inject(TransactionHost)),
|
|
1710
|
+
__param(15, Inject(PlatformComponents)),
|
|
1711
|
+
__param(16, Inject(getQueueToken(MAINTENANCE_QUEUE_NAME))),
|
|
1712
|
+
__param(17, Inject(ClientBuilds))
|
|
1072
1713
|
], PluginImport);
|
|
1073
1714
|
export { PluginImport };
|
|
1074
1715
|
/**
|
|
@@ -1077,7 +1718,7 @@ export { PluginImport };
|
|
|
1077
1718
|
*/
|
|
1078
1719
|
function normalizedManifest(pkg) {
|
|
1079
1720
|
const pinned = new Map((pkg.manifest.skills ?? []).map((s) => [packagePath(s.path), s.pinned]));
|
|
1080
|
-
const { agents: _, ...manifest } = pkg.manifest;
|
|
1721
|
+
const { agents: _, themes: __, ...manifest } = pkg.manifest;
|
|
1081
1722
|
return {
|
|
1082
1723
|
...manifest,
|
|
1083
1724
|
skills: pkg.skills.map((s) => {
|
|
@@ -1089,6 +1730,7 @@ function normalizedManifest(pkg) {
|
|
|
1089
1730
|
...(pkg.agentTemplates.length > 0 && {
|
|
1090
1731
|
agents: pkg.agentTemplates.map((a) => ({ path: `./${a.path}` })),
|
|
1091
1732
|
}),
|
|
1733
|
+
...(pkg.themes.length > 0 && { themes: pkg.themes.map((t) => ({ path: `./${t.path}` })) }),
|
|
1092
1734
|
};
|
|
1093
1735
|
}
|
|
1094
1736
|
/** package.json `name`, or null without one (a git plugin; never the string "undefined"). */
|
|
@@ -1097,13 +1739,20 @@ function packageNameOf(pkg) {
|
|
|
1097
1739
|
return typeof name === "string" ? name : null;
|
|
1098
1740
|
}
|
|
1099
1741
|
/** The extension's deployment state -> action and current version. */
|
|
1100
|
-
function actionOf(s, sha256) {
|
|
1742
|
+
function actionOf(s, sha256, version) {
|
|
1101
1743
|
if (s.kind === "installed") {
|
|
1744
|
+
// A version below the deployed one is recorded in the catalog only: an import never
|
|
1745
|
+
// downgrades the deployment (ruling H)
|
|
1746
|
+
const older = s.sha256 !== sha256 &&
|
|
1747
|
+
semver.valid(version) !== null &&
|
|
1748
|
+
semver.valid(s.version) !== null &&
|
|
1749
|
+
semver.lt(version, s.version);
|
|
1102
1750
|
return {
|
|
1103
|
-
action: s.sha256 === sha256 ? "keep" : "upgrade",
|
|
1751
|
+
action: s.sha256 === sha256 || older ? "keep" : "upgrade",
|
|
1104
1752
|
deployed: true,
|
|
1105
1753
|
currentVersion: s.version,
|
|
1106
1754
|
currentSha256: s.sha256,
|
|
1755
|
+
...(older && { olderThanDeployed: true }),
|
|
1107
1756
|
};
|
|
1108
1757
|
}
|
|
1109
1758
|
return { action: "install", deployed: false, currentVersion: null, currentSha256: null };
|
|
@@ -1113,13 +1762,17 @@ function actionOf(s, sha256) {
|
|
|
1113
1762
|
* current version / package, its own review digest), every template field, each skill's name / path
|
|
1114
1763
|
* / file count, the dependency resolution, the sha256 of every stored file, the format, the
|
|
1115
1764
|
* translation report's items, the sha256 of the license text and the two review flags
|
|
1116
|
-
* (`claudeManifestIgnored`, `licenseTruncated`),
|
|
1765
|
+
* (`claudeManifestIgnored`, `licenseTruncated`), the agent templates when there are any and the
|
|
1766
|
+
* themes when there are any.
|
|
1117
1767
|
* Exported for tests. `repository` is display only.
|
|
1118
1768
|
*/
|
|
1119
1769
|
export function pluginReviewHash(r, files) {
|
|
1120
1770
|
const e = r.extension;
|
|
1121
1771
|
const lic = r.licenseText;
|
|
1122
|
-
|
|
1772
|
+
// canonicalJson, not JSON.stringify: the review is stored as jsonb, which reorders object keys,
|
|
1773
|
+
// so a template's auth / endpoint object would hash differently at confirm (plugin.review_stale
|
|
1774
|
+
// on every import of a plugin whose connector template has a non-trivial auth block).
|
|
1775
|
+
const canonical = canonicalJson([
|
|
1123
1776
|
r.name,
|
|
1124
1777
|
r.version,
|
|
1125
1778
|
r.contentDigest,
|
|
@@ -1146,9 +1799,34 @@ export function pluginReviewHash(r, files) {
|
|
|
1146
1799
|
...((r.agentTemplates ?? []).length > 0
|
|
1147
1800
|
? [(r.agentTemplates ?? []).map((a) => [a.path, canonicalJson(a)])]
|
|
1148
1801
|
: []),
|
|
1802
|
+
// themes, only when there are any, tagged (never read as agent templates)
|
|
1803
|
+
...((r.themes ?? []).length > 0
|
|
1804
|
+
? [{ themes: (r.themes ?? []).map((t) => [t.id, canonicalJson(t)]) }]
|
|
1805
|
+
: []),
|
|
1149
1806
|
]);
|
|
1150
1807
|
return createHash("sha256").update(canonical).digest("hex").slice(0, 32);
|
|
1151
1808
|
}
|
|
1809
|
+
/** The client code of a read extension package for its review (sizes from the package's files). */
|
|
1810
|
+
function reviewClient(pkg) {
|
|
1811
|
+
const c = pkg.section.client;
|
|
1812
|
+
const sizes = new Map(pkg.files.map((f) => [f.path, f.size]));
|
|
1813
|
+
const files = [
|
|
1814
|
+
...(c.entry !== undefined ? [c.entry] : []),
|
|
1815
|
+
...(c.styles ?? []),
|
|
1816
|
+
...(c.assets ?? []),
|
|
1817
|
+
].map((path) => {
|
|
1818
|
+
// checkClientFiles ran first: every listed file is in the package
|
|
1819
|
+
const size = sizes.get(path.slice(2));
|
|
1820
|
+
if (size === undefined)
|
|
1821
|
+
throw new Error(`client file ${path} is not in the package`);
|
|
1822
|
+
return { path, size };
|
|
1823
|
+
});
|
|
1824
|
+
return {
|
|
1825
|
+
files,
|
|
1826
|
+
totalBytes: files.reduce((n, f) => n + f.size, 0),
|
|
1827
|
+
apiVersion: c.apiVersion,
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1152
1830
|
/**
|
|
1153
1831
|
* A version change that is a downgrade (the imported version below the installed one) whose
|
|
1154
1832
|
* version has migrations not run on this deployment -> `extension.downgrade_unsupported` (the same
|
|
@@ -1206,3 +1884,23 @@ function pinnedNames(m, review) {
|
|
|
1206
1884
|
const byPath = new Map(review.skills.map((s) => [s.path, s.name]));
|
|
1207
1885
|
return (m.skills ?? []).filter((s) => s.pinned === true).map((s) => byPath.get(s.path) ?? s.path);
|
|
1208
1886
|
}
|
|
1887
|
+
/**
|
|
1888
|
+
* The staging rows a route may see (P3-8): the platform's (`org_id` null) without an owner, else
|
|
1889
|
+
* the owner org's.
|
|
1890
|
+
*/
|
|
1891
|
+
function ownStaging(owner) {
|
|
1892
|
+
return (eb) => owner === undefined ? eb("org_id", "is", null) : eb("org_id", "=", owner.orgId);
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* An org upload's custom deny, by content (ruling P3-15'): skills or agent templates ->
|
|
1896
|
+
* `customSkills`, connector templates -> `customConnectors`; each `deny` -> 403
|
|
1897
|
+
* `catalog.custom_disabled`. A package carrying neither passes; themes are covered by neither
|
|
1898
|
+
* switch (themes spec §6), so a themes-only upload passes.
|
|
1899
|
+
*/
|
|
1900
|
+
async function assertCustomContent(db, content) {
|
|
1901
|
+
if (content.skills.length > 0 || content.agentTemplates.length > 0) {
|
|
1902
|
+
await assertCustomAllowed(db, "customSkills");
|
|
1903
|
+
}
|
|
1904
|
+
if (content.templates.length > 0)
|
|
1905
|
+
await assertCustomAllowed(db, "customConnectors");
|
|
1906
|
+
}
|