@capybara-hq/kernel 0.1.0-rc.23 → 0.1.0-rc.25
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 +25 -25
- package/dist/admin/admin.module.d.ts +2 -1
- package/dist/admin/admin.module.js +9 -3
- package/dist/admin/health.service.d.ts +2 -2
- package/dist/admin/health.service.js +6 -2
- package/dist/admin/outbox-dead.controller.d.ts +23 -0
- package/dist/admin/outbox-dead.controller.js +62 -0
- package/dist/admin/outbox-dead.schemas.d.ts +8 -0
- package/dist/admin/outbox-dead.schemas.js +18 -0
- package/dist/admin/outbox-dead.service.d.ts +66 -0
- package/dist/admin/outbox-dead.service.js +179 -0
- package/dist/admin/overview.service.d.ts +40 -5
- package/dist/admin/overview.service.js +41 -7
- package/dist/agents/agents.module.js +3 -0
- package/dist/agents/agents.service.d.ts +6 -1
- package/dist/agents/agents.service.js +11 -2
- package/dist/agents/from-template.js +1 -1
- package/dist/background/finish.d.ts +5 -2
- package/dist/background/finish.js +14 -3
- package/dist/background/launch.d.ts +2 -1
- package/dist/background/launch.js +5 -2
- package/dist/background/store.d.ts +8 -0
- package/dist/background/store.js +24 -0
- package/dist/catalog/admin-catalog.controller.d.ts +21 -2
- package/dist/catalog/admin-catalog.controller.js +45 -6
- package/dist/catalog/admin-catalog.schemas.d.ts +5 -0
- package/dist/catalog/admin-catalog.schemas.js +8 -0
- package/dist/catalog/catalog-import.module.js +0 -4
- package/dist/catalog/catalog-scope.service.d.ts +63 -26
- package/dist/catalog/catalog-scope.service.js +146 -71
- package/dist/catalog/catalog.module.d.ts +2 -1
- package/dist/catalog/catalog.module.js +9 -4
- package/dist/catalog/catalog.service.d.ts +11 -4
- package/dist/catalog/catalog.service.js +21 -5
- package/dist/catalog/cli.d.ts +4 -3
- package/dist/catalog/cli.js +8 -13
- package/dist/catalog/job-ids.d.ts +8 -20
- package/dist/catalog/job-ids.js +11 -16
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-plugin-uploads.d.ts +11 -4
- package/dist/catalog/org-plugin-uploads.js +21 -6
- package/dist/catalog/owned-items.d.ts +6 -13
- package/dist/catalog/owned-items.js +11 -29
- package/dist/catalog/owned-plugin-cleanup.d.ts +8 -17
- package/dist/catalog/owned-plugin-cleanup.js +12 -66
- package/dist/catalog/platform-components.d.ts +56 -34
- package/dist/catalog/platform-components.js +68 -78
- package/dist/catalog/platform-import-update.d.ts +50 -0
- package/dist/catalog/platform-import-update.js +116 -0
- package/dist/catalog/plugin-import.d.ts +64 -26
- package/dist/catalog/plugin-import.js +113 -77
- package/dist/catalog/plugin-upgrade.d.ts +22 -4
- package/dist/catalog/plugin-upgrade.js +26 -19
- package/dist/catalog/scope-jobs.d.ts +59 -0
- package/dist/catalog/scope-jobs.js +65 -0
- package/dist/catalog/scope-sync-workers.d.ts +22 -0
- package/dist/catalog/scope-sync-workers.js +58 -2
- package/dist/catalog/scope-sync.d.ts +40 -65
- package/dist/catalog/scope-sync.js +114 -122
- package/dist/channels/channels.module.d.ts +5 -2
- package/dist/channels/channels.module.js +9 -2
- package/dist/channels/deliver-job.d.ts +25 -0
- package/dist/channels/deliver-job.js +25 -0
- package/dist/channels/inbound.d.ts +1 -1
- package/dist/channels/inbound.js +4 -17
- package/dist/channels/jobs.d.ts +28 -18
- package/dist/channels/jobs.js +63 -26
- package/dist/channels/threads.d.ts +4 -3
- package/dist/channels/threads.js +4 -3
- package/dist/config/schema.d.ts +0 -3
- package/dist/config/schema.js +11 -20
- package/dist/conversations/agent-tree.d.ts +16 -0
- package/dist/conversations/agent-tree.js +36 -0
- package/dist/conversations/conversations.controller.js +4 -2
- package/dist/conversations/conversations.service.d.ts +61 -19
- package/dist/conversations/conversations.service.js +69 -43
- package/dist/conversations/event-log.d.ts +7 -10
- package/dist/conversations/event-log.js +24 -15
- package/dist/conversations/events.d.ts +21 -0
- package/dist/conversations/events.js +26 -2
- package/dist/conversations/queue.service.d.ts +8 -3
- package/dist/conversations/queue.service.js +37 -13
- package/dist/conversations/source.d.ts +10 -0
- package/dist/conversations/source.js +17 -0
- package/dist/conversations/titles.d.ts +21 -8
- package/dist/conversations/titles.js +42 -15
- package/dist/conversations/tree.d.ts +10 -0
- package/dist/conversations/tree.js +35 -0
- package/dist/db/kernel-schema.d.ts +35 -22
- package/dist/devices/devices.service.d.ts +23 -11
- package/dist/devices/devices.service.js +34 -26
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +11 -0
- package/dist/evals/run-replay.d.ts +13 -2
- package/dist/evals/run-replay.js +42 -9
- package/dist/evals/snapshot.d.ts +7 -1
- package/dist/evals/snapshot.js +2 -1
- package/dist/extensions/extensions.module.js +3 -0
- package/dist/extensions/hooks.d.ts +22 -3
- package/dist/extensions/hooks.js +15 -1
- package/dist/extensions/lifecycle-hooks.d.ts +99 -0
- package/dist/extensions/lifecycle-hooks.js +273 -0
- package/dist/extensions/lifecycle.d.ts +6 -1
- package/dist/extensions/lifecycle.js +9 -2
- package/dist/extensions/org-config.d.ts +13 -1
- package/dist/extensions/org-config.js +19 -2
- package/dist/extensions/permission-view.d.ts +9 -5
- package/dist/extensions/permission-view.js +9 -4
- package/dist/extensions/point-defaults.d.ts +28 -1
- package/dist/extensions/point-defaults.js +44 -13
- package/dist/extensions/usage-subscribers.d.ts +43 -0
- package/dist/extensions/usage-subscribers.js +108 -0
- package/dist/http/api.module.js +2 -0
- package/dist/inbox/inbox.service.d.ts +6 -20
- package/dist/inbox/inbox.service.js +0 -3
- package/dist/inbox/org-notices.d.ts +1 -1
- package/dist/inbox/platform-inbox.service.d.ts +3 -32
- package/dist/inbox/platform-inbox.service.js +5 -54
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/infra/cli/kernel-cli.module.js +5 -0
- package/dist/infra/events/kernel-events.d.ts +9 -35
- package/dist/infra/outbox/outbox-relay.module.d.ts +6 -0
- package/dist/infra/outbox/outbox-relay.module.js +18 -0
- package/dist/infra/outbox/outbox.dispatcher.d.ts +103 -0
- package/dist/infra/outbox/outbox.dispatcher.js +310 -0
- package/dist/infra/outbox/outbox.module.d.ts +24 -0
- package/dist/infra/outbox/outbox.module.js +50 -0
- package/dist/infra/outbox/outbox.relay.d.ts +31 -0
- package/dist/infra/outbox/outbox.relay.js +76 -0
- package/dist/infra/outbox/outbox.service.d.ts +51 -0
- package/dist/infra/outbox/outbox.service.js +131 -0
- package/dist/infra/outbox/registry.d.ts +244 -0
- package/dist/infra/outbox/registry.js +234 -0
- package/dist/infra/queue/queue-names.d.ts +8 -0
- package/dist/infra/queue/queue-names.js +17 -0
- package/dist/kernel.module.js +3 -0
- package/dist/local-devices/device-policy.service.d.ts +4 -0
- package/dist/local-devices/device-policy.service.js +61 -3
- package/dist/local-devices/machines.d.ts +13 -5
- package/dist/local-devices/machines.js +45 -7
- package/dist/local-devices/policy-summary.d.ts +44 -1
- package/dist/local-devices/policy-summary.js +69 -0
- package/dist/models/embeddings.d.ts +9 -9
- package/dist/models/embeddings.js +11 -18
- package/dist/models/models.module.js +3 -0
- package/dist/orgs/directory-sync.js +1 -1
- package/dist/orgs/members.service.js +1 -1
- package/dist/orgs/offboarding.d.ts +50 -57
- package/dist/orgs/offboarding.js +117 -162
- package/dist/orgs/orgs.module.js +3 -0
- package/dist/orgs/orgs.service.d.ts +11 -5
- package/dist/orgs/orgs.service.js +22 -6
- package/dist/overrides.d.ts +23 -3
- package/dist/overrides.js +12 -2
- package/dist/platform/exclusions.js +5 -0
- package/dist/platform/ops/admin.ops.js +18 -2
- package/dist/platform/ops/catalog-admin.ops.d.ts +3 -1
- package/dist/platform/ops/catalog-admin.ops.js +32 -4
- package/dist/platform/ops/inbox.ops.js +4 -20
- package/dist/platform/ops/outbox.ops.d.ts +21 -0
- package/dist/platform/ops/outbox.ops.js +125 -0
- package/dist/platform/ops/platform.ops.d.ts +1 -0
- package/dist/platform/ops/platform.ops.js +6 -3
- package/dist/platform/ops/schedules.ops.js +40 -1
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +3 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/roles/worker-role.d.ts +10 -5
- package/dist/roles/worker-role.js +19 -9
- package/dist/roles/worker.module.js +11 -8
- package/dist/runtime/context/build.d.ts +3 -0
- package/dist/runtime/context/build.js +15 -0
- package/dist/runtime/context/plugin-context.d.ts +20 -0
- package/dist/runtime/context/plugin-context.js +30 -0
- package/dist/runtime/langgraph-loop.js +17 -5
- package/dist/runtime/limits.d.ts +15 -0
- package/dist/runtime/limits.js +25 -0
- package/dist/runtime/loop.d.ts +16 -3
- package/dist/runtime/loop.js +2 -1
- package/dist/runtime/maintenance.d.ts +7 -3
- package/dist/runtime/maintenance.js +52 -12
- package/dist/runtime/model-call.d.ts +20 -17
- package/dist/runtime/model-call.js +15 -24
- package/dist/runtime/plugin-context.service.d.ts +69 -0
- package/dist/runtime/plugin-context.service.js +208 -0
- package/dist/runtime/queue-lost-jobs.d.ts +24 -0
- package/dist/runtime/queue-lost-jobs.js +51 -0
- package/dist/runtime/run-control.d.ts +47 -5
- package/dist/runtime/run-control.js +79 -12
- package/dist/runtime/run-finish.d.ts +39 -12
- package/dist/runtime/run-finish.js +97 -14
- package/dist/runtime/run-jobs.d.ts +95 -13
- package/dist/runtime/run-jobs.js +199 -28
- package/dist/runtime/run-orphan-check.job.d.ts +142 -0
- package/dist/runtime/run-orphan-check.job.js +339 -0
- package/dist/runtime/run-processors.d.ts +16 -9
- package/dist/runtime/run-processors.js +1 -1
- package/dist/runtime/run-queue.d.ts +75 -53
- package/dist/runtime/run-queue.js +189 -263
- package/dist/runtime/run-steps.d.ts +1 -2
- package/dist/runtime/run-steps.js +8 -11
- package/dist/runtime/run-worker.d.ts +26 -16
- package/dist/runtime/run-worker.js +132 -37
- package/dist/runtime/runtime.module.d.ts +2 -3
- package/dist/runtime/runtime.module.js +7 -6
- package/dist/runtime/step-log.d.ts +16 -4
- package/dist/runtime/step-log.js +26 -6
- package/dist/runtime/stream.controller.d.ts +2 -4
- package/dist/runtime/stream.controller.js +5 -11
- package/dist/runtime/subagents/child.js +1 -1
- package/dist/runtime/subagents/definition.d.ts +2 -1
- package/dist/runtime/subagents/definition.js +4 -2
- package/dist/runtime/subagents/deliveries.d.ts +6 -3
- package/dist/runtime/subagents/deliveries.js +16 -7
- package/dist/runtime/subagents/dispatch.d.ts +12 -12
- package/dist/runtime/subagents/dispatch.js +14 -38
- package/dist/runtime/subagents/messages.d.ts +5 -1
- package/dist/runtime/subagents/messages.js +11 -3
- package/dist/runtime/subagents/skill-fork.d.ts +3 -3
- package/dist/runtime/subagents/skill-fork.js +8 -5
- package/dist/runtime/subagents/subagents.service.js +1 -1
- package/dist/runtime/subagents/tree-jobs.d.ts +61 -0
- package/dist/runtime/subagents/tree-jobs.js +86 -0
- package/dist/runtime/usage-report-jobs.d.ts +23 -48
- package/dist/runtime/usage-report-jobs.js +67 -119
- package/dist/runtime/usage-report.d.ts +28 -77
- package/dist/runtime/usage-report.js +35 -213
- package/dist/runtime/waits.d.ts +48 -198
- package/dist/runtime/waits.js +103 -805
- package/dist/sandbox/jobs.d.ts +20 -10
- package/dist/sandbox/jobs.js +23 -17
- package/dist/sandbox/sandbox.service.d.ts +17 -4
- package/dist/sandbox/sandbox.service.js +55 -14
- package/dist/schedules/calendar.d.ts +134 -0
- package/dist/schedules/calendar.js +410 -0
- package/dist/schedules/fire.d.ts +26 -7
- package/dist/schedules/fire.js +91 -22
- package/dist/schedules/job-ids.d.ts +66 -17
- package/dist/schedules/job-ids.js +81 -13
- package/dist/schedules/run-tracker.d.ts +0 -5
- package/dist/schedules/run-tracker.js +2 -14
- package/dist/schedules/scan.job.d.ts +13 -32
- package/dist/schedules/scan.job.js +50 -164
- package/dist/schedules/schedule-math.d.ts +42 -0
- package/dist/schedules/schedule-math.js +52 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +22 -6
- package/dist/schedules/scheduled-tasks.service.js +70 -14
- package/dist/schedules/schedules.controller.d.ts +5 -1
- package/dist/schedules/schedules.controller.js +15 -1
- package/dist/schedules/schedules.module.js +0 -4
- package/dist/schedules/schedules.schemas.d.ts +35 -0
- package/dist/schedules/schedules.schemas.js +27 -0
- package/dist/schedules/store.d.ts +5 -0
- package/dist/schedules/store.js +20 -0
- package/dist/skills/changes.controller.d.ts +1 -1
- package/dist/skills/changes.controller.js +1 -1
- package/dist/tools/approvals.service.d.ts +41 -11
- package/dist/tools/approvals.service.js +108 -14
- package/dist/tools/builtin-names.d.ts +5 -3
- package/dist/tools/builtin-names.js +12 -4
- package/dist/tools/builtins/builtin-tools.d.ts +1 -2
- package/dist/tools/builtins/builtin-tools.js +21 -17
- package/dist/tools/builtins/sandbox/bash.js +9 -3
- package/dist/tools/builtins/sandbox/common.d.ts +18 -1
- package/dist/tools/builtins/sandbox/common.js +14 -1
- package/dist/tools/builtins/sandbox/index.d.ts +2 -1
- package/dist/tools/builtins/sandbox/index.js +4 -1
- package/dist/tools/builtins/sandbox/task-list.d.ts +12 -0
- package/dist/tools/builtins/sandbox/task-list.js +130 -0
- package/dist/tools/builtins/sandbox/task-output.d.ts +8 -1
- package/dist/tools/builtins/sandbox/task-output.js +21 -3
- package/dist/tools/builtins/web/extract.d.ts +2 -4
- package/dist/tools/builtins/web/extract.js +2 -5
- package/dist/tools/pipeline.d.ts +12 -3
- package/dist/tools/pipeline.js +6 -1
- package/dist/tools/questions.service.d.ts +30 -10
- package/dist/tools/questions.service.js +41 -27
- package/dist/tools/registry.d.ts +12 -3
- package/dist/tools/registry.js +13 -3
- package/dist/tools/tools.module.js +4 -3
- package/package.json +3 -3
- package/src/migrations/0118_device_policy_ops.sql +6 -0
- package/src/migrations/0119_outbox.sql +22 -0
- package/src/migrations/0120_drop_usage_report_sweep.sql +7 -0
- package/src/migrations/0121_drop_platform_migration_runs.sql +12 -0
- package/src/migrations/0122_drop_scheduled_task_runs_rechecked_at.sql +5 -0
- package/src/migrations/0123_pgvector.sql +27 -0
- package/src/migrations/0124_conversation_source.sql +36 -0
- package/dist/catalog/platform-migration.d.ts +0 -115
- package/dist/catalog/platform-migration.js +0 -583
- package/dist/infra/queue/add-job-once.d.ts +0 -14
- package/dist/infra/queue/add-job-once.js +0 -16
|
@@ -9,9 +9,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
9
9
|
};
|
|
10
10
|
// Taking out the extension of a removed org-owned plugin (plugin scope phase 3, spec §14, P3-20,
|
|
11
11
|
// P3-21; pre-flight F9, F10): the one-off job `owned-plugin-cleanup-<itemId>` on
|
|
12
|
-
// `cap-kernel-maintenance` (dispatched by `MaintenanceProcessor`)
|
|
13
|
-
//
|
|
14
|
-
// imports.
|
|
12
|
+
// `cap-kernel-maintenance` (dispatched by `MaintenanceProcessor`), owed in the outbox by the
|
|
13
|
+
// removal's transaction (transactional outbox spec §8.1). Worker-only: `OwnedPluginCleanupModule`
|
|
14
|
+
// is imported only by `MaintenanceModule`, which only `WorkerModule` imports.
|
|
15
15
|
import { Inject, Injectable, Module } from "@nestjs/common";
|
|
16
16
|
import { ApiError } from "../errors.js";
|
|
17
17
|
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
@@ -19,11 +19,8 @@ import { ExtensionsModule } from "../extensions/extensions.module.js";
|
|
|
19
19
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
20
20
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
21
21
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
22
|
-
import { LockService } from "../infra/lock/lock.service.js";
|
|
23
|
-
import { LockedCron } from "../infra/schedule/locked-cron.decorator.js";
|
|
24
22
|
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
25
23
|
import { CatalogImportModule } from "./catalog.module.js";
|
|
26
|
-
import { OWNED_PLUGIN_CLEANUP_SWEEP_JOB } from "./job-ids.js";
|
|
27
24
|
import { CatalogItemLock } from "./locks.js";
|
|
28
25
|
import { releaseExtensionClaim } from "./ownership.js";
|
|
29
26
|
/** Codes that mean another run (or the confirmation's own take-out) got there first. */
|
|
@@ -31,27 +28,24 @@ const GONE = new Set(["extension.not_found", "extension.not_disabled"]);
|
|
|
31
28
|
/**
|
|
32
29
|
* The cleanup of a removed org-owned plugin: {@link run} disables and uninstalls its extension (an
|
|
33
30
|
* install of the item's name from the item's package) when no live catalog item uses it any more
|
|
34
|
-
* ({@link OwnedPluginCleanup.referenced}), then releases the extension name claim, in one
|
|
35
|
-
* (pre-flight F10: the claim of an
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* for every removed org-owned item whose extension is still installed (a lost enqueue).
|
|
31
|
+
* ({@link OwnedPluginCleanup.referenced}), then releases the extension name claim, in one
|
|
32
|
+
* transaction under the import's item name lock (pre-flight F10: the claim of an installed
|
|
33
|
+
* extension is released here, never at the removal). Idempotent: a live item (a transferred one),
|
|
34
|
+
* a platform item or nothing installed changes nothing but the claim. The extension's data,
|
|
35
|
+
* secrets and configs stay, as with every uninstall.
|
|
40
36
|
*/
|
|
41
37
|
let OwnedPluginCleanup = class OwnedPluginCleanup {
|
|
42
38
|
kdb;
|
|
43
39
|
ops;
|
|
44
40
|
itemLock;
|
|
45
|
-
lockService;
|
|
46
41
|
log;
|
|
47
42
|
txHost;
|
|
48
43
|
constructor(kdb, ops,
|
|
49
44
|
/** The import's item name lock (M5: no uninstall racing a re-import of the package). */
|
|
50
|
-
itemLock,
|
|
45
|
+
itemLock, log, txHost) {
|
|
51
46
|
this.kdb = kdb;
|
|
52
47
|
this.ops = ops;
|
|
53
48
|
this.itemLock = itemLock;
|
|
54
|
-
this.lockService = lockService;
|
|
55
49
|
this.log = log;
|
|
56
50
|
this.txHost = txHost;
|
|
57
51
|
}
|
|
@@ -100,50 +94,6 @@ let OwnedPluginCleanup = class OwnedPluginCleanup {
|
|
|
100
94
|
}
|
|
101
95
|
await releaseExtensionClaim(this.db, name, pkg);
|
|
102
96
|
}
|
|
103
|
-
/**
|
|
104
|
-
* Daily: {@link run} for every removed org-owned item no live item {@link referenced} names
|
|
105
|
-
* whose extension is still installed, or whose name claim is still held (a lost enqueue, or a
|
|
106
|
-
* run that uninstalled and failed before releasing the claim).
|
|
107
|
-
*/
|
|
108
|
-
async sweep() {
|
|
109
|
-
const rows = await this.db
|
|
110
|
-
.selectFrom("catalog_items as ci")
|
|
111
|
-
.select("ci.id")
|
|
112
|
-
.where("ci.deleted_at", "is not", null)
|
|
113
|
-
.where("ci.owner_org_id", "is not", null)
|
|
114
|
-
.where("ci.package_name", "is not", null)
|
|
115
|
-
.where(({ and, or, not, exists, selectFrom }) => and([
|
|
116
|
-
not(exists(selectFrom("catalog_items as live")
|
|
117
|
-
.select("live.id")
|
|
118
|
-
.whereRef("live.name", "=", "ci.name")
|
|
119
|
-
.whereRef("live.package_name", "=", "ci.package_name")
|
|
120
|
-
.where("live.deleted_at", "is", null)
|
|
121
|
-
.where((eb) => eb.or([
|
|
122
|
-
eb("live.owner_org_id", "is", null),
|
|
123
|
-
eb("live.owner_org_id", "=", eb.ref("ci.owner_org_id")),
|
|
124
|
-
])))),
|
|
125
|
-
or([
|
|
126
|
-
exists(selectFrom("extension_installs as x")
|
|
127
|
-
.innerJoin("extension_packages as p", "p.sha256", "x.sha256")
|
|
128
|
-
.select("x.name")
|
|
129
|
-
.whereRef("x.name", "=", "ci.name")
|
|
130
|
-
.whereRef("p.package_name", "=", "ci.package_name")),
|
|
131
|
-
exists(selectFrom("extension_name_owners as o")
|
|
132
|
-
.select("o.name")
|
|
133
|
-
.whereRef("o.name", "=", "ci.name")
|
|
134
|
-
.whereRef("o.package_name", "=", "ci.package_name")),
|
|
135
|
-
]),
|
|
136
|
-
]))
|
|
137
|
-
.execute();
|
|
138
|
-
for (const r of rows) {
|
|
139
|
-
try {
|
|
140
|
-
await this.run(r.id);
|
|
141
|
-
}
|
|
142
|
-
catch (err) {
|
|
143
|
-
this.log.error("owned plugin cleanup failed", { itemId: r.id, err });
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
97
|
/**
|
|
148
98
|
* A live catalog item still uses the extension: one named like it (a plugin and its extension
|
|
149
99
|
* share one name) from the same package whose owner is the removed item's owner (a re-upload)
|
|
@@ -165,22 +115,18 @@ let OwnedPluginCleanup = class OwnedPluginCleanup {
|
|
|
165
115
|
__decorate([
|
|
166
116
|
Transactional()
|
|
167
117
|
], OwnedPluginCleanup.prototype, "takeOut", null);
|
|
168
|
-
__decorate([
|
|
169
|
-
LockedCron("40 3 * * *", { name: OWNED_PLUGIN_CLEANUP_SWEEP_JOB })
|
|
170
|
-
], OwnedPluginCleanup.prototype, "sweep", null);
|
|
171
118
|
OwnedPluginCleanup = __decorate([
|
|
172
119
|
Injectable(),
|
|
173
120
|
__param(0, Inject(KernelDb)),
|
|
174
121
|
__param(1, Inject(ExtensionAdminOps)),
|
|
175
122
|
__param(2, Inject(CatalogItemLock)),
|
|
176
|
-
__param(3, Inject(
|
|
177
|
-
__param(4, Inject(
|
|
178
|
-
__param(5, Inject(TransactionHost))
|
|
123
|
+
__param(3, Inject(KERNEL_LOGGER)),
|
|
124
|
+
__param(4, Inject(TransactionHost))
|
|
179
125
|
], OwnedPluginCleanup);
|
|
180
126
|
export { OwnedPluginCleanup };
|
|
181
127
|
/**
|
|
182
128
|
* {@link OwnedPluginCleanup}: imported only by `MaintenanceModule` (the job's dispatcher), which
|
|
183
|
-
* only the worker role imports
|
|
129
|
+
* only the worker role imports.
|
|
184
130
|
*/
|
|
185
131
|
let OwnedPluginCleanupModule = class OwnedPluginCleanupModule {
|
|
186
132
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentTemplate, type ConnectorTemplateFile, type ParsedTheme } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import { type AgentTemplate, type ConnectorTemplateFile, type ParsedTheme, type PluginManifest } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import type { SkillManifest, SourceFormat } from "../db/kernel-schema.js";
|
|
3
3
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
4
4
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -26,7 +26,7 @@ export interface ChangedConnectorTemplateRef {
|
|
|
26
26
|
from: string | null;
|
|
27
27
|
to: string;
|
|
28
28
|
}
|
|
29
|
-
/** What {@link PlatformComponents.
|
|
29
|
+
/** What {@link PlatformComponents.applySyncIn} changed (unchanged components are not listed). */
|
|
30
30
|
export interface PlatformSyncResult {
|
|
31
31
|
skills: ChangedRef[];
|
|
32
32
|
agentTemplates: ChangedRef[];
|
|
@@ -37,11 +37,6 @@ export interface PlatformSyncResult {
|
|
|
37
37
|
export declare const platformSkillPrefix: (id: string, version: number) => string;
|
|
38
38
|
/** The prefix (in `deployment/`) of a platform agent template version's file. */
|
|
39
39
|
export declare const platformAgentTemplatePrefix: (id: string, version: number) => string;
|
|
40
|
-
/**
|
|
41
|
-
* The prefix (in `deployment/`) of a platform theme's files (themes spec §6); a version's fonts
|
|
42
|
-
* and logo are under `<prefix><version>-<catalog version>/` ({@link syncVersionPrefix}).
|
|
43
|
-
*/
|
|
44
|
-
export declare const platformThemePrefix: (id: string) => string;
|
|
45
40
|
/**
|
|
46
41
|
* A fresh prefix (in `deployment/`) for a version written before its transaction (ruling P3-45):
|
|
47
42
|
* `<id>/<version>-<uuid>/`, so two writers racing for one version number never overwrite each
|
|
@@ -49,12 +44,20 @@ export declare const platformThemePrefix: (id: string) => string;
|
|
|
49
44
|
*/
|
|
50
45
|
export declare const uniqueVersionPrefix: (base: string) => string;
|
|
51
46
|
/**
|
|
52
|
-
* The prefix of
|
|
53
|
-
*
|
|
54
|
-
*
|
|
47
|
+
* The prefix (in `deployment/`) of the files a plugin sync writes for a component version:
|
|
48
|
+
* `platform/<kind>/sha256-<digest>/`, the digest of the files' paths and contents
|
|
49
|
+
* ({@link skillFilesDigest}). The files are copied before the transaction that writes the rows (no
|
|
50
|
+
* storage call holds a row lock), so the same content always lands on the same keys: a sync or an
|
|
51
|
+
* import that is retried after its transaction rolled back writes nothing new, and versions with
|
|
52
|
+
* the same content share their objects. Objects are immutable and nothing deletes them (versions
|
|
53
|
+
* are kept), so an import that rolled back leaves at most objects a later import of that content
|
|
54
|
+
* reuses. Stored on the version row; readers use the stored prefix, so rows written before keep
|
|
55
55
|
* theirs.
|
|
56
56
|
*/
|
|
57
|
-
export declare const
|
|
57
|
+
export declare const contentPrefix: (kind: "skills" | "agent-templates" | "themes", files: {
|
|
58
|
+
path: string;
|
|
59
|
+
sha256: string;
|
|
60
|
+
}[]) => string;
|
|
58
61
|
/** The live component a plan was made against (absent: the plan creates it). */
|
|
59
62
|
interface Base<V> {
|
|
60
63
|
id: string;
|
|
@@ -112,12 +115,32 @@ export interface SyncPlan {
|
|
|
112
115
|
export declare class PlanStale extends Error {
|
|
113
116
|
}
|
|
114
117
|
/**
|
|
115
|
-
* A sync planned and its files copied ({@link PlatformComponents.prepareSync}
|
|
116
|
-
*
|
|
118
|
+
* A sync planned and its files copied ({@link PlatformComponents.prepareSync},
|
|
119
|
+
* {@link PlatformComponents.prepareImport}), waiting for its rows
|
|
120
|
+
* ({@link PlatformComponents.applySyncIn}). Opaque outside this module but for the item and the
|
|
121
|
+
* catalog version it was planned for.
|
|
117
122
|
*/
|
|
118
123
|
export interface PreparedSync {
|
|
119
124
|
readonly plan: SyncPlan;
|
|
120
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* The catalog version a sync plans from: its row, or a staged import whose row its transaction
|
|
128
|
+
* is about to write (the files are in object storage under `objectPrefix` already).
|
|
129
|
+
*/
|
|
130
|
+
export interface SyncSource {
|
|
131
|
+
itemId: string;
|
|
132
|
+
/** The plugin (the catalog item's name). */
|
|
133
|
+
plugin: string;
|
|
134
|
+
version: string;
|
|
135
|
+
manifest: PluginManifest;
|
|
136
|
+
objectPrefix: string | null;
|
|
137
|
+
files: {
|
|
138
|
+
path: string;
|
|
139
|
+
size: number;
|
|
140
|
+
sha256: string;
|
|
141
|
+
}[];
|
|
142
|
+
sourceFormat: SourceFormat;
|
|
143
|
+
}
|
|
121
144
|
/** A component version written by an upload ({@link PlatformComponents.uploadSkillVersion}). */
|
|
122
145
|
export interface UploadedComponentVersion {
|
|
123
146
|
kind: "skill" | "agent_template";
|
|
@@ -145,8 +168,9 @@ export interface UploadActor {
|
|
|
145
168
|
auditDetail?: Record<string, unknown>;
|
|
146
169
|
}
|
|
147
170
|
/**
|
|
148
|
-
* Writes the platform rows of a catalog version's components
|
|
149
|
-
*
|
|
171
|
+
* Writes the platform rows of a catalog version's components, in the transaction of the import
|
|
172
|
+
* confirm that makes an item's first usable version, of the super admin's confirmation of an org
|
|
173
|
+
* upload's first version, and of the platform plugin update to a new version.
|
|
150
174
|
*/
|
|
151
175
|
export declare class PlatformComponents {
|
|
152
176
|
private readonly kdb;
|
|
@@ -160,26 +184,19 @@ export declare class PlatformComponents {
|
|
|
160
184
|
/** CLI only (see `PluginImport.useCliStorage`): files go to the object store the CLI set up. */
|
|
161
185
|
useCliStorage(storage: PrefixedStorage): void;
|
|
162
186
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* Files are copied from the catalog prefix to `deployment/platform/…` before the rows are
|
|
168
|
-
* written (outside the transaction), so a sync that stops midway leaves at most unreferenced
|
|
169
|
-
* files, and running it again is a no-op once it succeeded. `initial` is the confirm that
|
|
170
|
-
* created the item. Components missing from the version are left alone (the platform update
|
|
171
|
-
* decides what a removal means). On success the item records `version` as
|
|
172
|
-
* `platform_synced_version`.
|
|
187
|
+
* The first phase of a sync inside a caller's transaction (the platform plugin update, the super
|
|
188
|
+
* admin's confirmation of an org upload's first version: `confirming`, the item still awaiting
|
|
189
|
+
* it): plans the version's components and copies their files, outside any transaction (no
|
|
190
|
+
* storage call holds a row lock). {@link applySyncIn} writes the rows.
|
|
173
191
|
*/
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}): Promise<
|
|
192
|
+
prepareSync(itemId: string, version: string, opts?: {
|
|
193
|
+
confirming?: boolean;
|
|
194
|
+
}): Promise<PreparedSync>;
|
|
177
195
|
/**
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
* row lock). {@link applySyncIn} writes the rows.
|
|
196
|
+
* {@link prepareSync} for an import whose transaction writes the catalog version (the item may
|
|
197
|
+
* not exist yet): plans from the staged content and copies the files, before that transaction.
|
|
181
198
|
*/
|
|
182
|
-
|
|
199
|
+
prepareImport(source: SyncSource): Promise<PreparedSync>;
|
|
183
200
|
/**
|
|
184
201
|
* The second phase: writes the prepared rows in the caller's transaction and records
|
|
185
202
|
* `platform_synced_version`. A component changed since the plan -> {@link PlanStale} (the caller
|
|
@@ -226,11 +243,16 @@ export declare class PlatformComponents {
|
|
|
226
243
|
private writeTemplateVersionIn;
|
|
227
244
|
/**
|
|
228
245
|
* Records that the item's platform components are written from `version`
|
|
229
|
-
* (`catalog_items.platform_synced_version
|
|
246
|
+
* (`catalog_items.platform_synced_version`, the version orgs install).
|
|
230
247
|
*/
|
|
231
248
|
private markSynced;
|
|
249
|
+
/**
|
|
250
|
+
* The stored catalog version `version` of live item `itemId`. An org upload still waiting for the
|
|
251
|
+
* super admin has no platform components (P3-9) unless this is its `confirming`.
|
|
252
|
+
*/
|
|
253
|
+
private source;
|
|
232
254
|
/** Reads the version's components and the live platform rows; keeps only what changed. */
|
|
233
|
-
private
|
|
255
|
+
private planFrom;
|
|
234
256
|
/** Copies the planned versions' files to their platform prefixes. */
|
|
235
257
|
private writeFiles;
|
|
236
258
|
/**
|
|
@@ -9,8 +9,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
9
9
|
};
|
|
10
10
|
// Platform components (plugin scope phase 2, rulings A2 and C2): the skills, agent templates,
|
|
11
11
|
// connector templates and themes of a catalog item, stored once for the deployment. Files live
|
|
12
|
-
// under `deployment/platform/{skills,agent-templates,themes}
|
|
13
|
-
//
|
|
12
|
+
// under `deployment/platform/{skills,agent-templates,themes}/…/`, never under an org prefix (orgs
|
|
13
|
+
// are purged by prefix): a plugin sync's under the digest of their content
|
|
14
|
+
// (`sha256-<digest>/`, {@link contentPrefix}), an upload's or a promotion's under
|
|
15
|
+
// `<id>/<version>-<uuid>/`.
|
|
14
16
|
import { createHash, randomUUID } from "node:crypto";
|
|
15
17
|
import { parseAgentTemplate, } from "@capybara-hq/plugin-sdk";
|
|
16
18
|
import { Inject, Injectable } from "@nestjs/common";
|
|
@@ -32,11 +34,6 @@ import { assertNotAwaiting } from "./ownership.js";
|
|
|
32
34
|
export const platformSkillPrefix = (id, version) => `platform/skills/${id}/${version}/`;
|
|
33
35
|
/** The prefix (in `deployment/`) of a platform agent template version's file. */
|
|
34
36
|
export const platformAgentTemplatePrefix = (id, version) => `platform/agent-templates/${id}/${version}/`;
|
|
35
|
-
/**
|
|
36
|
-
* The prefix (in `deployment/`) of a platform theme's files (themes spec §6); a version's fonts
|
|
37
|
-
* and logo are under `<prefix><version>-<catalog version>/` ({@link syncVersionPrefix}).
|
|
38
|
-
*/
|
|
39
|
-
export const platformThemePrefix = (id) => `platform/themes/${id}/`;
|
|
40
37
|
/**
|
|
41
38
|
* A fresh prefix (in `deployment/`) for a version written before its transaction (ruling P3-45):
|
|
42
39
|
* `<id>/<version>-<uuid>/`, so two writers racing for one version number never overwrite each
|
|
@@ -44,22 +41,26 @@ export const platformThemePrefix = (id) => `platform/themes/${id}/`;
|
|
|
44
41
|
*/
|
|
45
42
|
export const uniqueVersionPrefix = (base) => `${base.slice(0, -1)}-${randomUUID()}/`;
|
|
46
43
|
/**
|
|
47
|
-
* The prefix of
|
|
48
|
-
*
|
|
49
|
-
*
|
|
44
|
+
* The prefix (in `deployment/`) of the files a plugin sync writes for a component version:
|
|
45
|
+
* `platform/<kind>/sha256-<digest>/`, the digest of the files' paths and contents
|
|
46
|
+
* ({@link skillFilesDigest}). The files are copied before the transaction that writes the rows (no
|
|
47
|
+
* storage call holds a row lock), so the same content always lands on the same keys: a sync or an
|
|
48
|
+
* import that is retried after its transaction rolled back writes nothing new, and versions with
|
|
49
|
+
* the same content share their objects. Objects are immutable and nothing deletes them (versions
|
|
50
|
+
* are kept), so an import that rolled back leaves at most objects a later import of that content
|
|
51
|
+
* reuses. Stored on the version row; readers use the stored prefix, so rows written before keep
|
|
50
52
|
* theirs.
|
|
51
53
|
*/
|
|
52
|
-
export const
|
|
54
|
+
export const contentPrefix = (kind, files) => `platform/${kind}/sha256-${skillFilesDigest(files)}/`;
|
|
53
55
|
/** 409 `catalog.not_owned`: an org's own promoted item is versioned by its owner only (P3-48). */
|
|
54
56
|
const ownedByOrg = (what, name) => new ApiError("catalog.not_owned", `The ${what} ${name} belongs to an organization that shared it: only that organization uploads its versions`);
|
|
55
57
|
/** A component changed between the plan and its write (a concurrent sync): plan again. */
|
|
56
58
|
export class PlanStale extends Error {
|
|
57
59
|
}
|
|
58
|
-
/** Plans are retried this many times against concurrent syncs of the same item. */
|
|
59
|
-
const SYNC_ATTEMPTS = 3;
|
|
60
60
|
/**
|
|
61
|
-
* Writes the platform rows of a catalog version's components
|
|
62
|
-
*
|
|
61
|
+
* Writes the platform rows of a catalog version's components, in the transaction of the import
|
|
62
|
+
* confirm that makes an item's first usable version, of the super admin's confirmation of an org
|
|
63
|
+
* upload's first version, and of the platform plugin update to a new version.
|
|
63
64
|
*/
|
|
64
65
|
let PlatformComponents = class PlatformComponents {
|
|
65
66
|
kdb;
|
|
@@ -82,56 +83,30 @@ let PlatformComponents = class PlatformComponents {
|
|
|
82
83
|
useCliStorage(storage) {
|
|
83
84
|
this.files = storage;
|
|
84
85
|
}
|
|
86
|
+
// A plugin sync matches a component by plugin and name (connector templates by item and template
|
|
87
|
+
// id) and gives it a new version only when its content changed (skills by their files' digest,
|
|
88
|
+
// templates by canonical JSON); new rows follow the plugin's scope (`scope_mode: follow`).
|
|
89
|
+
// Components missing from the version are left alone (the platform update decides what a removal
|
|
90
|
+
// means). It runs in two phases: {@link prepareImport} / {@link prepareSync} plan and copy the
|
|
91
|
+
// files (keyed by content, {@link contentPrefix}) before the caller's transaction, and
|
|
92
|
+
// {@link applySyncIn} writes the rows and `platform_synced_version` in it.
|
|
85
93
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* Files are copied from the catalog prefix to `deployment/platform/…` before the rows are
|
|
91
|
-
* written (outside the transaction), so a sync that stops midway leaves at most unreferenced
|
|
92
|
-
* files, and running it again is a no-op once it succeeded. `initial` is the confirm that
|
|
93
|
-
* created the item. Components missing from the version are left alone (the platform update
|
|
94
|
-
* decides what a removal means). On success the item records `version` as
|
|
95
|
-
* `platform_synced_version`.
|
|
94
|
+
* The first phase of a sync inside a caller's transaction (the platform plugin update, the super
|
|
95
|
+
* admin's confirmation of an org upload's first version: `confirming`, the item still awaiting
|
|
96
|
+
* it): plans the version's components and copies their files, outside any transaction (no
|
|
97
|
+
* storage call holds a row lock). {@link applySyncIn} writes the rows.
|
|
96
98
|
*/
|
|
97
|
-
async
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
plan.agentTemplates.length === 0 &&
|
|
102
|
-
plan.connectorTemplates.length === 0 &&
|
|
103
|
-
plan.themes.length === 0) {
|
|
104
|
-
await this.markSynced(itemId, version);
|
|
105
|
-
return { skills: [], agentTemplates: [], connectorTemplates: [], themes: [] };
|
|
106
|
-
}
|
|
107
|
-
await this.writeFiles(plan);
|
|
108
|
-
try {
|
|
109
|
-
const r = await this.apply(plan);
|
|
110
|
-
await this.markSynced(itemId, version);
|
|
111
|
-
this.log.info("platform components synced", {
|
|
112
|
-
itemId,
|
|
113
|
-
version,
|
|
114
|
-
initial: opts.initial,
|
|
115
|
-
skills: r.skills.length,
|
|
116
|
-
agentTemplates: r.agentTemplates.length,
|
|
117
|
-
connectorTemplates: r.connectorTemplates.length,
|
|
118
|
-
themes: r.themes.length,
|
|
119
|
-
});
|
|
120
|
-
return r;
|
|
121
|
-
}
|
|
122
|
-
catch (e) {
|
|
123
|
-
if (!(e instanceof PlanStale) || attempt >= SYNC_ATTEMPTS)
|
|
124
|
-
throw e;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
99
|
+
async prepareSync(itemId, version, opts = {}) {
|
|
100
|
+
const plan = await this.planFrom(await this.source(itemId, version, opts.confirming === true));
|
|
101
|
+
await this.writeFiles(plan);
|
|
102
|
+
return { plan };
|
|
127
103
|
}
|
|
128
104
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* row lock). {@link applySyncIn} writes the rows.
|
|
105
|
+
* {@link prepareSync} for an import whose transaction writes the catalog version (the item may
|
|
106
|
+
* not exist yet): plans from the staged content and copies the files, before that transaction.
|
|
132
107
|
*/
|
|
133
|
-
async
|
|
134
|
-
const plan = await this.
|
|
108
|
+
async prepareImport(source) {
|
|
109
|
+
const plan = await this.planFrom(source);
|
|
135
110
|
await this.writeFiles(plan);
|
|
136
111
|
return { plan };
|
|
137
112
|
}
|
|
@@ -411,7 +386,7 @@ let PlatformComponents = class PlatformComponents {
|
|
|
411
386
|
}
|
|
412
387
|
/**
|
|
413
388
|
* Records that the item's platform components are written from `version`
|
|
414
|
-
* (`catalog_items.platform_synced_version
|
|
389
|
+
* (`catalog_items.platform_synced_version`, the version orgs install).
|
|
415
390
|
*/
|
|
416
391
|
async markSynced(itemId, version) {
|
|
417
392
|
await this.db
|
|
@@ -420,16 +395,18 @@ let PlatformComponents = class PlatformComponents {
|
|
|
420
395
|
.where("id", "=", itemId)
|
|
421
396
|
.execute();
|
|
422
397
|
}
|
|
423
|
-
/**
|
|
424
|
-
|
|
398
|
+
/**
|
|
399
|
+
* The stored catalog version `version` of live item `itemId`. An org upload still waiting for the
|
|
400
|
+
* super admin has no platform components (P3-9) unless this is its `confirming`.
|
|
401
|
+
*/
|
|
402
|
+
async source(itemId, version, confirming) {
|
|
425
403
|
const item = await this.db
|
|
426
404
|
.selectFrom("catalog_items")
|
|
427
405
|
.select(["name", "awaiting_confirmation"])
|
|
428
406
|
.where("id", "=", itemId)
|
|
429
407
|
.where("deleted_at", "is", null)
|
|
430
408
|
.executeTakeFirst();
|
|
431
|
-
|
|
432
|
-
if (item !== undefined)
|
|
409
|
+
if (item !== undefined && !confirming)
|
|
433
410
|
assertNotAwaiting(item);
|
|
434
411
|
const row = item
|
|
435
412
|
? await this.db
|
|
@@ -442,21 +419,36 @@ let PlatformComponents = class PlatformComponents {
|
|
|
442
419
|
if (!item || !row) {
|
|
443
420
|
throw new ApiError("catalog.item_not_found", `Catalog item ${itemId}@${version} not found`);
|
|
444
421
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
422
|
+
return {
|
|
423
|
+
itemId,
|
|
424
|
+
plugin: item.name,
|
|
425
|
+
version,
|
|
426
|
+
manifest: row.manifest,
|
|
427
|
+
objectPrefix: row.object_prefix,
|
|
428
|
+
files: row.files,
|
|
429
|
+
sourceFormat: row.source_format,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
/** Reads the version's components and the live platform rows; keeps only what changed. */
|
|
433
|
+
async planFrom(src) {
|
|
434
|
+
const { itemId, plugin, version, manifest } = src;
|
|
435
|
+
const v = {
|
|
436
|
+
manifest,
|
|
437
|
+
object_prefix: src.objectPrefix,
|
|
438
|
+
files: src.files,
|
|
439
|
+
};
|
|
448
440
|
const plan = {
|
|
449
441
|
itemId,
|
|
450
442
|
plugin,
|
|
451
443
|
version,
|
|
452
|
-
sourceFormat:
|
|
444
|
+
sourceFormat: src.sourceFormat,
|
|
453
445
|
skills: [],
|
|
454
446
|
agentTemplates: [],
|
|
455
447
|
connectorTemplates: [],
|
|
456
448
|
themes: [],
|
|
457
449
|
};
|
|
458
450
|
for (const s of manifest.skills ?? []) {
|
|
459
|
-
const files = await readCatalogFiles(this.files,
|
|
451
|
+
const files = await readCatalogFiles(this.files, v.object_prefix, v.files, packagePath(s.path));
|
|
460
452
|
const pkg = { ...skillOf(files), files };
|
|
461
453
|
const live = await this.db
|
|
462
454
|
.selectFrom("platform_skills as p")
|
|
@@ -475,8 +467,7 @@ let PlatformComponents = class PlatformComponents {
|
|
|
475
467
|
base: live && { id: live.id, version: live.current_version },
|
|
476
468
|
id,
|
|
477
469
|
to,
|
|
478
|
-
|
|
479
|
-
prefix: syncVersionPrefix(platformSkillPrefix(id, to), version),
|
|
470
|
+
prefix: contentPrefix("skills", files),
|
|
480
471
|
files,
|
|
481
472
|
manifest: skillManifest(pkg),
|
|
482
473
|
});
|
|
@@ -495,18 +486,19 @@ let PlatformComponents = class PlatformComponents {
|
|
|
495
486
|
.executeTakeFirst();
|
|
496
487
|
if (live && canonicalJson(live.definition) === canonicalJson(a.template))
|
|
497
488
|
continue;
|
|
498
|
-
const [file] = await readCatalogFiles(this.files,
|
|
489
|
+
const [file] = await readCatalogFiles(this.files, v.object_prefix, v.files.filter((f) => f.path === a.path));
|
|
499
490
|
if (!file)
|
|
500
491
|
throw new ApiError("internal", `Stored agent template ${a.path} is missing`);
|
|
501
492
|
const id = live?.id ?? randomUUID();
|
|
502
493
|
const to = (live?.current_version ?? 0) + 1;
|
|
494
|
+
const name = file.path.split("/").pop();
|
|
503
495
|
plan.agentTemplates.push({
|
|
504
496
|
name: a.template.name,
|
|
505
497
|
base: live && { id: live.id, version: live.current_version },
|
|
506
498
|
id,
|
|
507
499
|
to,
|
|
508
|
-
prefix:
|
|
509
|
-
file: { ...file, path:
|
|
500
|
+
prefix: contentPrefix("agent-templates", [{ path: name, sha256: file.sha256 }]),
|
|
501
|
+
file: { ...file, path: name },
|
|
510
502
|
template: a.template,
|
|
511
503
|
});
|
|
512
504
|
}
|
|
@@ -554,9 +546,7 @@ let PlatformComponents = class PlatformComponents {
|
|
|
554
546
|
base: live && { id: live.id, version: live.current_version },
|
|
555
547
|
id,
|
|
556
548
|
to,
|
|
557
|
-
prefix: t.assets.length > 0
|
|
558
|
-
? syncVersionPrefix(`${platformThemePrefix(id)}${to}/`, version)
|
|
559
|
-
: null,
|
|
549
|
+
prefix: t.assets.length > 0 ? contentPrefix("themes", t.assets) : null,
|
|
560
550
|
files: t.assets,
|
|
561
551
|
theme: t.theme,
|
|
562
552
|
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { KernelLogger } from "../log.js";
|
|
2
|
+
import type { ActorOpts, CatalogItemView } from "./catalog.service.js";
|
|
3
|
+
import { PluginImport } from "./plugin-import.js";
|
|
4
|
+
import { PlatformPluginUpdater, type PlatformUpdatePreview, type PlatformUpdateResult } from "./plugin-upgrade.js";
|
|
5
|
+
/** `POST /api/v1/admin/catalog/imports/:stagingId/update`: the import and the update it applied. */
|
|
6
|
+
export interface PlatformImportUpdateResult {
|
|
7
|
+
item: CatalogItemView;
|
|
8
|
+
update: PlatformUpdateResult;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The platform's update of an installed plugin to a version staged for import (the one wizard of
|
|
12
|
+
* the admin plugin pages, maintainer decision 2026-11-13): the import review (prepared as any
|
|
13
|
+
* import, `PluginImport.prepare`) and the platform update preview of the staged version
|
|
14
|
+
* ({@link preview}: `PlatformPluginUpdater.previewStaged`, the target read from the staging) are
|
|
15
|
+
* confirmed together ({@link confirm} with the review's `reviewHash` and the preview's `diffHash`).
|
|
16
|
+
* Nothing is written before that confirm: cancelling the wizard leaves only the staging row, which
|
|
17
|
+
* expires like any staged import.
|
|
18
|
+
*
|
|
19
|
+
* The confirm holds the item's update lock (`PlatformPluginUpdater.withItemLock`, one per item
|
|
20
|
+
* across replicas: another update -> 409 `plugin.install_in_progress`), recomputes the preview
|
|
21
|
+
* (another `diffHash` -> 409 `plugin.upgrade_stale`, nothing written), commits the import without
|
|
22
|
+
* deploying its extension (the permission snapshot is written as the review approved it), then
|
|
23
|
+
* runs the platform update, which moves the extension with its own rollback and writes the
|
|
24
|
+
* components in one transaction. When that update fails, the platform stays on its version, the
|
|
25
|
+
* extension where it was and its previous approval is put back; the imported version stays in the
|
|
26
|
+
* catalog (its 版本 tab, and 更新到 retries the update with the plain update preview): 409
|
|
27
|
+
* `plugin.imported_not_updated` says so, with the cause in the details. No in-process state.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PlatformImportUpdate {
|
|
30
|
+
private readonly pluginImport;
|
|
31
|
+
private readonly updater;
|
|
32
|
+
private readonly log;
|
|
33
|
+
constructor(pluginImport: PluginImport, updater: PlatformPluginUpdater, log: KernelLogger);
|
|
34
|
+
/**
|
|
35
|
+
* The platform update the staged version would apply (writes nothing). The staging must be a
|
|
36
|
+
* platform staging (else 404 `plugin.staging_not_found`) of a new version of a live
|
|
37
|
+
* platform-owned plugin (else 409 `plugin.upgrade_target_invalid`, reason `not_installed`); the
|
|
38
|
+
* updater's refusals apply as for any update preview. `needsApproval` is false: the confirm
|
|
39
|
+
* approves the permissions the review shows.
|
|
40
|
+
*/
|
|
41
|
+
preview(stagingId: string): Promise<PlatformUpdatePreview>;
|
|
42
|
+
/** Confirms the import and the update together (see the class comment). */
|
|
43
|
+
confirm(actor: string, stagingId: string, input: {
|
|
44
|
+
reviewHash: string;
|
|
45
|
+
diffHash: string;
|
|
46
|
+
}, opts?: ActorOpts): Promise<PlatformImportUpdateResult>;
|
|
47
|
+
/** The staged target, which must be a new version of a live platform-owned plugin. */
|
|
48
|
+
private target;
|
|
49
|
+
private previewOf;
|
|
50
|
+
}
|