@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
|
@@ -10,6 +10,7 @@ import { ChannelsModule } from "../channels/channels.module.js";
|
|
|
10
10
|
import { TitlesModule } from "../conversations/titles.js";
|
|
11
11
|
import { EvalsModule } from "../evals/evals.module.js";
|
|
12
12
|
import { ExtensionsModule } from "../extensions/extensions.module.js";
|
|
13
|
+
import { LifecycleHooksModule } from "../extensions/lifecycle-hooks.js";
|
|
13
14
|
import { IdentityModule } from "../identity/identity.module.js";
|
|
14
15
|
import { InboxModule } from "../inbox/inbox.module.js";
|
|
15
16
|
import { ModelsModule } from "../models/models.module.js";
|
|
@@ -48,6 +49,7 @@ AdminModule = __decorate([
|
|
|
48
49
|
TitlesModule,
|
|
49
50
|
UsageReportModule,
|
|
50
51
|
EvalsModule,
|
|
52
|
+
LifecycleHooksModule,
|
|
51
53
|
// the price table of the usage aggregate
|
|
52
54
|
ModelsModule,
|
|
53
55
|
],
|
|
@@ -4,7 +4,7 @@ import { KernelDb } from "../infra/database/kernel-db.js";
|
|
|
4
4
|
import { type LiveReplica, ReplicaPresence } from "../infra/presence/replica-presence.js";
|
|
5
5
|
import type { KernelLogger } from "../log.js";
|
|
6
6
|
/** The kernel's own queues, in the order the overview lists them (extension queues are not read). */
|
|
7
|
-
export declare const KERNEL_QUEUE_NAMES: readonly ["cap-kernel-runs", "cap-kernel-subagent-runs", "cap-kernel-channels", "cap-kernel-maintenance", "cap-kernel-plugin-scope", "cap-kernel-titles", "cap-kernel-usage-report", "cap-kernel-evals"];
|
|
7
|
+
export declare const KERNEL_QUEUE_NAMES: readonly ["cap-kernel-runs", "cap-kernel-subagent-runs", "cap-kernel-channels", "cap-kernel-maintenance", "cap-kernel-plugin-scope", "cap-kernel-titles", "cap-kernel-usage-report", "cap-kernel-evals", "cap-kernel-lifecycle"];
|
|
8
8
|
/** How long each source's reads may take before the answer marks it unavailable. */
|
|
9
9
|
export declare const HEALTH_READ_TIMEOUT_MS = 3000;
|
|
10
10
|
/** A live replica as the overview shows it. */
|
|
@@ -97,7 +97,7 @@ export declare class AdminHealthService {
|
|
|
97
97
|
private readonly redis;
|
|
98
98
|
private readonly log;
|
|
99
99
|
private readonly queues;
|
|
100
|
-
constructor(presence: Pick<ReplicaPresence, "live">, db: KernelDb, redis: Pick<Redis, "zcount" | "status">, log: Pick<KernelLogger, "warn">, runs: Queue, subagentRuns: Queue, channels: Queue, maintenance: Queue, pluginScope: Queue, titles: Queue, usageReport: Queue, evals: Queue);
|
|
100
|
+
constructor(presence: Pick<ReplicaPresence, "live">, db: KernelDb, redis: Pick<Redis, "zcount" | "status">, log: Pick<KernelLogger, "warn">, runs: Queue, subagentRuns: Queue, channels: Queue, maintenance: Queue, pluginScope: Queue, titles: Queue, usageReport: Queue, evals: Queue, lifecycle: Queue);
|
|
101
101
|
read(): Promise<AdminHealth>;
|
|
102
102
|
private readRedis;
|
|
103
103
|
private readDb;
|
|
@@ -14,6 +14,7 @@ import { PLUGIN_SCOPE_QUEUE } from "../catalog/scope-sync.js";
|
|
|
14
14
|
import { CHANNEL_QUEUE_NAME } from "../channels/jobs.js";
|
|
15
15
|
import { TITLE_QUEUE } from "../conversations/titles.js";
|
|
16
16
|
import { EVAL_QUEUE_NAME } from "../evals/jobs.js";
|
|
17
|
+
import { LIFECYCLE_QUEUE } from "../extensions/lifecycle-hooks.js";
|
|
17
18
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
18
19
|
import { ReplicaPresence } from "../infra/presence/replica-presence.js";
|
|
19
20
|
import { KERNEL_LOGGER, REDIS } from "../infra/tokens.js";
|
|
@@ -31,6 +32,7 @@ export const KERNEL_QUEUE_NAMES = [
|
|
|
31
32
|
TITLE_QUEUE,
|
|
32
33
|
USAGE_REPORT_QUEUE,
|
|
33
34
|
EVAL_QUEUE_NAME,
|
|
35
|
+
LIFECYCLE_QUEUE,
|
|
34
36
|
];
|
|
35
37
|
/** How long each source's reads may take before the answer marks it unavailable. */
|
|
36
38
|
export const HEALTH_READ_TIMEOUT_MS = 3_000;
|
|
@@ -58,7 +60,7 @@ let AdminHealthService = class AdminHealthService {
|
|
|
58
60
|
redis;
|
|
59
61
|
log;
|
|
60
62
|
queues;
|
|
61
|
-
constructor(presence, db, redis, log, runs, subagentRuns, channels, maintenance, pluginScope, titles, usageReport, evals) {
|
|
63
|
+
constructor(presence, db, redis, log, runs, subagentRuns, channels, maintenance, pluginScope, titles, usageReport, evals, lifecycle) {
|
|
62
64
|
this.presence = presence;
|
|
63
65
|
this.db = db;
|
|
64
66
|
this.redis = redis;
|
|
@@ -73,6 +75,7 @@ let AdminHealthService = class AdminHealthService {
|
|
|
73
75
|
titles,
|
|
74
76
|
usageReport,
|
|
75
77
|
evals,
|
|
78
|
+
lifecycle,
|
|
76
79
|
];
|
|
77
80
|
}
|
|
78
81
|
async read() {
|
|
@@ -241,6 +244,7 @@ AdminHealthService = __decorate([
|
|
|
241
244
|
__param(8, Inject(getQueueToken(PLUGIN_SCOPE_QUEUE))),
|
|
242
245
|
__param(9, Inject(getQueueToken(TITLE_QUEUE))),
|
|
243
246
|
__param(10, Inject(getQueueToken(USAGE_REPORT_QUEUE))),
|
|
244
|
-
__param(11, Inject(getQueueToken(EVAL_QUEUE_NAME)))
|
|
247
|
+
__param(11, Inject(getQueueToken(EVAL_QUEUE_NAME))),
|
|
248
|
+
__param(12, Inject(getQueueToken(LIFECYCLE_QUEUE)))
|
|
245
249
|
], AdminHealthService);
|
|
246
250
|
export { AdminHealthService };
|
|
@@ -50,8 +50,9 @@ export declare class OutboxDeadService {
|
|
|
50
50
|
* the fast path after the commit; the relay delivers it otherwise. When the same (queue, job id)
|
|
51
51
|
* is owed by a pending row already, the dead row is deleted instead (`already_owed`). A pending
|
|
52
52
|
* row added between the check and the update fails the update on the unique index: the retry
|
|
53
|
-
* then runs once more and takes the `already_owed` branch
|
|
54
|
-
*
|
|
53
|
+
* then runs once more and takes the `already_owed` branch; a second conflict on that run (the
|
|
54
|
+
* job owed, delivered and owed again meanwhile) is `conflict` (409), the dead row left as it was.
|
|
55
|
+
* `outbox.not_found` (404) when no dead row has the id.
|
|
55
56
|
*/
|
|
56
57
|
retry(id: string, actor: WriteActor, detail?: Record<string, unknown>): Promise<{
|
|
57
58
|
outcome: OutboxRetryOutcome;
|
|
@@ -61,6 +62,9 @@ export declare class OutboxDeadService {
|
|
|
61
62
|
discard(id: string, actor: WriteActor, detail?: Record<string, unknown>): Promise<void>;
|
|
62
63
|
/** The dead row `id`, locked for the transaction; `outbox.not_found` when it is not dead. */
|
|
63
64
|
private lockDead;
|
|
64
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* A platform-level audit event (no org: the outbox is the deployment's), naming the job. The
|
|
67
|
+
* caller's detail (`via`, `operation`) comes first, so it cannot override the row's fields.
|
|
68
|
+
*/
|
|
65
69
|
private audit;
|
|
66
70
|
}
|
|
@@ -89,8 +89,9 @@ let OutboxDeadService = class OutboxDeadService {
|
|
|
89
89
|
* the fast path after the commit; the relay delivers it otherwise. When the same (queue, job id)
|
|
90
90
|
* is owed by a pending row already, the dead row is deleted instead (`already_owed`). A pending
|
|
91
91
|
* row added between the check and the update fails the update on the unique index: the retry
|
|
92
|
-
* then runs once more and takes the `already_owed` branch
|
|
93
|
-
*
|
|
92
|
+
* then runs once more and takes the `already_owed` branch; a second conflict on that run (the
|
|
93
|
+
* job owed, delivered and owed again meanwhile) is `conflict` (409), the dead row left as it was.
|
|
94
|
+
* `outbox.not_found` (404) when no dead row has the id.
|
|
94
95
|
*/
|
|
95
96
|
async retry(id, actor, detail = {}) {
|
|
96
97
|
try {
|
|
@@ -99,7 +100,14 @@ let OutboxDeadService = class OutboxDeadService {
|
|
|
99
100
|
catch (e) {
|
|
100
101
|
if (!isPendingConflict(e))
|
|
101
102
|
throw e;
|
|
102
|
-
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
return await this.retryOnce(id, actor, detail);
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
if (!isPendingConflict(e))
|
|
109
|
+
throw e;
|
|
110
|
+
throw new ApiError("conflict", `The job of dead outbox row ${id} was owed again while it was retried; list the dead rows with GET /api/v1/admin/outbox/dead and retry or discard it again`);
|
|
103
111
|
}
|
|
104
112
|
}
|
|
105
113
|
async retryOnce(id, actor, detail) {
|
|
@@ -125,7 +133,7 @@ let OutboxDeadService = class OutboxDeadService {
|
|
|
125
133
|
outcome = "retried";
|
|
126
134
|
afterCommit(() => this.fastPath([id]));
|
|
127
135
|
}
|
|
128
|
-
await this.audit("outbox.retried", id, row, actor, {
|
|
136
|
+
await this.audit("outbox.retried", id, row, actor, { ...detail, outcome });
|
|
129
137
|
return { outcome };
|
|
130
138
|
}
|
|
131
139
|
/** Deletes a dead row: its job is never delivered. `outbox.not_found` (404) when none. */
|
|
@@ -147,7 +155,10 @@ let OutboxDeadService = class OutboxDeadService {
|
|
|
147
155
|
throw notFound(id);
|
|
148
156
|
return row;
|
|
149
157
|
}
|
|
150
|
-
/**
|
|
158
|
+
/**
|
|
159
|
+
* A platform-level audit event (no org: the outbox is the deployment's), naming the job. The
|
|
160
|
+
* caller's detail (`via`, `operation`) comes first, so it cannot override the row's fields.
|
|
161
|
+
*/
|
|
151
162
|
audit(action, id, row, actor, detail) {
|
|
152
163
|
return audit(this.db.db, {
|
|
153
164
|
actorAccountId: actor.accountId,
|
|
@@ -155,11 +166,11 @@ let OutboxDeadService = class OutboxDeadService {
|
|
|
155
166
|
action,
|
|
156
167
|
target: id,
|
|
157
168
|
detail: {
|
|
169
|
+
...detail,
|
|
158
170
|
queue: row.queue,
|
|
159
171
|
jobName: row.job_name,
|
|
160
172
|
jobId: row.job_id,
|
|
161
173
|
...(row.org_id !== null && { orgId: row.org_id }),
|
|
162
|
-
...detail,
|
|
163
174
|
},
|
|
164
175
|
});
|
|
165
176
|
}
|
|
@@ -107,11 +107,11 @@ export declare function extensionReason(e: Pick<AdminExtensionView, "status" | "
|
|
|
107
107
|
/** The problem of a provider in the platform view, or null (`org_configured` is not one). */
|
|
108
108
|
export declare function providerProblem(p: ProviderStatus): AttentionProviderProblem | null;
|
|
109
109
|
/**
|
|
110
|
-
* The admin overview (spec §4.1, §5.2): its numbers and the 待处理 lists, read live from the
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* `unavailable`. Reads are not audited (decision D5) and not cached further
|
|
114
|
-
* or already Redis-cached).
|
|
110
|
+
* The admin overview (spec §4.1, §5.2): its numbers and the 待处理 lists, read live from the sources
|
|
111
|
+
* the admin pages read (`ExtensionAdmin`, the catalog, the provider registry's cached lists, the
|
|
112
|
+
* dead outbox rows, the run queue's lost-jobs canary). Each source is read on its own: a failing
|
|
113
|
+
* one is reported in `unavailable`. Reads are not audited (decision D5) and not cached further
|
|
114
|
+
* (every source is PG or already Redis-cached).
|
|
115
115
|
*/
|
|
116
116
|
export declare class AdminOverviewService {
|
|
117
117
|
private readonly extensions;
|
|
@@ -136,7 +136,7 @@ export declare class AdminOverviewService {
|
|
|
136
136
|
/**
|
|
137
137
|
* The extensions needing a look, but not one pending approval whose plugin waits in the platform
|
|
138
138
|
* inbox (a permission confirmation or an org upload: the inbox already lists and counts it). A
|
|
139
|
-
* config-declared extension has no catalog item and stays. Without the catalog
|
|
139
|
+
* config-declared extension has no catalog item and stays. Without the catalog none is left out.
|
|
140
140
|
*/
|
|
141
141
|
private extensionRows;
|
|
142
142
|
/** Every live catalog item, page by page (the catalog lists by name). */
|
|
@@ -53,11 +53,11 @@ export function providerProblem(p) {
|
|
|
53
53
|
return p.models.some((m) => m.kind === "chat" && m.disabled !== true) ? null : "no_chat_model";
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* The admin overview (spec §4.1, §5.2): its numbers and the 待处理 lists, read live from the
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* `unavailable`. Reads are not audited (decision D5) and not cached further
|
|
60
|
-
* or already Redis-cached).
|
|
56
|
+
* The admin overview (spec §4.1, §5.2): its numbers and the 待处理 lists, read live from the sources
|
|
57
|
+
* the admin pages read (`ExtensionAdmin`, the catalog, the provider registry's cached lists, the
|
|
58
|
+
* dead outbox rows, the run queue's lost-jobs canary). Each source is read on its own: a failing
|
|
59
|
+
* one is reported in `unavailable`. Reads are not audited (decision D5) and not cached further
|
|
60
|
+
* (every source is PG or already Redis-cached).
|
|
61
61
|
*/
|
|
62
62
|
let AdminOverviewService = class AdminOverviewService {
|
|
63
63
|
extensions;
|
|
@@ -164,13 +164,13 @@ let AdminOverviewService = class AdminOverviewService {
|
|
|
164
164
|
/**
|
|
165
165
|
* The extensions needing a look, but not one pending approval whose plugin waits in the platform
|
|
166
166
|
* inbox (a permission confirmation or an org upload: the inbox already lists and counts it). A
|
|
167
|
-
* config-declared extension has no catalog item and stays. Without the catalog
|
|
167
|
+
* config-declared extension has no catalog item and stays. Without the catalog none is left out.
|
|
168
168
|
*/
|
|
169
169
|
async extensionRows(items) {
|
|
170
170
|
const [views, catalog] = await Promise.all([this.extensions.list(), items.catch(() => [])]);
|
|
171
171
|
const inInbox = new Set(catalog.filter((i) => i.pending).map((i) => i.name));
|
|
172
172
|
return views.flatMap((v) => {
|
|
173
|
-
// every status of extensionNeedsAction has a reason,
|
|
173
|
+
// every status of extensionNeedsAction has a reason, as has enabled with an invalid config
|
|
174
174
|
const reason = extensionReason(v);
|
|
175
175
|
if (reason === null)
|
|
176
176
|
return [];
|
|
@@ -8,6 +8,7 @@ import { Module } from "@nestjs/common";
|
|
|
8
8
|
import { AttachmentsModule } from "../conversations/attachments.module.js";
|
|
9
9
|
import { EvalBudgetModule } from "../evals/budget.js";
|
|
10
10
|
import { ExtensionsModule } from "../extensions/extensions.module.js";
|
|
11
|
+
import { LifecycleHooksModule } from "../extensions/lifecycle-hooks.js";
|
|
11
12
|
import { ModelsModule } from "../models/models.module.js";
|
|
12
13
|
import { OrgLockModule } from "../orgs/org-lock.js";
|
|
13
14
|
import { ProvidersModule } from "../runtime/providers.js";
|
|
@@ -48,6 +49,8 @@ AgentsModule = __decorate([
|
|
|
48
49
|
// creating from a template: the extension tools and the tier purposes (rulings P4-4, P4-5)
|
|
49
50
|
ExtensionsModule,
|
|
50
51
|
ModelsModule,
|
|
52
|
+
// the agent delete records `agent.deleted` deliveries
|
|
53
|
+
LifecycleHooksModule,
|
|
51
54
|
],
|
|
52
55
|
providers: [
|
|
53
56
|
AgentsService,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
2
2
|
import { EvalBudget } from "../evals/budget.js";
|
|
3
|
+
import { LifecycleHooks } from "../extensions/lifecycle-hooks.js";
|
|
3
4
|
import type { WriteActor } from "../identity/write-actor.js";
|
|
4
5
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
5
6
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -92,6 +93,8 @@ export declare class AgentsService {
|
|
|
92
93
|
private readonly evalBudget;
|
|
93
94
|
/** Settles the agent's connector setup request when its pending connectors change (P4-7). */
|
|
94
95
|
private readonly setupRequests;
|
|
96
|
+
/** Records `agent.deleted` for the subscribing plugins in the delete's transaction. */
|
|
97
|
+
private readonly lifecycle;
|
|
95
98
|
constructor(db: KernelDb, lookup: AgentLookup, tools: Pick<ToolRegistry, "checkDisabled">,
|
|
96
99
|
/**
|
|
97
100
|
* Cancels the agent's pending skill requests: all of them when it is deleted, share requests
|
|
@@ -105,7 +108,9 @@ export declare class AgentsService {
|
|
|
105
108
|
/** Cancels the deleted agent's running eval runs (in the delete's transaction). */
|
|
106
109
|
evalBudget: Pick<EvalBudget, "cancelRuns">,
|
|
107
110
|
/** Settles the agent's connector setup request when its pending connectors change (P4-7). */
|
|
108
|
-
setupRequests: Pick<PendingConnectorRequests, "settleIn" | "retargetIn"
|
|
111
|
+
setupRequests: Pick<PendingConnectorRequests, "settleIn" | "retargetIn">,
|
|
112
|
+
/** Records `agent.deleted` for the subscribing plugins in the delete's transaction. */
|
|
113
|
+
lifecycle: Pick<LifecycleHooks, "recordIn">);
|
|
109
114
|
/**
|
|
110
115
|
* Checks the turned-off tools and the policies (tools default-on spec §2): `disabledTools` must
|
|
111
116
|
* name existing builtins, extensions and connectors (`ToolRegistry.checkDisabled`); `toolPolicies`
|
|
@@ -13,7 +13,9 @@ import { Inject, Injectable } from "@nestjs/common";
|
|
|
13
13
|
import { sql } from "kysely";
|
|
14
14
|
import { ApiError } from "../errors.js";
|
|
15
15
|
import { EvalBudget } from "../evals/budget.js";
|
|
16
|
+
import { LifecycleHooks } from "../extensions/lifecycle-hooks.js";
|
|
16
17
|
import { audit } from "../identity/audit.js";
|
|
18
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
17
19
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
18
20
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
19
21
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
@@ -279,6 +281,7 @@ let AgentsService = class AgentsService {
|
|
|
279
281
|
txHost;
|
|
280
282
|
evalBudget;
|
|
281
283
|
setupRequests;
|
|
284
|
+
lifecycle;
|
|
282
285
|
constructor(db, lookup, tools,
|
|
283
286
|
/**
|
|
284
287
|
* Cancels the agent's pending skill requests: all of them when it is deleted, share requests
|
|
@@ -292,7 +295,9 @@ let AgentsService = class AgentsService {
|
|
|
292
295
|
/** Cancels the deleted agent's running eval runs (in the delete's transaction). */
|
|
293
296
|
evalBudget,
|
|
294
297
|
/** Settles the agent's connector setup request when its pending connectors change (P4-7). */
|
|
295
|
-
setupRequests
|
|
298
|
+
setupRequests,
|
|
299
|
+
/** Records `agent.deleted` for the subscribing plugins in the delete's transaction. */
|
|
300
|
+
lifecycle) {
|
|
296
301
|
this.db = db;
|
|
297
302
|
this.lookup = lookup;
|
|
298
303
|
this.tools = tools;
|
|
@@ -302,6 +307,7 @@ let AgentsService = class AgentsService {
|
|
|
302
307
|
this.txHost = txHost;
|
|
303
308
|
this.evalBudget = evalBudget;
|
|
304
309
|
this.setupRequests = setupRequests;
|
|
310
|
+
this.lifecycle = lifecycle;
|
|
305
311
|
}
|
|
306
312
|
/**
|
|
307
313
|
* Checks the turned-off tools and the policies (tools default-on spec §2): `disabledTools` must
|
|
@@ -746,6 +752,8 @@ let AgentsService = class AgentsService {
|
|
|
746
752
|
});
|
|
747
753
|
// 评测集的 agent 删除后其评测运行不再花钱:显式取消(审计带原因)
|
|
748
754
|
await this.evalBudget.cancelRuns({ orgId, agentId }, { accountId: actorAccountId, ...(actorTokenId !== undefined && { tokenId: actorTokenId }) }, "agent_deleted");
|
|
755
|
+
// plugins learn of the delete durably: owed here, delivered by the outbox after the commit
|
|
756
|
+
await this.lifecycle.recordIn("agent.deleted", { orgId, agentId });
|
|
749
757
|
// joins this transaction (mandatory: it relies on the agent row lock taken above)
|
|
750
758
|
return this.skillChanges.cancelPendingForAgent(orgId, agentId, actorAccountId, "agent_deleted", actorTokenId);
|
|
751
759
|
}
|
|
@@ -907,6 +915,7 @@ AgentsService = __decorate([
|
|
|
907
915
|
__param(5, Inject(ProviderRegistry)),
|
|
908
916
|
__param(6, Inject(TransactionHost)),
|
|
909
917
|
__param(7, Inject(EvalBudget)),
|
|
910
|
-
__param(8, Inject(PendingConnectorRequests))
|
|
918
|
+
__param(8, Inject(PendingConnectorRequests)),
|
|
919
|
+
__param(9, Inject(LifecycleHooks))
|
|
911
920
|
], AgentsService);
|
|
912
921
|
export { AgentsService };
|
|
@@ -54,6 +54,11 @@ export type WakeDecision = {
|
|
|
54
54
|
* - the wake setting is on (the org's override, else `deploymentOn`);
|
|
55
55
|
* - the root's queue is not paused and the root is not deleted (a paused root holds the wakes of
|
|
56
56
|
* the whole tree, agent map spec §5.3);
|
|
57
|
+
* - for a `subagent_delivery` to the root: the root's tree is not stopped (`tree_stopped_at`, set by
|
|
58
|
+
* a person's stop of the root and cleared by the root's next run; agent map spec §6, changed in
|
|
59
|
+
* acceptance 2026-11-13): no sub-agent's finish or report, whenever its child finished, wakes a
|
|
60
|
+
* root a person stopped, the delivery waits for the next run. A sub-agent of a stopped tree is
|
|
61
|
+
* never woken here (`RunQueue.childWakeIn` refuses it first);
|
|
57
62
|
* - the event's trigger account can still send to the root (`canSend`, which the caller binds to
|
|
58
63
|
* the root);
|
|
59
64
|
* - no other wake of this conversation started in the last {@link WAKE_WINDOW_MS} (else `later`).
|
|
@@ -38,6 +38,11 @@ const WAKE_EVENT_TYPES = ["background_task_finished", "subagent_delivery"];
|
|
|
38
38
|
* - the wake setting is on (the org's override, else `deploymentOn`);
|
|
39
39
|
* - the root's queue is not paused and the root is not deleted (a paused root holds the wakes of
|
|
40
40
|
* the whole tree, agent map spec §5.3);
|
|
41
|
+
* - for a `subagent_delivery` to the root: the root's tree is not stopped (`tree_stopped_at`, set by
|
|
42
|
+
* a person's stop of the root and cleared by the root's next run; agent map spec §6, changed in
|
|
43
|
+
* acceptance 2026-11-13): no sub-agent's finish or report, whenever its child finished, wakes a
|
|
44
|
+
* root a person stopped, the delivery waits for the next run. A sub-agent of a stopped tree is
|
|
45
|
+
* never woken here (`RunQueue.childWakeIn` refuses it first);
|
|
41
46
|
* - the event's trigger account can still send to the root (`canSend`, which the caller binds to
|
|
42
47
|
* the root);
|
|
43
48
|
* - no other wake of this conversation started in the last {@link WAKE_WINDOW_MS} (else `later`).
|
|
@@ -68,21 +73,27 @@ export async function wakeDecisionIn(t, conv, consumed, deploymentOn, canSend) {
|
|
|
68
73
|
.orderBy("e.seq", "desc")
|
|
69
74
|
.limit(CANDIDATES)
|
|
70
75
|
.execute();
|
|
71
|
-
|
|
72
|
-
.sort((a, b) => Number(b.seq) - Number(a.seq))
|
|
73
|
-
.slice(0, CANDIDATES);
|
|
74
|
-
if (candidates.length === 0)
|
|
76
|
+
if (finishes.length === 0 && deliveries.length === 0)
|
|
75
77
|
return null;
|
|
76
78
|
const org = (await readOrgSettings(t, conv.orgId)).wakeOnBackgroundTask;
|
|
77
79
|
if (!effectiveWakeOnBackgroundTask(deploymentOn, org))
|
|
78
80
|
return null;
|
|
81
|
+
// read under the root's row lock when `conv` is the root (`RunQueue.ensureRunIn` holds it), so a
|
|
82
|
+
// person's stop of the tree (which writes `tree_stopped_at` on that row) is seen by every wake
|
|
83
|
+
// decided after its commit
|
|
79
84
|
const root = await t
|
|
80
85
|
.selectFrom("conversations")
|
|
81
|
-
.select(["queue_paused", "deleted_at"])
|
|
86
|
+
.select(["queue_paused", "deleted_at", "tree_stopped_at"])
|
|
82
87
|
.where("id", "=", conv.rootId)
|
|
83
88
|
.executeTakeFirst();
|
|
84
89
|
if (!root || root.queue_paused || root.deleted_at !== null)
|
|
85
90
|
return null;
|
|
91
|
+
const treeStopped = root.tree_stopped_at !== null;
|
|
92
|
+
const candidates = [...finishes, ...(treeStopped ? [] : deliveries)]
|
|
93
|
+
.sort((a, b) => Number(b.seq) - Number(a.seq))
|
|
94
|
+
.slice(0, CANDIDATES);
|
|
95
|
+
if (candidates.length === 0)
|
|
96
|
+
return null;
|
|
86
97
|
let boundary;
|
|
87
98
|
for (const c of candidates) {
|
|
88
99
|
if (await canSend(c.account)) {
|
|
@@ -8,9 +8,7 @@ import { Module } from "@nestjs/common";
|
|
|
8
8
|
import { ClientModule } from "../client/client.module.js";
|
|
9
9
|
import { ExtensionsModule } from "../extensions/extensions.module.js";
|
|
10
10
|
import { SuperAdminLockModule } from "../identity/super-admin.js";
|
|
11
|
-
import { QueueModule } from "../infra/queue/queue.module.js";
|
|
12
11
|
import { OrgLockModule } from "../orgs/org-lock.js";
|
|
13
|
-
import { MAINTENANCE_QUEUE_NAME } from "../runtime/maintenance-queue.js";
|
|
14
12
|
import { StorageModule } from "../storage/storage.module.js";
|
|
15
13
|
import { CatalogService } from "./catalog.service.js";
|
|
16
14
|
import { ComponentPromotion } from "./component-promotion.js";
|
|
@@ -37,8 +35,6 @@ CatalogImportModule = __decorate([
|
|
|
37
35
|
StorageModule,
|
|
38
36
|
// the client build prefix goes with an expired org upload's package (`PluginImport`)
|
|
39
37
|
ClientModule,
|
|
40
|
-
// a failed post-import platform sync enqueues the migration job (`PluginImport.syncPlatform`)
|
|
41
|
-
QueueModule.registerQueue(MAINTENANCE_QUEUE_NAME),
|
|
42
38
|
],
|
|
43
39
|
providers: [
|
|
44
40
|
CatalogSourceLock,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Queue } from "bullmq";
|
|
2
1
|
import { ApiError } from "../errors.js";
|
|
3
2
|
import { ExtensionAdminOps } from "../extensions/admin-ops.js";
|
|
4
3
|
import { ExtensionAdmin } from "../extensions/admin-view.js";
|
|
@@ -7,11 +6,14 @@ import { PluginInstallLock } from "../extensions/locks.js";
|
|
|
7
6
|
import { SuperAdminLock } from "../identity/super-admin.js";
|
|
8
7
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
9
8
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
9
|
+
import { OutboxService } from "../infra/outbox/outbox.service.js";
|
|
10
10
|
import type { KernelLogger } from "../log.js";
|
|
11
11
|
import { OrgLock } from "../orgs/org-lock.js";
|
|
12
12
|
import { type ThemePreview } from "../themes/theme-usage.js";
|
|
13
13
|
import { type ActorOpts, type CatalogItemView, CatalogService } from "./catalog.service.js";
|
|
14
14
|
import { type ComponentKind } from "./component-state.js";
|
|
15
|
+
import { CatalogItemLock } from "./locks.js";
|
|
16
|
+
import { PlatformComponents } from "./platform-components.js";
|
|
15
17
|
import { type PluginConfirmResult, PluginImport } from "./plugin-import.js";
|
|
16
18
|
import { PluginInstaller } from "./plugin-install.js";
|
|
17
19
|
import { PlatformPluginUpdater } from "./plugin-upgrade.js";
|
|
@@ -85,10 +87,10 @@ export type ScopeTarget = {
|
|
|
85
87
|
export declare function conflictsError(conflicts: ScopePreview["conflicts"]): ApiError;
|
|
86
88
|
/**
|
|
87
89
|
* The super admin's plugin scope and deployment-level disable (plugin and component management
|
|
88
|
-
* spec §4.1, §5 rules 2-4 and 8), and the import confirm that
|
|
90
|
+
* spec §4.1, §5 rules 2-4 and 8), and the import confirm that owes the scope sync of the item it
|
|
89
91
|
* wrote. A change is previewed, then confirmed with the preview's `scopeHash`, recomputed under the
|
|
90
92
|
* item row lock (a difference -> 409 `plugin.scope_stale`); it bumps `scope_version`, audits
|
|
91
|
-
* `catalog.scope_changed` and
|
|
93
|
+
* `catalog.scope_changed` and owes the item's scope sync in the same transaction, which installs or
|
|
92
94
|
* uninstalls in every org. Disabling keeps the scope, its org list and the org switches, so
|
|
93
95
|
* re-enabling (no hash needed) reinstalls where it was on. Builtin items -> 409 `plugin.builtin`.
|
|
94
96
|
* Stateless, shared by every replica.
|
|
@@ -98,6 +100,10 @@ export declare class CatalogScopeService {
|
|
|
98
100
|
private readonly adminLock;
|
|
99
101
|
private readonly catalog;
|
|
100
102
|
private readonly pluginImport;
|
|
103
|
+
/** A confirmed first version's platform components (written in the confirming commit). */
|
|
104
|
+
private readonly platform;
|
|
105
|
+
/** The import's item name lock, taken by the confirming commit before the item row. */
|
|
106
|
+
private readonly itemLock;
|
|
101
107
|
private readonly installer;
|
|
102
108
|
private readonly extensions;
|
|
103
109
|
private readonly ops;
|
|
@@ -109,23 +115,27 @@ export declare class CatalogScopeService {
|
|
|
109
115
|
private readonly installLock;
|
|
110
116
|
/** This replica's reconcile once a confirmed extension is enabled (before the scope sync). */
|
|
111
117
|
private readonly lifecycle;
|
|
112
|
-
/**
|
|
113
|
-
private readonly
|
|
118
|
+
/** Owes the scope syncs and the removed org plugin's cleanup (P3-21, pre-flight F9). */
|
|
119
|
+
private readonly outbox;
|
|
114
120
|
private readonly log;
|
|
115
121
|
readonly txHost: TransactionHost;
|
|
116
|
-
constructor(kdb: KernelDb, adminLock: SuperAdminLock, catalog: CatalogService, pluginImport: PluginImport,
|
|
122
|
+
constructor(kdb: KernelDb, adminLock: SuperAdminLock, catalog: CatalogService, pluginImport: PluginImport,
|
|
123
|
+
/** A confirmed first version's platform components (written in the confirming commit). */
|
|
124
|
+
platform: PlatformComponents,
|
|
125
|
+
/** The import's item name lock, taken by the confirming commit before the item row. */
|
|
126
|
+
itemLock: CatalogItemLock, installer: PluginInstaller, extensions: ExtensionAdmin, ops: ExtensionAdminOps, sync: PluginScopeSync, updater: PlatformPluginUpdater,
|
|
117
127
|
/** The owner org's lock: an org admin withdrawing its pending upload (ruling P3-10). */
|
|
118
128
|
orgLock: OrgLock,
|
|
119
129
|
/** The per-name install lock a reject / withdraw releases the name claim under (M1). */
|
|
120
130
|
installLock: PluginInstallLock,
|
|
121
131
|
/** This replica's reconcile once a confirmed extension is enabled (before the scope sync). */
|
|
122
132
|
lifecycle: ExtensionLifecycle,
|
|
123
|
-
/**
|
|
124
|
-
|
|
133
|
+
/** Owes the scope syncs and the removed org plugin's cleanup (P3-21, pre-flight F9). */
|
|
134
|
+
outbox: Pick<OutboxService, "add">, log: KernelLogger, txHost: TransactionHost);
|
|
125
135
|
private get db();
|
|
126
136
|
/**
|
|
127
137
|
* Confirms a staged import ({@link PluginImport.confirm}: installs and enables the extension,
|
|
128
|
-
* writes the new item's scope), then
|
|
138
|
+
* writes the new item's scope), then owes the item's scope sync when its scope turns it on
|
|
129
139
|
* by itself (`all` or `named`; an `optional` item is on only where an org admin switches it on).
|
|
130
140
|
*/
|
|
131
141
|
confirmImport(actor: string, stagingId: string, input: Parameters<PluginImport["confirm"]>[2], opts?: ActorOpts): Promise<PluginConfirmResult>;
|
|
@@ -148,9 +158,10 @@ export declare class CatalogScopeService {
|
|
|
148
158
|
* pending version (withdrawn, rejected, replaced by one without an extension) -> 409
|
|
149
159
|
* `extension.not_pending`.
|
|
150
160
|
*
|
|
151
|
-
* A first version: its
|
|
152
|
-
*
|
|
153
|
-
*
|
|
161
|
+
* A first version: its platform components planned and their files copied (keyed by content),
|
|
162
|
+
* its extension installed, its permissions approved, enabled, then (one transaction) the item
|
|
163
|
+
* stops waiting, its platform component rows are written and the owner is told
|
|
164
|
+
* (`upload_confirmed`); after the commit the scope sync is owed. Each step re-reads
|
|
154
165
|
* the item under its row lock: removed meanwhile -> 409 `catalog.item_removed`, the pending
|
|
155
166
|
* version replaced -> `extension.approval_stale`; the extension this confirmation installed is
|
|
156
167
|
* then taken out again. A new version: the platform update to it
|
|
@@ -160,8 +171,8 @@ export declare class CatalogScopeService {
|
|
|
160
171
|
*/
|
|
161
172
|
private confirmOrgUpload;
|
|
162
173
|
/**
|
|
163
|
-
* {@link confirmOrgUpload} under the item lock; returns the confirmed first version (its
|
|
164
|
-
*
|
|
174
|
+
* {@link confirmOrgUpload} under the item lock; returns the confirmed first version (its scope
|
|
175
|
+
* sync follows after), null for a new version.
|
|
165
176
|
*/
|
|
166
177
|
private confirmLocked;
|
|
167
178
|
/** The item is live and its first version confirmed (no longer awaiting). */
|
|
@@ -186,18 +197,33 @@ export declare class CatalogScopeService {
|
|
|
186
197
|
/**
|
|
187
198
|
* An extension a confirmation installed whose item was removed or replaced meanwhile is taken
|
|
188
199
|
* out again (disabled, uninstalled; P3-21), and the name claim released when the item is gone
|
|
189
|
-
* (ruling P3-37)
|
|
190
|
-
* (`owned-plugin-cleanup-<itemId>`, idempotent) is
|
|
191
|
-
*
|
|
200
|
+
* (ruling P3-37), in one transaction ({@link takeOutIn}). Inline (a failure is logged): when the
|
|
201
|
+
* take-out fails, a removed item's cleanup job (`owned-plugin-cleanup-<itemId>`, idempotent) is
|
|
202
|
+
* owed instead, so the job retries it (pre-flight F9). That owe is the last resort: when it
|
|
203
|
+
* fails too (PG unavailable) nothing retries the take-out, and it is logged as an error.
|
|
192
204
|
*/
|
|
193
205
|
private takeOut;
|
|
194
|
-
/**
|
|
195
|
-
|
|
206
|
+
/**
|
|
207
|
+
* {@link takeOut}'s transaction, in the global lock order (ruling P3-50): the super admin lock,
|
|
208
|
+
* the item row, then the extension's install lock (taken by the disable): disabled,
|
|
209
|
+
* uninstalled, and the name claim released when the item is gone.
|
|
210
|
+
*/
|
|
211
|
+
private takeOutIn;
|
|
212
|
+
/**
|
|
213
|
+
* Owes the cleanup of a removed item; a live item owes nothing (a removal committing later owes
|
|
214
|
+
* its own).
|
|
215
|
+
*/
|
|
216
|
+
private oweCleanupIfGone;
|
|
196
217
|
/** The item is still live and pending with `version` (row lock), else 409 (P3-21). */
|
|
197
218
|
private stillPending;
|
|
198
219
|
/** {@link stillPending} in the caller's transaction; returns the owner org. */
|
|
199
220
|
private pendingRow;
|
|
200
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* A confirmed first version: the item stops waiting, its platform component rows are written
|
|
223
|
+
* from `components` (a component changed since they were planned -> 409
|
|
224
|
+
* `extension.approval_stale`: confirm again), the owner is told (`upload_confirmed`). The
|
|
225
|
+
* import's item name lock before the item row, as an import's commit takes them (ruling P3-50).
|
|
226
|
+
*/
|
|
201
227
|
private finishFirstVersion;
|
|
202
228
|
/**
|
|
203
229
|
* The super admin rejects an org upload's pending version (ruling P3-10, `reason` shown to the
|
|
@@ -238,8 +264,8 @@ export declare class CatalogScopeService {
|
|
|
238
264
|
/**
|
|
239
265
|
* Writes an org-owned plugin's 可共享 flag and copies it to its component rows (ruling P3-2).
|
|
240
266
|
* Turning it off narrows an `optional` / `all` plugin, and each component with its own such
|
|
241
|
-
* scope, to the owner plus the orgs where it is on now (ruling P3-25), and
|
|
242
|
-
* scope sync
|
|
267
|
+
* scope, to the owner plus the orgs where it is on now (ruling P3-25), and owes the item's
|
|
268
|
+
* scope sync with it. The caller authorizes (the owner org's admin, Task 7). A platform
|
|
243
269
|
* item (no owner) or a missing one -> 404.
|
|
244
270
|
*/
|
|
245
271
|
setShareable(itemId: string, shareable: boolean, actor?: string | null): Promise<void>;
|
|
@@ -247,19 +273,30 @@ export declare class CatalogScopeService {
|
|
|
247
273
|
* Adds one org to a `named` item's list in the caller's transaction (an approved `access`
|
|
248
274
|
* request, spec §5.1 rule 2): nobody loses access, so no preview. The item row is locked; it
|
|
249
275
|
* must be live and not builtin (404 / `plugin.builtin`). Bumps `scope_version`, audits
|
|
250
|
-
* `catalog.scope_changed` and
|
|
276
|
+
* `catalog.scope_changed` and owes the item's scope sync in that transaction. Returns whether
|
|
251
277
|
* the list changed (false: not `named`, or listed already).
|
|
252
278
|
*/
|
|
253
279
|
addOrg(actor: string, itemId: string, orgId: string, opts?: ActorOpts & {
|
|
254
280
|
requestId?: string;
|
|
255
281
|
}): Promise<boolean>;
|
|
256
282
|
/**
|
|
257
|
-
*
|
|
258
|
-
* `OrgPluginUploads`)
|
|
283
|
+
* Owes the item's scope sync in the caller's transaction (an ownership transfer, an org upload's
|
|
284
|
+
* confirm in `OrgPluginUploads`).
|
|
259
285
|
*/
|
|
260
286
|
enqueueSync(itemId: string): Promise<void>;
|
|
261
|
-
/**
|
|
287
|
+
/** Owes the item's scope sync in the transaction that changes its scope (outbox spec §8.1). */
|
|
262
288
|
private enqueue;
|
|
289
|
+
/**
|
|
290
|
+
* Owes the item's scope sync in a transaction of its own, after a confirmation whose last write
|
|
291
|
+
* (the extension's deploy, or the platform components) committed outside the scope service: the
|
|
292
|
+
* sync must not run before the extension it installs is enabled.
|
|
293
|
+
*/
|
|
294
|
+
private oweSync;
|
|
295
|
+
/**
|
|
296
|
+
* Owes the delayed backstop of the item's sync in a transaction of its own (ruling R24): a
|
|
297
|
+
* permissions confirm writes nothing of the scope service's before its enable.
|
|
298
|
+
*/
|
|
299
|
+
private oweBackstop;
|
|
263
300
|
/**
|
|
264
301
|
* 409 `theme.platform_default` when a live theme of the item is the platform default and `after`
|
|
265
302
|
* says the change leaves it narrower than `all` or gone (themes spec §7). In the caller's
|