@capybara-hq/kernel 0.1.0-rc.24 → 0.1.0-rc.26
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/dist/admin/admin.module.js +2 -0
- package/dist/admin/health.service.d.ts +2 -2
- package/dist/admin/health.service.js +6 -2
- package/dist/admin/outbox-dead.service.d.ts +7 -3
- package/dist/admin/outbox-dead.service.js +17 -6
- package/dist/admin/overview.service.d.ts +6 -6
- package/dist/admin/overview.service.js +7 -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/background/wake-rules.d.ts +5 -0
- package/dist/background/wake-rules.js +16 -5
- 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.js +4 -3
- 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/plugin-import.d.ts +28 -25
- package/dist/catalog/plugin-import.js +90 -76
- package/dist/catalog/plugin-upgrade.d.ts +4 -4
- package/dist/catalog/plugin-upgrade.js +7 -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 +9 -8
- package/dist/channels/channels.module.js +11 -10
- package/dist/channels/connections.service.d.ts +3 -3
- package/dist/channels/connections.service.js +6 -6
- package/dist/channels/deliver-job.d.ts +10 -3
- package/dist/channels/deliver-job.js +7 -3
- package/dist/channels/inbound.js +2 -2
- package/dist/channels/jobs.d.ts +11 -4
- package/dist/channels/jobs.js +18 -3
- package/dist/channels/outbound.d.ts +5 -2
- package/dist/channels/outbound.js +9 -2
- package/dist/channels/threads.d.ts +4 -3
- package/dist/channels/threads.js +4 -3
- package/dist/conversations/conversations.controller.d.ts +4 -2
- package/dist/conversations/conversations.controller.js +8 -4
- package/dist/conversations/conversations.service.d.ts +54 -9
- package/dist/conversations/conversations.service.js +94 -25
- package/dist/conversations/events.d.ts +27 -0
- package/dist/conversations/events.js +30 -1
- package/dist/conversations/source.d.ts +10 -0
- package/dist/conversations/source.js +17 -0
- package/dist/conversations/tree.d.ts +10 -0
- package/dist/conversations/tree.js +35 -0
- package/dist/db/kernel-schema.d.ts +19 -15
- package/dist/devices/devices.service.d.ts +25 -14
- package/dist/devices/devices.service.js +36 -30
- package/dist/evals/evals.module.js +5 -1
- package/dist/evals/jobs.d.ts +14 -6
- package/dist/evals/jobs.js +21 -19
- package/dist/evals/run-replay.d.ts +13 -2
- package/dist/evals/run-replay.js +28 -1
- package/dist/evals/runs.service.d.ts +5 -6
- package/dist/evals/runs.service.js +11 -33
- package/dist/evals/snapshot.d.ts +7 -1
- package/dist/evals/snapshot.js +2 -1
- 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/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/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/infra/outbox/outbox.service.d.ts +6 -0
- package/dist/infra/outbox/outbox.service.js +51 -17
- package/dist/infra/outbox/registry.d.ts +176 -0
- package/dist/infra/outbox/registry.js +183 -0
- package/dist/infra/queue/queue-names.d.ts +1 -1
- package/dist/infra/queue/queue-names.js +1 -0
- package/dist/local-devices/device-policy.service.d.ts +131 -26
- package/dist/local-devices/device-policy.service.js +341 -145
- package/dist/local-devices/machines.d.ts +17 -2
- package/dist/local-devices/machines.js +66 -5
- package/dist/local-devices/policy-op-jobs.d.ts +15 -0
- package/dist/local-devices/policy-op-jobs.js +12 -0
- package/dist/local-devices/policy-summary.d.ts +36 -3
- package/dist/local-devices/policy-summary.js +47 -1
- 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 +19 -7
- package/dist/overrides.d.ts +7 -0
- package/dist/overrides.js +4 -0
- package/dist/platform/ops/conversations.ops.js +1 -1
- package/dist/platform/ops/inbox.ops.js +4 -20
- package/dist/platform/ops/platform.ops.d.ts +1 -0
- package/dist/platform/ops/platform.ops.js +6 -3
- package/dist/roles/worker-role.d.ts +10 -5
- package/dist/roles/worker-role.js +19 -9
- package/dist/roles/worker.module.js +2 -4
- 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 +4 -0
- package/dist/runtime/loop.d.ts +8 -0
- package/dist/runtime/maintenance.d.ts +9 -4
- package/dist/runtime/maintenance.js +52 -13
- package/dist/runtime/model-call.d.ts +6 -1
- package/dist/runtime/model-call.js +1 -0
- package/dist/runtime/plugin-context.service.d.ts +75 -0
- package/dist/runtime/plugin-context.service.js +220 -0
- package/dist/runtime/run-context.service.d.ts +7 -3
- package/dist/runtime/run-context.service.js +12 -2
- package/dist/runtime/run-control.d.ts +6 -1
- package/dist/runtime/run-control.js +13 -0
- package/dist/runtime/run-finish.d.ts +2 -2
- package/dist/runtime/run-finish.js +11 -6
- package/dist/runtime/run-jobs.d.ts +21 -4
- package/dist/runtime/run-jobs.js +29 -6
- package/dist/runtime/run-orphan-check.job.d.ts +14 -11
- package/dist/runtime/run-orphan-check.job.js +16 -11
- package/dist/runtime/run-queue.d.ts +29 -24
- package/dist/runtime/run-queue.js +118 -57
- package/dist/runtime/run-status.d.ts +12 -0
- package/dist/runtime/run-status.js +21 -0
- package/dist/runtime/run-worker.d.ts +32 -3
- package/dist/runtime/run-worker.js +143 -21
- package/dist/runtime/runtime.module.js +2 -0
- package/dist/runtime/step-log.d.ts +6 -5
- package/dist/runtime/step-log.js +6 -5
- package/dist/runtime/subagents/dispatch.js +1 -0
- package/dist/runtime/subagents/skill-fork.js +3 -0
- package/dist/runtime/usage-report.d.ts +3 -1
- package/dist/runtime/usage-report.js +4 -2
- package/dist/runtime/waits.d.ts +16 -6
- package/dist/runtime/waits.js +37 -15
- package/dist/sandbox/jobs.d.ts +20 -10
- package/dist/sandbox/jobs.js +23 -17
- package/dist/schedules/fire.d.ts +25 -4
- package/dist/schedules/fire.js +87 -13
- package/dist/schedules/job-ids.d.ts +66 -17
- package/dist/schedules/job-ids.js +81 -13
- package/dist/schedules/run-tracker.js +2 -1
- package/dist/schedules/scan.job.d.ts +16 -35
- package/dist/schedules/scan.job.js +38 -147
- package/dist/schedules/scheduled-tasks.service.d.ts +6 -6
- package/dist/schedules/scheduled-tasks.service.js +17 -14
- package/dist/schedules/schedules.module.js +0 -4
- package/dist/skills/catalog.d.ts +7 -3
- package/dist/skills/catalog.js +12 -2
- package/dist/skills/changes.controller.d.ts +1 -1
- package/dist/skills/changes.controller.js +1 -1
- package/dist/tools/approvals.service.d.ts +111 -23
- package/dist/tools/approvals.service.js +326 -77
- package/dist/tools/builtins/sandbox/task-output.js +21 -6
- package/dist/tools/device-op-resolver.d.ts +40 -0
- package/dist/tools/device-op-resolver.js +121 -0
- package/dist/tools/network-asks.d.ts +1 -1
- package/dist/tools/network-asks.js +4 -3
- package/dist/tools/pipeline.d.ts +11 -2
- package/dist/tools/pipeline.js +5 -0
- package/dist/tools/questions.service.d.ts +15 -4
- package/dist/tools/questions.service.js +21 -19
- package/dist/tools/registry.d.ts +8 -1
- package/dist/tools/registry.js +9 -0
- package/dist/tools/tools.module.js +4 -0
- package/package.json +3 -3
- 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/src/migrations/0125_conversation_tree_stopped_at.sql +5 -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
|
@@ -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
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type AgentTemplate, type AgentTemplateTier, type LocalizedName, type PluginManifest, type ThemeScheme } from "@capybara-hq/plugin-sdk";
|
|
2
|
-
import type { Queue } from "bullmq";
|
|
3
2
|
import { ClientBuilds } from "../client/client-builds.service.js";
|
|
4
3
|
import { ApiError } from "../errors.js";
|
|
5
4
|
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
@@ -16,6 +15,7 @@ import { SuperAdminLock } from "../identity/super-admin.js";
|
|
|
16
15
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
17
16
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
18
17
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
18
|
+
import { OutboxService } from "../infra/outbox/outbox.service.js";
|
|
19
19
|
import type { KernelLogger } from "../log.js";
|
|
20
20
|
import { OrgLock } from "../orgs/org-lock.js";
|
|
21
21
|
import type { ProvenanceResult } from "../packages/provenance.js";
|
|
@@ -27,8 +27,6 @@ import { CatalogItemLock } from "./locks.js";
|
|
|
27
27
|
import { PlatformComponents } from "./platform-components.js";
|
|
28
28
|
import { PluginPackageError } from "./plugin-package.js";
|
|
29
29
|
import type { PluginScope } from "./scope.js";
|
|
30
|
-
/** How long after a failed post-import platform sync the migration job runs for the item. */
|
|
31
|
-
export declare const PLATFORM_SYNC_RETRY_MS = 60000;
|
|
32
30
|
/**
|
|
33
31
|
* Platform import of a plugin (package ecosystem spec §4.3): one review for every plugin, whatever
|
|
34
32
|
* it contains (an extension, skills, connector templates, dependencies), confirmed once.
|
|
@@ -54,8 +52,10 @@ export declare const PLATFORM_SYNC_RETRY_MS = 60000;
|
|
|
54
52
|
* snapshot when it is installed or upgraded by this import (source web, audit
|
|
55
53
|
* `extension.permissions_approved` carrying the plugin), and creates the item (with the scope the
|
|
56
54
|
* admin chose, default `optional`) or adds the version (`manifest` = the normalized plugin.json,
|
|
57
|
-
* `extension_sha256`, the files under the staging prefix)
|
|
58
|
-
*
|
|
55
|
+
* `extension_sha256`, the files under the staging prefix); an item's first usable version also
|
|
56
|
+
* gets its platform component rows there (their files copied before, keyed by content: a failure
|
|
57
|
+
* leaves nothing a retry copies again; no job heals an item later). After the commit the plugin's
|
|
58
|
+
* own extension is installed on the deployment and enabled (`ExtensionAdminOps.install` + `enable`;
|
|
59
59
|
* each replica reconciles, no restart); a failure is returned, not thrown, and an upgrade that was
|
|
60
60
|
* not installed gets its old snapshot back.
|
|
61
61
|
*
|
|
@@ -413,12 +413,14 @@ export declare class PluginImport {
|
|
|
413
413
|
private readonly registry;
|
|
414
414
|
private readonly log;
|
|
415
415
|
readonly txHost: TransactionHost;
|
|
416
|
-
/** The platform rows of a new item's components, written
|
|
416
|
+
/** The platform rows of a new item's components, written in the confirm's transaction. */
|
|
417
417
|
private readonly platform;
|
|
418
|
-
/** A failed platform sync enqueues a run of the migration job here (it heals the item). */
|
|
419
|
-
private readonly maintenance;
|
|
420
418
|
/** The client build of a dropped org upload's package is deleted with it. */
|
|
421
419
|
private readonly clientBuilds;
|
|
420
|
+
/** The scope sync's backstop, owed by the confirm's commit (ruling R24). */
|
|
421
|
+
private readonly outbox;
|
|
422
|
+
/** The backstop's delay (a test seam; default `SCOPE_BACKSTOP_DELAY_MS`). */
|
|
423
|
+
private readonly backstopDelayMs;
|
|
422
424
|
/** Where plugin files go (the kernel's object storage; the CLI's own, see {@link useCliStorage}). */
|
|
423
425
|
private files;
|
|
424
426
|
/**
|
|
@@ -436,12 +438,14 @@ export declare class PluginImport {
|
|
|
436
438
|
blobs: ExtensionBlobs,
|
|
437
439
|
/** Config-declared names, loaded connectors and extension versions (the extension registry). */
|
|
438
440
|
registry: ExtensionRegistry, log: KernelLogger, txHost: TransactionHost,
|
|
439
|
-
/** The platform rows of a new item's components, written
|
|
441
|
+
/** The platform rows of a new item's components, written in the confirm's transaction. */
|
|
440
442
|
platform: PlatformComponents,
|
|
441
|
-
/** A failed platform sync enqueues a run of the migration job here (it heals the item). */
|
|
442
|
-
maintenance: Pick<Queue, "add">,
|
|
443
443
|
/** The client build of a dropped org upload's package is deleted with it. */
|
|
444
|
-
clientBuilds: ClientBuilds
|
|
444
|
+
clientBuilds: ClientBuilds,
|
|
445
|
+
/** The scope sync's backstop, owed by the confirm's commit (ruling R24). */
|
|
446
|
+
outbox: Pick<OutboxService, "add">,
|
|
447
|
+
/** The backstop's delay (a test seam; default `SCOPE_BACKSTOP_DELAY_MS`). */
|
|
448
|
+
backstopDelayMs?: number);
|
|
445
449
|
/** The kernel-schema handle of the current context (the transaction, else the pool). */
|
|
446
450
|
private get db();
|
|
447
451
|
/**
|
|
@@ -587,11 +591,12 @@ export declare class PluginImport {
|
|
|
587
591
|
owner?: ImportOwner;
|
|
588
592
|
}): Promise<PluginConfirmResult>;
|
|
589
593
|
/**
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
594
|
+
* The platform components of the staged version when its confirm will most likely make it the
|
|
595
|
+
* item's first usable version ({@link commit} decides under its locks): no live item of the name
|
|
596
|
+
* yet, or an org upload replacing its own first upload still awaiting confirmation. Planned from
|
|
597
|
+
* the staged content and their files copied, outside any transaction; otherwise undefined.
|
|
593
598
|
*/
|
|
594
|
-
|
|
599
|
+
private prepareFirstVersion;
|
|
595
600
|
/**
|
|
596
601
|
* The confirm's transaction: the staging row consumed, the extension's action recomputed under
|
|
597
602
|
* its install lock (stale -> `plugin.review_stale`), its snapshot approved, and the catalog
|
|
@@ -605,17 +610,15 @@ export declare class PluginImport {
|
|
|
605
610
|
* upload without an extension for an item whose first version still waits (plan Task 6) replaces
|
|
606
611
|
* that upload and applies at once: the item stops waiting and the claim is released (nothing
|
|
607
612
|
* was installed under it).
|
|
613
|
+
*
|
|
614
|
+
* The item's first usable version (a new item not waiting, or an awaiting first upload replaced)
|
|
615
|
+
* writes the platform rows of its skills, agent templates, connector templates and themes
|
|
616
|
+
* (plugin scope phase 2) from `prepared` (their files copied before the transaction, keyed by
|
|
617
|
+
* content): a failure rolls the whole confirm back, and a retry copies nothing again. A plan made
|
|
618
|
+
* for another item or version, or a component changed since it -> `plugin.review_stale`. A new
|
|
619
|
+
* version of an existing item leaves them to the platform update.
|
|
608
620
|
*/
|
|
609
621
|
private commit;
|
|
610
|
-
/**
|
|
611
|
-
* The platform components of a new item. The item is committed already, so a failure is logged
|
|
612
|
-
* and not thrown (like a failed deploy, the import itself succeeded); a run of the platform
|
|
613
|
-
* components migration job (which writes what is missing) is enqueued on `cap-kernel-maintenance`
|
|
614
|
-
* after {@link PLATFORM_SYNC_RETRY_MS}, one per item (deterministic job id). If that run fails
|
|
615
|
-
* too, its `itemsFailed` shows in the super admin's inbox; the daily run and every worker start
|
|
616
|
-
* try again.
|
|
617
|
-
*/
|
|
618
|
-
private syncPlatform;
|
|
619
622
|
/**
|
|
620
623
|
* Writes the extension's permission snapshot for the version being imported (source web; cli
|
|
621
624
|
* without an actor; bootstrap for the bootstrap step), after
|