@capybara-hq/kernel 0.1.0-rc.20 → 0.1.0-rc.22
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 +10 -1
- package/dist/agents/admin-agents.d.ts +16 -3
- package/dist/agents/admin-agents.js +65 -7
- package/dist/agents/agents.schemas.d.ts +24 -6
- package/dist/agents/agents.service.d.ts +4 -3
- package/dist/agents/agents.service.js +39 -26
- package/dist/agents/definition.d.ts +44 -6
- package/dist/agents/definition.js +86 -18
- package/dist/agents/from-template.d.ts +6 -3
- package/dist/agents/from-template.js +57 -44
- package/dist/agents/org-templates.js +97 -41
- package/dist/agents/templates.d.ts +6 -0
- package/dist/agents/templates.js +15 -1
- package/dist/catalog/admin-catalog.controller.d.ts +2 -4
- package/dist/catalog/admin-catalog.controller.js +2 -6
- package/dist/catalog/catalog.module.js +3 -0
- package/dist/catalog/claude/report.d.ts +9 -2
- package/dist/catalog/claude/report.js +1 -0
- package/dist/catalog/claude/translate.js +1 -1
- package/dist/catalog/component-promotion.js +1 -2
- package/dist/catalog/component-state.d.ts +13 -1
- package/dist/catalog/component-state.js +14 -5
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/marketplaces.service.js +2 -1
- package/dist/catalog/org-catalog.controller.d.ts +13 -3
- package/dist/catalog/org-catalog.controller.js +26 -4
- package/dist/catalog/org-catalog.schemas.d.ts +13 -0
- package/dist/catalog/org-catalog.schemas.js +34 -0
- package/dist/catalog/org-plugin-uploads.controller.js +0 -1
- package/dist/catalog/org-plugin-uploads.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.js +0 -3
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.schemas.js +0 -2
- package/dist/catalog/platform-components.d.ts +0 -1
- package/dist/catalog/platform-components.js +3 -8
- package/dist/catalog/plugin-import.d.ts +0 -8
- package/dist/catalog/plugin-import.js +4 -35
- package/dist/catalog/plugin-install.d.ts +2 -2
- package/dist/catalog/plugin-install.js +2 -2
- package/dist/catalog/plugin-package.d.ts +7 -0
- package/dist/catalog/plugin-package.js +27 -1
- package/dist/catalog/plugin-upgrade.d.ts +5 -6
- package/dist/catalog/plugin-upgrade.js +5 -23
- package/dist/catalog/requests.service.d.ts +66 -10
- package/dist/catalog/requests.service.js +196 -15
- package/dist/channels/actions.d.ts +2 -0
- package/dist/channels/actions.js +19 -4
- package/dist/channels/cards.d.ts +16 -2
- package/dist/channels/cards.js +40 -7
- package/dist/channels/channels.module.js +3 -0
- package/dist/channels/outbound.d.ts +22 -1
- package/dist/channels/outbound.js +116 -7
- package/dist/channels/phrases.d.ts +25 -0
- package/dist/channels/phrases.js +19 -0
- package/dist/channels/threads.d.ts +12 -0
- package/dist/channels/threads.js +34 -0
- package/dist/config/schema.d.ts +23 -1
- package/dist/config/schema.js +105 -5
- package/dist/conversations/conversations.service.d.ts +42 -9
- package/dist/conversations/conversations.service.js +57 -25
- package/dist/conversations/events.d.ts +106 -11
- package/dist/conversations/events.js +121 -18
- package/dist/conversations/message-context.d.ts +6 -3
- package/dist/conversations/message-context.js +14 -10
- package/dist/conversations/queue.d.ts +15 -2
- package/dist/conversations/queue.js +22 -3
- package/dist/conversations/queue.service.d.ts +12 -6
- package/dist/conversations/queue.service.js +36 -13
- package/dist/db/kernel-schema.d.ts +105 -3
- package/dist/devices/conversation-devices.d.ts +8 -1
- package/dist/devices/conversation-devices.js +8 -0
- package/dist/devices/devices.controller.d.ts +21 -4
- package/dist/devices/devices.controller.js +46 -8
- package/dist/devices/devices.schemas.d.ts +9 -1
- package/dist/devices/devices.schemas.js +11 -3
- package/dist/devices/devices.service.d.ts +176 -4
- package/dist/devices/devices.service.js +341 -6
- package/dist/devices/dto.d.ts +56 -3
- package/dist/devices/dto.js +51 -1
- package/dist/devices/public-suffix.d.ts +6 -0
- package/dist/devices/public-suffix.js +79 -0
- package/dist/errors.d.ts +46 -5
- package/dist/errors.js +46 -5
- package/dist/evals/reconstruct.d.ts +18 -13
- package/dist/evals/reconstruct.js +50 -36
- package/dist/evals/recorded-tools.d.ts +7 -7
- package/dist/evals/recorded-tools.js +4 -3
- package/dist/evals/trajectory.d.ts +6 -1
- package/dist/evals/trajectory.js +7 -0
- package/dist/extensions/bootstrap.d.ts +49 -10
- package/dist/extensions/bootstrap.js +104 -27
- package/dist/extensions/package.js +2 -2
- package/dist/http/api.module.js +5 -0
- package/dist/inbox/inbox.module.js +2 -1
- package/dist/inbox/inbox.service.d.ts +19 -4
- package/dist/inbox/inbox.service.js +14 -3
- package/dist/infra/config/kernel-config.service.js +11 -0
- package/dist/infra/events/kernel-events.d.ts +2 -1
- package/dist/lifecycle/kernel-lifecycle.d.ts +5 -1
- package/dist/lifecycle/kernel-lifecycle.js +16 -4
- package/dist/local-devices/device-policy.service.d.ts +65 -0
- package/dist/local-devices/device-policy.service.js +217 -0
- package/dist/local-devices/local-device-gateway.js +4 -1
- package/dist/local-devices/local-device-provider.d.ts +40 -3
- package/dist/local-devices/local-device-provider.js +109 -7
- package/dist/local-devices/local-devices.module.d.ts +2 -1
- package/dist/local-devices/local-devices.module.js +19 -3
- package/dist/local-devices/machines.d.ts +14 -3
- package/dist/local-devices/machines.js +41 -3
- package/dist/local-devices/network-grants.d.ts +104 -0
- package/dist/local-devices/network-grants.js +288 -0
- package/dist/local-devices/policy-summary.d.ts +20 -0
- package/dist/local-devices/policy-summary.js +63 -0
- package/dist/orgs/orgs.module.js +4 -10
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +4 -0
- package/dist/orgs/settings.controller.js +2 -1
- package/dist/orgs/settings.service.d.ts +164 -12
- package/dist/orgs/settings.service.js +212 -24
- package/dist/platform/exclusions.js +11 -1
- package/dist/platform/operation.js +4 -0
- package/dist/platform/ops/admin-items.ops.js +1 -1
- package/dist/platform/ops/agent-skills.ops.js +2 -2
- package/dist/platform/ops/agent-templates.ops.js +2 -2
- package/dist/platform/ops/agents.ops.js +11 -15
- package/dist/platform/ops/devices.ops.js +3 -1
- package/dist/platform/ops/inbox.ops.js +19 -0
- package/dist/platform/ops/org-settings.ops.js +14 -5
- package/dist/platform/ops/platform.ops.d.ts +9 -1
- package/dist/platform/ops/platform.ops.js +34 -12
- package/dist/platform/ops/requests.ops.js +3 -2
- package/dist/platform/ops/schedules.ops.d.ts +21 -0
- package/dist/platform/ops/schedules.ops.js +470 -0
- package/dist/platform/ops/skills.ops.js +3 -3
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +5 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/roles/worker.module.js +3 -0
- package/dist/runtime/context/build.js +13 -4
- package/dist/runtime/context/compaction.js +6 -3
- package/dist/runtime/context/device-paths.d.ts +43 -21
- package/dist/runtime/context/device-paths.js +104 -21
- package/dist/runtime/context/run-context.d.ts +9 -0
- package/dist/runtime/context/run-context.js +8 -0
- package/dist/runtime/context/skills.d.ts +14 -1
- package/dist/runtime/context/skills.js +36 -5
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +16 -5
- package/dist/runtime/run-finish.d.ts +6 -1
- package/dist/runtime/run-finish.js +16 -2
- package/dist/runtime/run-queue.js +21 -2
- package/dist/runtime/run-worker.js +14 -33
- package/dist/runtime/runtime.module.js +3 -0
- package/dist/runtime/subagents/definition.d.ts +32 -14
- package/dist/runtime/subagents/definition.js +106 -109
- package/dist/runtime/subagents/dispatch.js +4 -3
- package/dist/runtime/subagents/preamble.d.ts +2 -1
- package/dist/runtime/subagents/preamble.js +2 -1
- package/dist/runtime/waits.js +14 -4
- package/dist/sandbox/sandbox.service.d.ts +120 -10
- package/dist/sandbox/sandbox.service.js +335 -28
- package/dist/sandbox/tiers.d.ts +86 -0
- package/dist/sandbox/tiers.js +96 -0
- package/dist/schedules/effective-settings.d.ts +16 -0
- package/dist/schedules/effective-settings.js +17 -0
- package/dist/schedules/errors.d.ts +8 -0
- package/dist/schedules/errors.js +8 -0
- package/dist/schedules/fire.d.ts +118 -0
- package/dist/schedules/fire.js +625 -0
- package/dist/schedules/grant-rules.d.ts +94 -0
- package/dist/schedules/grant-rules.js +126 -0
- package/dist/schedules/job-ids.d.ts +32 -0
- package/dist/schedules/job-ids.js +27 -0
- package/dist/schedules/pause.d.ts +9 -0
- package/dist/schedules/pause.js +33 -0
- package/dist/schedules/run-tracker.d.ts +81 -0
- package/dist/schedules/run-tracker.js +333 -0
- package/dist/schedules/scan.job.d.ts +64 -0
- package/dist/schedules/scan.job.js +303 -0
- package/dist/schedules/schedule-math.d.ts +31 -0
- package/dist/schedules/schedule-math.js +223 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +351 -0
- package/dist/schedules/scheduled-tasks.service.js +1193 -0
- package/dist/schedules/schedules.controller.d.ts +68 -0
- package/dist/schedules/schedules.controller.js +242 -0
- package/dist/schedules/schedules.module.d.ts +16 -0
- package/dist/schedules/schedules.module.js +65 -0
- package/dist/schedules/schedules.schemas.d.ts +316 -0
- package/dist/schedules/schedules.schemas.js +186 -0
- package/dist/schedules/store.d.ts +81 -0
- package/dist/schedules/store.js +390 -0
- package/dist/schedules/store.module.d.ts +6 -0
- package/dist/schedules/store.module.js +21 -0
- package/dist/schedules/types.d.ts +108 -0
- package/dist/schedules/types.js +1 -0
- package/dist/schedules/unattended.d.ts +117 -0
- package/dist/schedules/unattended.js +228 -0
- package/dist/setup/oauth-token-probe.js +8 -4
- package/dist/skills/agent-skills.service.d.ts +4 -8
- package/dist/skills/agent-skills.service.js +18 -53
- package/dist/skills/catalog.d.ts +65 -62
- package/dist/skills/catalog.js +109 -206
- package/dist/skills/conversation-catalog.d.ts +3 -3
- package/dist/skills/conversation-catalog.js +5 -12
- package/dist/skills/invoke.d.ts +2 -2
- package/dist/skills/skills.controller.d.ts +3 -1
- package/dist/skills/skills.service.d.ts +38 -37
- package/dist/skills/skills.service.js +168 -107
- package/dist/skills/usable.d.ts +57 -8
- package/dist/skills/usable.js +172 -38
- package/dist/tools/approvals.controller.d.ts +4 -2
- package/dist/tools/approvals.controller.js +17 -2
- package/dist/tools/approvals.schemas.d.ts +1 -0
- package/dist/tools/approvals.schemas.js +3 -1
- package/dist/tools/approvals.service.d.ts +182 -7
- package/dist/tools/approvals.service.js +597 -13
- package/dist/tools/builtin-names.d.ts +25 -4
- package/dist/tools/builtin-names.js +45 -4
- package/dist/tools/builtins/builtin-tools.d.ts +8 -0
- package/dist/tools/builtins/builtin-tools.js +23 -2
- package/dist/tools/builtins/sandbox/bash.js +16 -7
- package/dist/tools/builtins/sandbox/common.d.ts +1 -1
- package/dist/tools/builtins/sandbox/common.js +33 -10
- package/dist/tools/builtins/sandbox/edit.js +7 -3
- package/dist/tools/builtins/sandbox/file-state.d.ts +31 -1
- package/dist/tools/builtins/sandbox/file-state.js +33 -3
- package/dist/tools/builtins/sandbox/write.js +8 -4
- package/dist/tools/builtins/schedules.d.ts +107 -0
- package/dist/tools/builtins/schedules.js +789 -0
- package/dist/tools/elicitation.d.ts +2 -0
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/fixed-ask.d.ts +7 -0
- package/dist/tools/fixed-ask.js +9 -0
- package/dist/tools/network-asks.d.ts +109 -0
- package/dist/tools/network-asks.js +221 -0
- package/dist/tools/pipeline.d.ts +53 -6
- package/dist/tools/pipeline.js +202 -13
- package/dist/tools/policy.d.ts +21 -8
- package/dist/tools/policy.js +63 -9
- package/dist/tools/registry.d.ts +10 -1
- package/dist/tools/tools.module.js +12 -0
- package/package.json +2 -2
- package/src/migrations/0113_scheduled_tasks.sql +108 -0
- package/src/migrations/0114_network_asks.sql +23 -0
- package/src/migrations/0115_network_requests.sql +28 -0
- package/src/migrations/0116_skills_default_on.sql +37 -0
- package/src/migrations/0117_sandbox_tiers.sql +11 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type BootstrapManifest, type Logger } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import { type BootstrapEntry, type BootstrapManifest, type Logger } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { type PluginImport } from "../catalog/plugin-import.js";
|
|
3
3
|
import type { KernelConfig } from "../config/schema.js";
|
|
4
|
+
import { ApiError } from "../errors.js";
|
|
4
5
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
5
6
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
6
7
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -35,9 +36,15 @@ import type { SingleProviderNote } from "./single-provider.js";
|
|
|
35
36
|
* until expiry) aborts the run at its next step. "Done" is a `bootstrap_runs` row for the
|
|
36
37
|
* manifest's sha256 (written with the audit `bootstrap.completed` only when every entry
|
|
37
38
|
* succeeded; otherwise the next start runs it again, which is idempotent).
|
|
39
|
+
* - Two passes per start: the first runs before the extensions load (no object store yet), the
|
|
40
|
+
* second after them. A `builtin` entry (not required, but builtin in the catalog) is deferred by
|
|
41
|
+
* the first pass (`deferBuiltin`: skipped, not a failure; the run is then not recorded and the
|
|
42
|
+
* start runs the second pass), so it may ship skills and templates. A required entry is imported
|
|
43
|
+
* by the first pass and must succeed; a builtin one that fails is logged like an optional one.
|
|
38
44
|
* - Only entries new to the manifest are installed (Ruling 5): an optional entry that the last
|
|
39
45
|
* completed run already handled and that is not installed now (a super admin uninstalled
|
|
40
|
-
* it) stays uninstalled -> `kept`. A required entry is always installed
|
|
46
|
+
* it) stays uninstalled -> `kept`. A required or builtin entry is always installed (a
|
|
47
|
+
* declarative one imported again when its catalog item is gone).
|
|
41
48
|
* - Per entry, by the installed state of its extension:
|
|
42
49
|
* - not installed (and new, or required): imported into the catalog (source `bootstrap`, ref
|
|
43
50
|
* `bootstrap:<name>@<version>`, like a marketplace import), installed, approved (snapshot
|
|
@@ -65,7 +72,8 @@ import type { SingleProviderNote } from "./single-provider.js";
|
|
|
65
72
|
* never needed again. A plugin's icons and setup guide files are kept in PG too (`catalog_files`),
|
|
66
73
|
* so they never need it either; its skills, connector templates and agent templates do (an entry
|
|
67
74
|
* shipping them fails while no object store runs; an optional one is retried after the extensions
|
|
68
|
-
* loaded
|
|
75
|
+
* loaded, and a plugin that must be builtin and ships them is a `builtin` entry, which only the
|
|
76
|
+
* pass after the extensions load imports).
|
|
69
77
|
*/
|
|
70
78
|
/** The bootstrap manifest that ships with the kernel package. */
|
|
71
79
|
export declare const BOOTSTRAP_MANIFEST_FILE: string;
|
|
@@ -93,15 +101,23 @@ export interface BootstrapFailure {
|
|
|
93
101
|
code: string;
|
|
94
102
|
message: string;
|
|
95
103
|
}
|
|
96
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* Some entries failed or were deferred (the others were done); the run is not recorded as done.
|
|
106
|
+
*/
|
|
97
107
|
export declare class BootstrapFailedError extends Error {
|
|
98
108
|
readonly failures: BootstrapFailure[];
|
|
99
109
|
readonly results: BootstrapEntryResult[];
|
|
110
|
+
readonly deferred: string[];
|
|
111
|
+
readonly packages: ReadonlyMap<string, Uint8Array>;
|
|
100
112
|
/**
|
|
101
113
|
* @param results what the entries that did not fail did (pass them as `carry` to a later run in
|
|
102
114
|
* the same start, so its record keeps `installed` instead of `kept`).
|
|
115
|
+
* @param deferred the builtin entries a first pass skipped (`deferBuiltin`): not failures, the
|
|
116
|
+
* later pass of the same start imports them.
|
|
117
|
+
* @param packages the packages this run obtained, by entry name (pass them as `packages` to the
|
|
118
|
+
* later pass of the same start, so nothing is downloaded twice).
|
|
103
119
|
*/
|
|
104
|
-
constructor(failures: BootstrapFailure[], results?: BootstrapEntryResult[]);
|
|
120
|
+
constructor(failures: BootstrapFailure[], results?: BootstrapEntryResult[], deferred?: string[], packages?: ReadonlyMap<string, Uint8Array>);
|
|
105
121
|
/** A required entry failed: the kernel must not serve without it. */
|
|
106
122
|
get requiredFailed(): boolean;
|
|
107
123
|
}
|
|
@@ -121,13 +137,21 @@ export interface BootstrapResolveOptions {
|
|
|
121
137
|
log?: Pick<Logger, "warn">;
|
|
122
138
|
/** The npm download (default {@link fetchNpmPackage}; tests replace it). */
|
|
123
139
|
fetch?: typeof fetchNpmPackage;
|
|
140
|
+
/**
|
|
141
|
+
* Entries whose package failing to be obtained is that entry's failure only: the error goes into
|
|
142
|
+
* `failed` (by entry name) and the other entries are still obtained. Every other entry's failure
|
|
143
|
+
* throws, so nothing is written.
|
|
144
|
+
*/
|
|
145
|
+
soft?: (e: BootstrapEntry) => boolean;
|
|
146
|
+
failed?: Map<string, ApiError>;
|
|
124
147
|
}
|
|
125
148
|
/**
|
|
126
149
|
* Obtains every entry's tgz, checked against its pinned sha512: from the offline directory when a
|
|
127
150
|
* file there has that sha512, else (a `source: "npm"` entry) downloaded from the npm registry and
|
|
128
151
|
* verified against the pin (the packument's `dist.integrity` is not consulted). Throws an
|
|
129
152
|
* {@link ApiError} naming the plugin for the first entry it cannot obtain
|
|
130
|
-
* (`bootstrap.missing_file`, `bootstrap.download_failed`, `bootstrap.integrity_mismatch`)
|
|
153
|
+
* (`bootstrap.missing_file`, `bootstrap.download_failed`, `bootstrap.integrity_mismatch`), except
|
|
154
|
+
* for the `soft` entries (recorded in `failed`, left out of the result).
|
|
131
155
|
*/
|
|
132
156
|
export declare function resolveBootstrapPackages(manifest: BootstrapManifest, o: BootstrapResolveOptions): Promise<Map<string, Uint8Array>>;
|
|
133
157
|
/** The lock around a whole run (`lock:bootstrap`). */
|
|
@@ -181,6 +205,17 @@ export declare class BootstrapService {
|
|
|
181
205
|
dir?: string;
|
|
182
206
|
signal?: AbortSignal;
|
|
183
207
|
carry?: readonly BootstrapEntryResult[];
|
|
208
|
+
/**
|
|
209
|
+
* The first pass of a start (before the extensions load, so no object store): builtin entries
|
|
210
|
+
* are skipped, and the run throws {@link BootstrapFailedError} with them as `deferred` instead
|
|
211
|
+
* of being recorded as done.
|
|
212
|
+
*/
|
|
213
|
+
deferBuiltin?: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Packages an earlier pass of the same start obtained ({@link BootstrapFailedError.packages});
|
|
216
|
+
* one whose sha512 still equals its entry's pin is used instead of obtaining it again.
|
|
217
|
+
*/
|
|
218
|
+
packages?: ReadonlyMap<string, Uint8Array>;
|
|
184
219
|
/** The plugin import a declarative entry (or an entry's catalog version) goes through. */
|
|
185
220
|
imports: BootstrapImports;
|
|
186
221
|
}): Promise<BootstrapResult>;
|
|
@@ -201,11 +236,15 @@ export declare class BootstrapService {
|
|
|
201
236
|
/** The entry names the last completed run handled (undefined before any run completed). */
|
|
202
237
|
private lastRunNames;
|
|
203
238
|
private entry;
|
|
239
|
+
/** Whether a live (not deleted) platform catalog item has this name. */
|
|
240
|
+
private hasLiveItem;
|
|
204
241
|
/**
|
|
205
|
-
* The catalog item of a bootstrap entry follows `required`:
|
|
206
|
-
* to every org (scope `all
|
|
207
|
-
* disabled); an entry that stops being required
|
|
208
|
-
* admin may change it from then on).
|
|
242
|
+
* The catalog item of a bootstrap entry follows `required` / `builtin`: such an entry is builtin,
|
|
243
|
+
* offered to every org (scope `all`, which an org admin cannot switch off) and not disabled
|
|
244
|
+
* (migration 0075 could leave a required plugin disabled); an entry that stops being required or
|
|
245
|
+
* builtin is no longer builtin and keeps scope `all` (the admin may change it from then on).
|
|
246
|
+
* Only the platform item: an org-owned item of the same name (the entry then fails with
|
|
247
|
+
* `plugin.name_taken`) is never touched.
|
|
209
248
|
*/
|
|
210
249
|
private markBuiltin;
|
|
211
250
|
/** A declarative plugin: catalog only. Returns false when that version is already imported. */
|
|
@@ -57,9 +57,15 @@ import { ExtensionRegistry } from "./registry.js";
|
|
|
57
57
|
* until expiry) aborts the run at its next step. "Done" is a `bootstrap_runs` row for the
|
|
58
58
|
* manifest's sha256 (written with the audit `bootstrap.completed` only when every entry
|
|
59
59
|
* succeeded; otherwise the next start runs it again, which is idempotent).
|
|
60
|
+
* - Two passes per start: the first runs before the extensions load (no object store yet), the
|
|
61
|
+
* second after them. A `builtin` entry (not required, but builtin in the catalog) is deferred by
|
|
62
|
+
* the first pass (`deferBuiltin`: skipped, not a failure; the run is then not recorded and the
|
|
63
|
+
* start runs the second pass), so it may ship skills and templates. A required entry is imported
|
|
64
|
+
* by the first pass and must succeed; a builtin one that fails is logged like an optional one.
|
|
60
65
|
* - Only entries new to the manifest are installed (Ruling 5): an optional entry that the last
|
|
61
66
|
* completed run already handled and that is not installed now (a super admin uninstalled
|
|
62
|
-
* it) stays uninstalled -> `kept`. A required entry is always installed
|
|
67
|
+
* it) stays uninstalled -> `kept`. A required or builtin entry is always installed (a
|
|
68
|
+
* declarative one imported again when its catalog item is gone).
|
|
63
69
|
* - Per entry, by the installed state of its extension:
|
|
64
70
|
* - not installed (and new, or required): imported into the catalog (source `bootstrap`, ref
|
|
65
71
|
* `bootstrap:<name>@<version>`, like a marketplace import), installed, approved (snapshot
|
|
@@ -87,22 +93,35 @@ import { ExtensionRegistry } from "./registry.js";
|
|
|
87
93
|
* never needed again. A plugin's icons and setup guide files are kept in PG too (`catalog_files`),
|
|
88
94
|
* so they never need it either; its skills, connector templates and agent templates do (an entry
|
|
89
95
|
* shipping them fails while no object store runs; an optional one is retried after the extensions
|
|
90
|
-
* loaded
|
|
96
|
+
* loaded, and a plugin that must be builtin and ships them is a `builtin` entry, which only the
|
|
97
|
+
* pass after the extensions load imports).
|
|
91
98
|
*/
|
|
92
99
|
/** The bootstrap manifest that ships with the kernel package. */
|
|
93
100
|
export const BOOTSTRAP_MANIFEST_FILE = fileURLToPath(new URL("../../bootstrap.json", import.meta.url));
|
|
94
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Some entries failed or were deferred (the others were done); the run is not recorded as done.
|
|
103
|
+
*/
|
|
95
104
|
export class BootstrapFailedError extends Error {
|
|
96
105
|
failures;
|
|
97
106
|
results;
|
|
107
|
+
deferred;
|
|
108
|
+
packages;
|
|
98
109
|
/**
|
|
99
110
|
* @param results what the entries that did not fail did (pass them as `carry` to a later run in
|
|
100
111
|
* the same start, so its record keeps `installed` instead of `kept`).
|
|
112
|
+
* @param deferred the builtin entries a first pass skipped (`deferBuiltin`): not failures, the
|
|
113
|
+
* later pass of the same start imports them.
|
|
114
|
+
* @param packages the packages this run obtained, by entry name (pass them as `packages` to the
|
|
115
|
+
* later pass of the same start, so nothing is downloaded twice).
|
|
101
116
|
*/
|
|
102
|
-
constructor(failures, results = []) {
|
|
103
|
-
super(
|
|
117
|
+
constructor(failures, results = [], deferred = [], packages = new Map()) {
|
|
118
|
+
super(failures.length > 0
|
|
119
|
+
? `bootstrap failed for ${failures.map((f) => `${f.name}${f.required ? " (required)" : ""}: ${f.message}`).join("; ")}`
|
|
120
|
+
: `bootstrap deferred the builtin plugins ${deferred.join(", ")} to the pass after the extensions load`);
|
|
104
121
|
this.failures = failures;
|
|
105
122
|
this.results = results;
|
|
123
|
+
this.deferred = deferred;
|
|
124
|
+
this.packages = packages;
|
|
106
125
|
this.name = "BootstrapFailedError";
|
|
107
126
|
}
|
|
108
127
|
/** A required entry failed: the kernel must not serve without it. */
|
|
@@ -128,7 +147,8 @@ const integrityOf = (bytes) => `sha512-${createHash("sha512").update(bytes).dige
|
|
|
128
147
|
* file there has that sha512, else (a `source: "npm"` entry) downloaded from the npm registry and
|
|
129
148
|
* verified against the pin (the packument's `dist.integrity` is not consulted). Throws an
|
|
130
149
|
* {@link ApiError} naming the plugin for the first entry it cannot obtain
|
|
131
|
-
* (`bootstrap.missing_file`, `bootstrap.download_failed`, `bootstrap.integrity_mismatch`)
|
|
150
|
+
* (`bootstrap.missing_file`, `bootstrap.download_failed`, `bootstrap.integrity_mismatch`), except
|
|
151
|
+
* for the `soft` entries (recorded in `failed`, left out of the result).
|
|
132
152
|
*/
|
|
133
153
|
export async function resolveBootstrapPackages(manifest, o) {
|
|
134
154
|
const out = new Map();
|
|
@@ -141,11 +161,20 @@ export async function resolveBootstrapPackages(manifest, o) {
|
|
|
141
161
|
const where = o.dir !== undefined ? o.dir : "the bootstrap directory (config bootstrap.dir)";
|
|
142
162
|
for (const e of manifest.plugins) {
|
|
143
163
|
signal.throwIfAborted();
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
out.set(e.name, found);
|
|
147
|
-
continue;
|
|
164
|
+
try {
|
|
165
|
+
out.set(e.name, await obtain(e));
|
|
148
166
|
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
if (signal.aborted || !(err instanceof ApiError) || o.soft?.(e) !== true)
|
|
169
|
+
throw err;
|
|
170
|
+
o.failed?.set(e.name, err);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return out;
|
|
174
|
+
async function obtain(e) {
|
|
175
|
+
const found = offline.get(e.integrity);
|
|
176
|
+
if (found !== undefined)
|
|
177
|
+
return found;
|
|
149
178
|
if (e.source === "workspace") {
|
|
150
179
|
throw new ApiError("bootstrap.missing_file", `Bootstrap plugin ${e.name} ${e.version}: no file in ${where} has its pinned sha512 (${e.integrity.slice(0, 19)}…), and a workspace entry cannot be downloaded; put its package tgz (pnpm pack-plugin ${e.path}) in that directory`);
|
|
151
180
|
}
|
|
@@ -153,7 +182,7 @@ export async function resolveBootstrapPackages(manifest, o) {
|
|
|
153
182
|
const offlineHint = `to install offline, put the package tgz (npm pack ${e.npm}@${e.version}, any file name) in ${where}`;
|
|
154
183
|
try {
|
|
155
184
|
const r = await fetchPackage({ registry: npmRegistry, ...(npmToken !== undefined && { token: npmToken }), maxBytes }, e.npm, e.version, signal, { expectedIntegrity: e.integrity });
|
|
156
|
-
|
|
185
|
+
return r.bytes;
|
|
157
186
|
}
|
|
158
187
|
catch (err) {
|
|
159
188
|
if (signal.aborted)
|
|
@@ -169,7 +198,6 @@ export async function resolveBootstrapPackages(manifest, o) {
|
|
|
169
198
|
throw new ApiError("bootstrap.download_failed", `Bootstrap plugin ${e.name} ${e.version}: cannot download ${e.npm}@${e.version} from ${registry} (${reason}); ${offlineHint}, or set packages.npmRegistry to a reachable mirror`);
|
|
170
199
|
}
|
|
171
200
|
}
|
|
172
|
-
return out;
|
|
173
201
|
}
|
|
174
202
|
/** The registry's origin, for messages (never its credentials or path). */
|
|
175
203
|
function registryOrigin(registry) {
|
|
@@ -298,20 +326,47 @@ let BootstrapService = class BootstrapService {
|
|
|
298
326
|
const done = await recorded();
|
|
299
327
|
if (done)
|
|
300
328
|
return done;
|
|
301
|
-
|
|
302
|
-
const
|
|
329
|
+
const deferBuiltin = o.deferBuiltin === true;
|
|
330
|
+
const isDeferred = (e) => deferBuiltin && e.builtin === true;
|
|
331
|
+
// Every package is obtained and checked before the first write (a deferred entry's by the
|
|
332
|
+
// later pass). The first pass refuses to write anything when one is missing or tampered;
|
|
333
|
+
// the later pass only fails that entry unless it is required.
|
|
334
|
+
const files = new Map();
|
|
335
|
+
const fetchFailed = new Map();
|
|
336
|
+
const toObtain = [];
|
|
337
|
+
for (const e of o.manifest.plugins) {
|
|
338
|
+
if (isDeferred(e))
|
|
339
|
+
continue;
|
|
340
|
+
const kept = o.packages?.get(e.name);
|
|
341
|
+
if (kept !== undefined && integrityOf(kept) === e.integrity)
|
|
342
|
+
files.set(e.name, kept);
|
|
343
|
+
else
|
|
344
|
+
toObtain.push(e);
|
|
345
|
+
}
|
|
346
|
+
const obtained = await resolveBootstrapPackages({ ...o.manifest, plugins: toObtain }, {
|
|
303
347
|
...(o.dir !== undefined && { dir: o.dir }),
|
|
304
348
|
config: this.config(),
|
|
305
349
|
signal,
|
|
306
350
|
log: this.log,
|
|
351
|
+
...(!deferBuiltin && { soft: (e) => !e.required, failed: fetchFailed }),
|
|
307
352
|
});
|
|
353
|
+
for (const [name, bytes] of obtained)
|
|
354
|
+
files.set(name, bytes);
|
|
308
355
|
const handled = await this.lastRunNames();
|
|
309
356
|
const results = [];
|
|
310
357
|
const failures = [];
|
|
358
|
+
const deferred = [];
|
|
311
359
|
for (const e of o.manifest.plugins) {
|
|
312
360
|
signal.throwIfAborted();
|
|
361
|
+
if (isDeferred(e)) {
|
|
362
|
+
deferred.push(e.name);
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
313
365
|
await this.warnIfHeld(e);
|
|
314
366
|
try {
|
|
367
|
+
const fetchErr = fetchFailed.get(e.name);
|
|
368
|
+
if (fetchErr !== undefined)
|
|
369
|
+
throw fetchErr;
|
|
315
370
|
const r = await this.entry(e, files.get(e.name), handled, o.imports);
|
|
316
371
|
results.push(carried(r, o.carry));
|
|
317
372
|
}
|
|
@@ -320,6 +375,7 @@ let BootstrapService = class BootstrapService {
|
|
|
320
375
|
plugin: e.name,
|
|
321
376
|
version: e.version,
|
|
322
377
|
required: e.required,
|
|
378
|
+
...(e.builtin === true && { builtin: true }),
|
|
323
379
|
err,
|
|
324
380
|
});
|
|
325
381
|
failures.push({
|
|
@@ -331,8 +387,9 @@ let BootstrapService = class BootstrapService {
|
|
|
331
387
|
}
|
|
332
388
|
}
|
|
333
389
|
results.push(...(await this.clearRemoved(o.manifest)));
|
|
334
|
-
if (failures.length > 0)
|
|
335
|
-
throw new BootstrapFailedError(failures, results);
|
|
390
|
+
if (failures.length > 0 || deferred.length > 0) {
|
|
391
|
+
throw new BootstrapFailedError(failures, results, deferred, files);
|
|
392
|
+
}
|
|
336
393
|
signal.throwIfAborted();
|
|
337
394
|
await this.recordDone(manifestSha256, results);
|
|
338
395
|
this.log.info("bootstrap completed", { manifestSha256, results });
|
|
@@ -421,12 +478,15 @@ let BootstrapService = class BootstrapService {
|
|
|
421
478
|
const ref = `bootstrap:${e.name}@${e.version}`;
|
|
422
479
|
// Not new to the manifest: an optional entry left out on purpose stays out (Ruling 5)
|
|
423
480
|
const isNew = handled === undefined || !handled.has(e.name);
|
|
481
|
+
// Required and builtin entries are builtin in the catalog and put back when missing
|
|
482
|
+
const builtin = e.required || e.builtin === true;
|
|
424
483
|
if (!pkg.manifest.extension) {
|
|
425
|
-
await this.markBuiltin(e.name,
|
|
426
|
-
if (!isNew)
|
|
484
|
+
await this.markBuiltin(e.name, builtin);
|
|
485
|
+
if (!isNew && !(builtin && !(await this.hasLiveItem(e.name)))) {
|
|
427
486
|
return { name: e.name, action: "kept", version: e.version };
|
|
487
|
+
}
|
|
428
488
|
const imported = await this.importOnly(e, bytes, ref, imports);
|
|
429
|
-
await this.markBuiltin(e.name,
|
|
489
|
+
await this.markBuiltin(e.name, builtin);
|
|
430
490
|
return { name: e.name, action: imported ? "imported" : "kept", version: e.version };
|
|
431
491
|
}
|
|
432
492
|
if (this.registry.declared().has(e.name)) {
|
|
@@ -438,7 +498,7 @@ let BootstrapService = class BootstrapService {
|
|
|
438
498
|
.select(["version", "source", "required", "desired_state", "sha256"])
|
|
439
499
|
.where("name", "=", e.name)
|
|
440
500
|
.executeTakeFirst();
|
|
441
|
-
if (!row && !isNew && !
|
|
501
|
+
if (!row && !isNew && !builtin) {
|
|
442
502
|
this.log.info("bootstrap: an optional plugin that is not installed stays uninstalled", {
|
|
443
503
|
plugin: e.name,
|
|
444
504
|
});
|
|
@@ -476,18 +536,31 @@ let BootstrapService = class BootstrapService {
|
|
|
476
536
|
if (e.required && row?.desired_state === "disabled") {
|
|
477
537
|
leftDisabled = await this.enableOrWarn(e);
|
|
478
538
|
}
|
|
479
|
-
await this.markBuiltin(e.name,
|
|
539
|
+
await this.markBuiltin(e.name, builtin);
|
|
480
540
|
return leftDisabled === undefined ? result : { ...result, leftDisabled };
|
|
481
541
|
}
|
|
542
|
+
/** Whether a live (not deleted) platform catalog item has this name. */
|
|
543
|
+
async hasLiveItem(name) {
|
|
544
|
+
const row = await this.db
|
|
545
|
+
.selectFrom("catalog_items")
|
|
546
|
+
.select("id")
|
|
547
|
+
.where("name", "=", name)
|
|
548
|
+
.where("owner_org_id", "is", null)
|
|
549
|
+
.where("deleted_at", "is", null)
|
|
550
|
+
.executeTakeFirst();
|
|
551
|
+
return row !== undefined;
|
|
552
|
+
}
|
|
482
553
|
/**
|
|
483
|
-
* The catalog item of a bootstrap entry follows `required`:
|
|
484
|
-
* to every org (scope `all
|
|
485
|
-
* disabled); an entry that stops being required
|
|
486
|
-
* admin may change it from then on).
|
|
554
|
+
* The catalog item of a bootstrap entry follows `required` / `builtin`: such an entry is builtin,
|
|
555
|
+
* offered to every org (scope `all`, which an org admin cannot switch off) and not disabled
|
|
556
|
+
* (migration 0075 could leave a required plugin disabled); an entry that stops being required or
|
|
557
|
+
* builtin is no longer builtin and keeps scope `all` (the admin may change it from then on).
|
|
558
|
+
* Only the platform item: an org-owned item of the same name (the entry then fails with
|
|
559
|
+
* `plugin.name_taken`) is never touched.
|
|
487
560
|
*/
|
|
488
|
-
async markBuiltin(name,
|
|
561
|
+
async markBuiltin(name, builtin) {
|
|
489
562
|
const touch = { updated_at: sql `now()` };
|
|
490
|
-
if (
|
|
563
|
+
if (builtin) {
|
|
491
564
|
await this.db
|
|
492
565
|
.updateTable("catalog_items")
|
|
493
566
|
.set({
|
|
@@ -498,6 +571,7 @@ let BootstrapService = class BootstrapService {
|
|
|
498
571
|
...touch,
|
|
499
572
|
})
|
|
500
573
|
.where("name", "=", name)
|
|
574
|
+
.where("owner_org_id", "is", null)
|
|
501
575
|
.where("deleted_at", "is", null)
|
|
502
576
|
.where((eb) => eb.or([eb("builtin", "=", false), eb("scope", "<>", "all"), eb("disabled", "=", true)]))
|
|
503
577
|
.execute();
|
|
@@ -507,6 +581,7 @@ let BootstrapService = class BootstrapService {
|
|
|
507
581
|
.updateTable("catalog_items")
|
|
508
582
|
.set({ builtin: false, ...touch })
|
|
509
583
|
.where("name", "=", name)
|
|
584
|
+
.where("owner_org_id", "is", null)
|
|
510
585
|
.where("deleted_at", "is", null)
|
|
511
586
|
.where("builtin", "=", true)
|
|
512
587
|
.execute();
|
|
@@ -582,6 +657,7 @@ let BootstrapService = class BootstrapService {
|
|
|
582
657
|
.selectFrom("catalog_items")
|
|
583
658
|
.select("id")
|
|
584
659
|
.where("name", "=", e.name)
|
|
660
|
+
.where("owner_org_id", "is", null)
|
|
585
661
|
.where("deleted_at", "is", null)
|
|
586
662
|
.executeTakeFirst();
|
|
587
663
|
const installed = await this.ops.install(e.name, review.sha256, null, undefined, item ? { catalogItemId: item.id } : {});
|
|
@@ -650,6 +726,7 @@ let BootstrapService = class BootstrapService {
|
|
|
650
726
|
.updateTable("catalog_items")
|
|
651
727
|
.set({ builtin: false, updated_at: sql `now()` })
|
|
652
728
|
.where("builtin", "=", true)
|
|
729
|
+
.where("owner_org_id", "is", null)
|
|
653
730
|
.where("deleted_at", "is", null);
|
|
654
731
|
if (names.length > 0)
|
|
655
732
|
items = items.where("name", "not in", names);
|
|
@@ -2,7 +2,7 @@ import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { dirname, join, posix, relative, resolve as resolvePath } from "node:path";
|
|
3
3
|
import { checkEntryImports, isSafePackagePath, PLUGIN_MANIFEST_FILE, parsePluginManifest, } from "@capybara-hq/plugin-sdk";
|
|
4
4
|
import { init as lexerInit, parse as lexerParse } from "es-module-lexer";
|
|
5
|
-
import { PluginPackageError, readPluginPackage } from "../catalog/plugin-package.js";
|
|
5
|
+
import { PluginPackageError, readPluginPackage, withoutRemovedManifestFields, } from "../catalog/plugin-package.js";
|
|
6
6
|
import { pluginSchemaName } from "../ctx/create-ctx.js";
|
|
7
7
|
import { MIGRATION_FILE_RE } from "../db/migrator.js";
|
|
8
8
|
import { ApiError } from "../errors.js";
|
|
@@ -252,7 +252,7 @@ export async function declaredDisplayName(dir, name) {
|
|
|
252
252
|
const named = json?.name;
|
|
253
253
|
if (typeof named === "string" && named !== name)
|
|
254
254
|
return {};
|
|
255
|
-
const m = parsePluginManifest(
|
|
255
|
+
const m = parsePluginManifest(withoutRemovedManifestFields(text));
|
|
256
256
|
if ("errors" in m)
|
|
257
257
|
return { problem: m.errors.slice(0, 3).join("; ") };
|
|
258
258
|
if (m.name !== name)
|
package/dist/http/api.module.js
CHANGED
|
@@ -68,6 +68,8 @@ import { OrgsModule } from "../orgs/orgs.module.js";
|
|
|
68
68
|
import { OrgSettingsController } from "../orgs/settings.controller.js";
|
|
69
69
|
import { RuntimeModule } from "../runtime/runtime.module.js";
|
|
70
70
|
import { ConversationStreamController } from "../runtime/stream.controller.js";
|
|
71
|
+
import { SchedulesController } from "../schedules/schedules.controller.js";
|
|
72
|
+
import { SchedulesModule } from "../schedules/schedules.module.js";
|
|
71
73
|
import { SetupModule } from "../setup/setup.module.js";
|
|
72
74
|
import { SetupChecksController } from "../setup/setup-checks.controller.js";
|
|
73
75
|
import { SetupGuidesController } from "../setup/setup-guides.controller.js";
|
|
@@ -123,6 +125,7 @@ const CONTROLLERS = [
|
|
|
123
125
|
ConversationsController,
|
|
124
126
|
BackgroundController,
|
|
125
127
|
DevicesController,
|
|
128
|
+
SchedulesController,
|
|
126
129
|
AttachmentsController,
|
|
127
130
|
SkillsController,
|
|
128
131
|
SkillChangesController,
|
|
@@ -204,6 +207,8 @@ ApiModule = __decorate([
|
|
|
204
207
|
ThemesModule,
|
|
205
208
|
ClientModule,
|
|
206
209
|
SetupModule,
|
|
210
|
+
// scheduled tasks (the controller comes with the HTTP routes)
|
|
211
|
+
SchedulesModule,
|
|
207
212
|
],
|
|
208
213
|
controllers: CONTROLLERS,
|
|
209
214
|
providers: [{ provide: APP_GUARD, useClass: AuthGuard }],
|
|
@@ -6,6 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { Module } from "@nestjs/common";
|
|
8
8
|
import { CatalogModule } from "../catalog/catalog.module.js";
|
|
9
|
+
import { SchedulesModule } from "../schedules/schedules.module.js";
|
|
9
10
|
import { SkillsModule } from "../skills/skills.module.js";
|
|
10
11
|
import { ToolsModule } from "../tools/tools.module.js";
|
|
11
12
|
import { InboxService } from "./inbox.service.js";
|
|
@@ -18,7 +19,7 @@ let InboxModule = class InboxModule {
|
|
|
18
19
|
};
|
|
19
20
|
InboxModule = __decorate([
|
|
20
21
|
Module({
|
|
21
|
-
imports: [ToolsModule, SkillsModule, CatalogModule],
|
|
22
|
+
imports: [ToolsModule, SkillsModule, CatalogModule, SchedulesModule],
|
|
22
23
|
providers: [InboxService, PlatformInboxService],
|
|
23
24
|
exports: [InboxService, PlatformInboxService],
|
|
24
25
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CatalogRequestsService, type CatalogRequestView } from "../catalog/requests.service.js";
|
|
2
2
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { type ScheduleAttention, ScheduledTasksService } from "../schedules/scheduled-tasks.service.js";
|
|
3
4
|
import { SkillChangesService, type SkillChangeView } from "../skills/changes.service.js";
|
|
4
5
|
import { ApprovalsService, type ApprovalView } from "../tools/approvals.service.js";
|
|
5
6
|
import type { OrgNoticeDetails } from "./org-notices.js";
|
|
@@ -40,11 +41,16 @@ export declare const INBOX_MAX_ITEMS = 100;
|
|
|
40
41
|
* - `tool_approval`:当前用户能处理的待处理工具调用审批(与 `GET /approvals?status=pending` 同一视图);
|
|
41
42
|
* - `skill_change`: pending skill share requests and proposed versions of shared skills, when the
|
|
42
43
|
* current user is an org admin (`skillChange.kind`; spec §5.4, §5.5);
|
|
43
|
-
* - `catalog_request`: pending `enable` requests from members and pending
|
|
44
|
-
* requests (`request.kind`; `
|
|
45
|
-
* P4-T6-5
|
|
44
|
+
* - `catalog_request`: pending `enable` and `network_allowlist` requests from members and pending
|
|
45
|
+
* `connector_setup` requests (`request.kind`; for `connector_setup` `request.agent` and
|
|
46
|
+
* `request.connectors` set, `item` null, ruling P4-T6-5; for `network_allowlist`
|
|
47
|
+
* `request.network` set, network ask-to-allow spec §5.3), when the current user is an org admin
|
|
48
|
+
* (M6 T26, C22; plugin scope spec §5.1);
|
|
46
49
|
* - `catalog_request_decided`: the current user's own requests in this org that were approved or
|
|
47
50
|
* rejected (with the reason), until dismissed (`POST catalog-requests/:id/dismiss`);
|
|
51
|
+
* - `schedule_attention`: the current user's own scheduled task that needs them (spec §8): paused
|
|
52
|
+
* for any reason but their own pause, its latest run failed, or its latest run was refused tools
|
|
53
|
+
* or connections; derived live, gone once the task is resumed or runs clean;
|
|
48
54
|
* - the org notices (`skill_renamed`, `item_shared`, `shared_item_updated`, `upload_confirmed`,
|
|
49
55
|
* `upload_rejected`; `type` = the notice's kind): for org admins, until one dismisses it
|
|
50
56
|
* (`POST inbox/notices/:id/dismiss`).
|
|
@@ -70,12 +76,20 @@ export type InboxItem = {
|
|
|
70
76
|
/** When it was decided. */
|
|
71
77
|
createdAt: string;
|
|
72
78
|
request: CatalogRequestView;
|
|
79
|
+
} | {
|
|
80
|
+
type: "schedule_attention";
|
|
81
|
+
/** `<taskId>:paused`, `<taskId>:failed` or `<taskId>:grants`. */
|
|
82
|
+
id: string;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
attention: ScheduleAttentionView;
|
|
73
85
|
} | {
|
|
74
86
|
type: OrgNoticeView["kind"];
|
|
75
87
|
id: string;
|
|
76
88
|
createdAt: string;
|
|
77
89
|
notice: OrgNoticeView;
|
|
78
90
|
};
|
|
91
|
+
/** A scheduled task that needs its creator ({@link ScheduleAttention}, dates as ISO strings). */
|
|
92
|
+
export type ScheduleAttentionView = Omit<ScheduleAttention, "at">;
|
|
79
93
|
/** `GET /inbox` 的结果:新的在前,最多 {@link INBOX_MAX_ITEMS} 项;`truncated` 为 true 表示还有更多。 */
|
|
80
94
|
export interface InboxView {
|
|
81
95
|
items: InboxItem[];
|
|
@@ -87,7 +101,8 @@ export declare class InboxService {
|
|
|
87
101
|
private readonly skillChanges;
|
|
88
102
|
private readonly kdb;
|
|
89
103
|
private readonly catalogRequests;
|
|
90
|
-
|
|
104
|
+
private readonly schedules;
|
|
105
|
+
constructor(approvals: Pick<ApprovalsService, "list">, skillChanges: Pick<SkillChangesService, "listPending">, kdb: KernelDb, catalogRequests: Pick<CatalogRequestsService, "listForOrgAdmin" | "listDecidedForRequester">, schedules: Pick<ScheduledTasksService, "attentionFor">);
|
|
91
106
|
list(orgId: string, accountId: string): Promise<InboxView>;
|
|
92
107
|
/** The org's open notices when the account is an org admin (else none), newest first. */
|
|
93
108
|
private notices;
|
|
@@ -13,6 +13,7 @@ import { CATALOG_REQUESTS_LIST_MAX, CatalogRequestsService, } from "../catalog/r
|
|
|
13
13
|
import { ApiError } from "../errors.js";
|
|
14
14
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
15
15
|
import { roleAtLeast } from "../orgs/roles.js";
|
|
16
|
+
import { ScheduledTasksService, } from "../schedules/scheduled-tasks.service.js";
|
|
16
17
|
import { SKILL_CHANGES_LIST_MAX, SkillChangesService, } from "../skills/changes.service.js";
|
|
17
18
|
import { APPROVALS_LIST_MAX, ApprovalsService, } from "../tools/approvals.service.js";
|
|
18
19
|
/** The most open org notices one inbox read returns. */
|
|
@@ -25,19 +26,22 @@ let InboxService = class InboxService {
|
|
|
25
26
|
skillChanges;
|
|
26
27
|
kdb;
|
|
27
28
|
catalogRequests;
|
|
28
|
-
|
|
29
|
+
schedules;
|
|
30
|
+
constructor(approvals, skillChanges, kdb, catalogRequests, schedules) {
|
|
29
31
|
this.approvals = approvals;
|
|
30
32
|
this.skillChanges = skillChanges;
|
|
31
33
|
this.kdb = kdb;
|
|
32
34
|
this.catalogRequests = catalogRequests;
|
|
35
|
+
this.schedules = schedules;
|
|
33
36
|
}
|
|
34
37
|
async list(orgId, accountId) {
|
|
35
|
-
const [approvals, changes, requests, decided, notices] = await Promise.all([
|
|
38
|
+
const [approvals, changes, requests, decided, notices, attention] = await Promise.all([
|
|
36
39
|
this.approvals.list(orgId, accountId, "pending"),
|
|
37
40
|
this.skillChanges.listPending(orgId, accountId),
|
|
38
41
|
this.catalogRequests.listForOrgAdmin(orgId, accountId),
|
|
39
42
|
this.catalogRequests.listDecidedForRequester(orgId, accountId),
|
|
40
43
|
this.notices(orgId, accountId),
|
|
44
|
+
this.schedules.attentionFor(orgId, accountId),
|
|
41
45
|
]);
|
|
42
46
|
const all = [
|
|
43
47
|
...approvals.map((a) => ({
|
|
@@ -64,6 +68,12 @@ let InboxService = class InboxService {
|
|
|
64
68
|
createdAt: r.decidedAt ?? r.createdAt,
|
|
65
69
|
request: r,
|
|
66
70
|
})),
|
|
71
|
+
...attention.map(({ at, ...view }) => ({
|
|
72
|
+
type: "schedule_attention",
|
|
73
|
+
id: `${view.taskId}:${view.reason === "missing_grants" ? "grants" : view.reason === "failed" ? "failed" : "paused"}`,
|
|
74
|
+
createdAt: at.toISOString(),
|
|
75
|
+
attention: view,
|
|
76
|
+
})),
|
|
67
77
|
...notices.map((n) => ({ type: n.kind, id: n.id, createdAt: n.createdAt, notice: n })),
|
|
68
78
|
];
|
|
69
79
|
// 新的在前;同一时刻按 id 定序(结果稳定)
|
|
@@ -142,7 +152,8 @@ InboxService = __decorate([
|
|
|
142
152
|
__param(0, Inject(ApprovalsService)),
|
|
143
153
|
__param(1, Inject(SkillChangesService)),
|
|
144
154
|
__param(2, Inject(KernelDb)),
|
|
145
|
-
__param(3, Inject(CatalogRequestsService))
|
|
155
|
+
__param(3, Inject(CatalogRequestsService)),
|
|
156
|
+
__param(4, Inject(ScheduledTasksService))
|
|
146
157
|
], InboxService);
|
|
147
158
|
export { InboxService };
|
|
148
159
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -33,6 +33,10 @@ const HOT_APPLIERS = {
|
|
|
33
33
|
"models.embedTimeoutMs": () => { },
|
|
34
34
|
// SandboxService reads the shared-lease cap at every acquisition.
|
|
35
35
|
"sandbox.maxConcurrentCommands": () => { },
|
|
36
|
+
// Sandbox tiers are read at every device use, org settings read and Platform call.
|
|
37
|
+
"sandbox.tiers.max": () => { },
|
|
38
|
+
"sandbox.tiers.default": () => { },
|
|
39
|
+
"sandbox.tiers.allowUnsandboxed": () => { },
|
|
36
40
|
// The devices service reads the personal limit at every create.
|
|
37
41
|
"devices.maxPersonal": () => { },
|
|
38
42
|
// The local device relay reads the reconnect grace at every disconnect and token response.
|
|
@@ -48,6 +52,13 @@ const HOT_APPLIERS = {
|
|
|
48
52
|
"web.fetch.maxAnswerTokens": () => { },
|
|
49
53
|
"web.fetch.cacheSeconds": () => { },
|
|
50
54
|
"web.fetch.timeoutMs": () => { },
|
|
55
|
+
// Scheduled-task settings are clamped to these bounds on every read.
|
|
56
|
+
"schedules.minIntervalFloorMinutes": () => { },
|
|
57
|
+
"schedules.maxTasksPerMemberCap": () => { },
|
|
58
|
+
"schedules.maxTasksPerOrgCap": () => { },
|
|
59
|
+
"schedules.maxRunsPerHourCap": () => { },
|
|
60
|
+
// Run start reads the skills catalog budget when it records a snapshot.
|
|
61
|
+
"skills.catalogBudgetChars": () => { },
|
|
51
62
|
};
|
|
52
63
|
/**
|
|
53
64
|
* Environment variables of renamed config keys, with their replacements: warned about once when
|
|
@@ -31,7 +31,8 @@ export interface KernelEventMap {
|
|
|
31
31
|
orgId: string;
|
|
32
32
|
conversationId: string;
|
|
33
33
|
runId: string;
|
|
34
|
-
|
|
34
|
+
/** `skipped`: a network ask closed by the run's starter's message (network ask-to-allow §6.7). */
|
|
35
|
+
status: "approved" | "denied" | "skipped";
|
|
35
36
|
};
|
|
36
37
|
/**
|
|
37
38
|
* A person answered a tool call's input request, or skipped it with a message (after the commit,
|
|
@@ -99,6 +99,8 @@ export declare class KernelLifecycle implements OnApplicationBootstrap, BeforeAp
|
|
|
99
99
|
private unwatchConfig;
|
|
100
100
|
/** What the first bootstrap pass did, carried into the second one. */
|
|
101
101
|
private bootstrapCarry;
|
|
102
|
+
/** The packages the first bootstrap pass obtained, so the second downloads nothing again. */
|
|
103
|
+
private bootstrapPackages;
|
|
102
104
|
constructor(accounts: AccountsService, configService: KernelConfigService, log: KernelLogger, options: KernelAppOptions, pool: Kysely<any>, redis: Redis, kdb: KernelDb, shutdown: GracefulShutdown, host: ExtensionHost, registry: ExtensionRegistry, installs: ExtensionInstalls, blobs: ExtensionBlobs, extensionLifecycle: ExtensionLifecycle, replicaStatus: ReplicaStatusStore, bootstrap: BootstrapService, marketplaces: MarketplacesService, pluginImport: PluginImport, bus: Pick<ExtensionContext["bus"], "publish" | "subscribe">, usageReport: UsageReporter, titles: TitleQueue, channelJobs: ChannelJobs, channelOutbound: ChannelOutbound, presence: ReplicaPresence, worker?: WorkerRole | undefined, gateway?: GatewayRole | undefined);
|
|
103
105
|
/** The kernel HTTP application (set up by `buildKernelApp` before `init()`). */
|
|
104
106
|
get http(): KernelHttpApp;
|
|
@@ -122,7 +124,9 @@ export declare class KernelLifecycle implements OnApplicationBootstrap, BeforeAp
|
|
|
122
124
|
* kernel never serves without a required plugin. A failed optional entry is logged and returns
|
|
123
125
|
* true: the start runs the step once more after the extensions loaded (a declarative entry's
|
|
124
126
|
* catalog files need the object store, which on a fresh deployment is itself a bootstrap plugin),
|
|
125
|
-
* and the next start tries again while it stays incomplete.
|
|
127
|
+
* and the next start tries again while it stays incomplete. The first pass skips the `builtin`
|
|
128
|
+
* entries (they may ship skills and templates, which need the object store) and returns true for
|
|
129
|
+
* them too; the final pass imports them, and one that fails is logged like an optional entry.
|
|
126
130
|
*/
|
|
127
131
|
private runBootstrap;
|
|
128
132
|
/** 部署尚无活跃超级管理员时提示去初始化;查询失败只记日志,不影响启动。 */
|