@capybara-hq/kernel 0.1.0-rc.12 → 0.1.0-rc.14
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.schemas.d.ts +13 -0
- package/dist/agents/agent-lookup.d.ts +5 -0
- package/dist/agents/agent-lookup.js +15 -0
- package/dist/background/background.module.js +2 -2
- package/dist/background/launch-lock.d.ts +1 -1
- package/dist/background/launch-lock.js +1 -1
- package/dist/background/poll.job.d.ts +2 -2
- package/dist/background/poll.job.js +10 -10
- package/dist/background/stop.d.ts +1 -1
- package/dist/background/stop.js +3 -3
- package/dist/background/store.d.ts +5 -5
- package/dist/background/store.js +5 -5
- package/dist/background/tasks.service.d.ts +6 -6
- package/dist/background/tasks.service.js +13 -13
- package/dist/catalog/admin-catalog.controller.d.ts +13 -2
- package/dist/catalog/admin-catalog.controller.js +24 -3
- package/dist/catalog/admin-catalog.schemas.d.ts +10 -0
- package/dist/catalog/admin-catalog.schemas.js +7 -0
- package/dist/catalog/catalog-content.d.ts +9 -1
- package/dist/catalog/catalog-content.js +2 -1
- package/dist/catalog/catalog-files.d.ts +3 -2
- package/dist/catalog/catalog-files.js +8 -5
- package/dist/catalog/component-scope.service.d.ts +14 -1
- package/dist/catalog/component-scope.service.js +12 -2
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-catalog.controller.d.ts +5 -4
- package/dist/catalog/org-catalog.controller.js +5 -4
- package/dist/catalog/org-catalog.schemas.d.ts +18 -2
- package/dist/catalog/org-catalog.schemas.js +16 -2
- package/dist/catalog/org-catalog.service.js +8 -2
- package/dist/catalog/plugin-import.js +1 -1
- package/dist/catalog/plugin-package.js +37 -9
- package/dist/catalog/plugin-upgrade.d.ts +15 -1
- package/dist/catalog/plugin-upgrade.js +18 -5
- package/dist/channels/channels.module.js +2 -2
- package/dist/channels/connections.controller.d.ts +1 -1
- package/dist/channels/connections.controller.js +1 -1
- package/dist/channels/connections.service.d.ts +22 -5
- package/dist/channels/connections.service.js +56 -10
- package/dist/channels/inbound.d.ts +8 -8
- package/dist/channels/inbound.js +31 -31
- package/dist/channels/phrases.d.ts +27 -27
- package/dist/channels/phrases.js +27 -27
- package/dist/channels/webhook.d.ts +21 -1
- package/dist/channels/webhook.js +39 -4
- package/dist/config/docs.js +1 -1
- package/dist/config/schema.d.ts +2 -2
- package/dist/config/schema.js +21 -21
- package/dist/conversations/conversations.controller.d.ts +11 -11
- package/dist/conversations/conversations.controller.js +15 -15
- package/dist/conversations/conversations.module.d.ts +1 -1
- package/dist/conversations/conversations.module.js +7 -7
- package/dist/conversations/conversations.schemas.js +1 -1
- package/dist/conversations/conversations.service.d.ts +14 -14
- package/dist/conversations/conversations.service.js +19 -19
- package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
- package/dist/conversations/{environment-status.js → device-status.js} +18 -18
- package/dist/conversations/event-log.d.ts +1 -1
- package/dist/conversations/event-log.js +1 -1
- package/dist/conversations/events.d.ts +1 -1
- package/dist/conversations/events.js +2 -2
- package/dist/ctx/create-ctx.d.ts +26 -3
- package/dist/ctx/create-ctx.js +134 -26
- package/dist/db/kernel-schema.d.ts +37 -25
- package/dist/{environments → devices}/access.d.ts +19 -19
- package/dist/{environments → devices}/access.js +28 -28
- package/dist/devices/conversation-devices.d.ts +75 -0
- package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
- package/dist/devices/devices.controller.d.ts +36 -0
- package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
- package/dist/devices/devices.module.d.ts +5 -13
- package/dist/devices/devices.module.js +16 -29
- package/dist/devices/devices.schemas.d.ts +3 -0
- package/dist/devices/devices.schemas.js +14 -0
- package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
- package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
- package/dist/devices/dto.d.ts +13 -54
- package/dist/devices/dto.js +7 -39
- package/dist/devices/label.d.ts +11 -0
- package/dist/{environments → devices}/label.js +7 -7
- package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
- package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
- package/dist/errors.d.ts +29 -25
- package/dist/errors.js +29 -25
- package/dist/evals/recorded-tools.d.ts +2 -2
- package/dist/evals/recorded-tools.js +6 -6
- package/dist/extensions/admin-ops.js +1 -0
- package/dist/extensions/admin-view.js +2 -0
- package/dist/extensions/effective-config.d.ts +6 -0
- package/dist/extensions/effective-config.js +18 -7
- package/dist/extensions/guide-places.d.ts +66 -0
- package/dist/extensions/guide-places.js +152 -0
- package/dist/extensions/host.d.ts +13 -2
- package/dist/extensions/host.js +27 -6
- package/dist/extensions/instance.d.ts +17 -2
- package/dist/extensions/instance.js +21 -0
- package/dist/extensions/ledger.d.ts +1 -1
- package/dist/extensions/permission-set.d.ts +16 -2
- package/dist/extensions/permission-set.js +17 -3
- package/dist/extensions/permission-view.d.ts +10 -1
- package/dist/extensions/plugin-guides.d.ts +207 -54
- package/dist/extensions/plugin-guides.js +436 -165
- package/dist/files/previewers.d.ts +1 -1
- package/dist/files/previewers.js +1 -1
- package/dist/http/api.module.js +16 -6
- package/dist/http/gateway-routes.d.ts +1 -1
- package/dist/http/gateway-routes.js +1 -1
- package/dist/identity/settings.d.ts +32 -0
- package/dist/identity/settings.js +26 -2
- package/dist/infra/config/kernel-config.service.js +4 -4
- package/dist/infra/lock/lock.service.d.ts +8 -0
- package/dist/infra/lock/lock.service.js +27 -0
- package/dist/infra/throttler/named-throttlers.d.ts +4 -1
- package/dist/infra/throttler/named-throttlers.js +16 -1
- package/dist/infra/throttler/throttler.guard.js +1 -1
- package/dist/kernel.module.js +3 -3
- package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
- package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
- package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
- package/dist/{devices → local-devices}/device-auth.js +51 -53
- package/dist/local-devices/device-auth.module.d.ts +7 -0
- package/dist/{devices → local-devices}/device-auth.module.js +5 -5
- package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
- package/dist/{devices → local-devices}/device-routes.js +2 -2
- package/dist/local-devices/dto.d.ts +66 -0
- package/dist/local-devices/dto.js +44 -0
- package/dist/{devices → local-devices}/keys.d.ts +11 -11
- package/dist/{devices → local-devices}/keys.js +11 -11
- package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
- package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
- package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
- package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
- package/dist/local-devices/local-devices.module.d.ts +16 -0
- package/dist/local-devices/local-devices.module.js +44 -0
- package/dist/{devices → local-devices}/machines.d.ts +26 -26
- package/dist/{devices → local-devices}/machines.js +71 -71
- package/dist/{devices → local-devices}/relay.d.ts +15 -15
- package/dist/{devices → local-devices}/relay.js +55 -55
- package/dist/{devices → local-devices}/targets.d.ts +8 -8
- package/dist/{devices → local-devices}/targets.js +14 -14
- package/dist/orgs/offboarding.d.ts +6 -6
- package/dist/orgs/offboarding.js +12 -12
- package/dist/orgs/settings.service.d.ts +28 -0
- package/dist/orgs/settings.service.js +20 -1
- package/dist/overrides.d.ts +3 -1
- package/dist/overrides.js +2 -0
- package/dist/platform/exclusions.js +48 -8
- package/dist/platform/operation.js +10 -2
- package/dist/platform/ops/admin.ops.js +8 -2
- package/dist/platform/ops/connectors.ops.js +2 -0
- package/dist/platform/ops/conversations.ops.d.ts +3 -3
- package/dist/platform/ops/conversations.ops.js +9 -9
- package/dist/platform/ops/devices.ops.d.ts +26 -0
- package/dist/platform/ops/devices.ops.js +311 -0
- package/dist/platform/ops/org-settings.ops.js +2 -2
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/setup.ops.d.ts +24 -0
- package/dist/platform/ops/setup.ops.js +212 -0
- package/dist/platform/ops/ui.ops.d.ts +8 -0
- package/dist/platform/ops/ui.ops.js +41 -0
- package/dist/platform/platform-ops.module.d.ts +4 -2
- package/dist/platform/platform-ops.module.js +13 -5
- package/dist/platform/route-schemas.js +11 -3
- package/dist/roles/gateway-role.d.ts +3 -3
- package/dist/roles/gateway-role.js +4 -4
- package/dist/roles/gateway.module.d.ts +1 -1
- package/dist/roles/gateway.module.js +5 -5
- package/dist/roles/worker.module.js +1 -1
- package/dist/runtime/context/build.d.ts +1 -1
- package/dist/runtime/context/build.js +6 -6
- package/dist/runtime/context/compaction.js +1 -1
- package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
- package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
- package/dist/runtime/maintenance.d.ts +1 -1
- package/dist/sandbox/jobs.d.ts +13 -13
- package/dist/sandbox/jobs.js +20 -20
- package/dist/sandbox/leases.d.ts +9 -9
- package/dist/sandbox/leases.js +14 -14
- package/dist/sandbox/providers.d.ts +8 -8
- package/dist/sandbox/providers.js +8 -8
- package/dist/sandbox/sandbox.module.d.ts +1 -1
- package/dist/sandbox/sandbox.module.js +1 -1
- package/dist/sandbox/sandbox.service.d.ts +76 -76
- package/dist/sandbox/sandbox.service.js +230 -230
- package/dist/setup/kernel-checks.d.ts +91 -0
- package/dist/setup/kernel-checks.js +295 -0
- package/dist/setup/oauth-token-probe.d.ts +47 -0
- package/dist/setup/oauth-token-probe.js +108 -0
- package/dist/setup/redact-check.d.ts +18 -0
- package/dist/setup/redact-check.js +46 -0
- package/dist/setup/setup-check-registry.d.ts +86 -0
- package/dist/setup/setup-check-registry.js +75 -0
- package/dist/setup/setup-checks.controller.d.ts +28 -0
- package/dist/setup/setup-checks.controller.js +78 -0
- package/dist/setup/setup-checks.schemas.d.ts +38 -0
- package/dist/setup/setup-checks.schemas.js +43 -0
- package/dist/setup/setup-checks.service.d.ts +144 -0
- package/dist/setup/setup-checks.service.js +683 -0
- package/dist/setup/setup-guides.controller.d.ts +18 -0
- package/dist/setup/setup-guides.controller.js +48 -0
- package/dist/setup/setup-guides.schemas.d.ts +10 -0
- package/dist/setup/setup-guides.schemas.js +6 -0
- package/dist/setup/setup-guides.service.d.ts +126 -0
- package/dist/setup/setup-guides.service.js +315 -0
- package/dist/setup/setup.module.d.ts +8 -0
- package/dist/setup/setup.module.js +31 -0
- package/dist/tools/builtins/builtin-tools.d.ts +2 -2
- package/dist/tools/builtins/builtin-tools.js +5 -5
- package/dist/tools/builtins/platform.js +1 -1
- package/dist/tools/builtins/sandbox/bash.js +6 -6
- package/dist/tools/builtins/sandbox/common.d.ts +25 -25
- package/dist/tools/builtins/sandbox/common.js +51 -51
- package/dist/tools/builtins/sandbox/edit.js +2 -2
- package/dist/tools/builtins/sandbox/index.d.ts +1 -1
- package/dist/tools/builtins/sandbox/index.js +1 -1
- package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
- package/dist/tools/builtins/sandbox/task-output.js +10 -10
- package/dist/tools/builtins/sandbox/task-stop.js +2 -2
- package/dist/tools/builtins/sandbox/write.js +2 -2
- package/dist/tools/builtins/skill-load.d.ts +1 -1
- package/dist/tools/builtins/skill-load.js +2 -2
- package/dist/tools/connectors.controller.d.ts +28 -11
- package/dist/tools/connectors.controller.js +49 -14
- package/dist/tools/connectors.schemas.d.ts +4 -0
- package/dist/tools/connectors.schemas.js +4 -0
- package/dist/tools/connectors.service.d.ts +30 -2
- package/dist/tools/connectors.service.js +98 -3
- package/dist/tools/credentials.d.ts +20 -0
- package/dist/tools/credentials.js +90 -1
- package/dist/tools/oauth/tokens.d.ts +20 -0
- package/dist/tools/oauth/tokens.js +49 -24
- package/dist/tools/pipeline.js +4 -3
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/tools.module.js +3 -3
- package/dist/ui/admin-ui.controller.d.ts +56 -0
- package/dist/ui/admin-ui.controller.js +192 -0
- package/dist/ui/arrangement.d.ts +74 -0
- package/dist/ui/arrangement.js +98 -0
- package/dist/ui/embed-token.d.ts +2 -2
- package/dist/ui/embed-token.js +30 -5
- package/dist/ui/registry.d.ts +29 -14
- package/dist/ui/registry.js +31 -10
- package/dist/ui/slots.controller.d.ts +11 -0
- package/dist/ui/slots.controller.js +25 -0
- package/dist/ui/ui-stream.d.ts +20 -3
- package/dist/ui/ui-stream.js +25 -7
- package/dist/ui/ui.schemas.d.ts +66 -0
- package/dist/ui/ui.schemas.js +65 -0
- package/dist/ui/views.controller.d.ts +35 -49
- package/dist/ui/views.controller.js +48 -70
- package/dist/ui/views.d.ts +84 -18
- package/dist/ui/views.js +201 -38
- package/package.json +3 -3
- package/src/migrations/0105_devices_rename.sql +136 -0
- package/src/migrations/0106_setup_guides_v2.sql +10 -0
- package/dist/devices/device-auth.module.d.ts +0 -7
- package/dist/environments/conversation-environments.d.ts +0 -75
- package/dist/environments/dto.d.ts +0 -25
- package/dist/environments/dto.js +0 -12
- package/dist/environments/environments.controller.d.ts +0 -36
- package/dist/environments/environments.module.d.ts +0 -8
- package/dist/environments/environments.module.js +0 -31
- package/dist/environments/environments.schemas.d.ts +0 -3
- package/dist/environments/environments.schemas.js +0 -14
- package/dist/environments/label.d.ts +0 -11
- package/dist/platform/ops/environments.ops.d.ts +0 -26
- package/dist/platform/ops/environments.ops.js +0 -311
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
import type { SandboxRoots } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import type { ConversationEvent } from "../../conversations/events.js";
|
|
3
3
|
/**
|
|
4
|
-
* The `
|
|
4
|
+
* The `device_paths` event (environments spec §13.1, ruling R22): the first sandbox tool call
|
|
5
5
|
* of every conversation records the instance's roots (the defaults included), and a later call
|
|
6
6
|
* records them again whenever they differ from the conversation's latest recorded ones (a
|
|
7
7
|
* connected machine's real paths, a mode switch back to the defaults). Model-visible: rendered at
|
|
8
8
|
* its position as a system message; in the log, so it needs no `DriftReason`.
|
|
9
9
|
*/
|
|
10
|
-
/** The system line of an `
|
|
11
|
-
export declare function
|
|
10
|
+
/** The system line of an `device_paths` event (model-visible, English). */
|
|
11
|
+
export declare function devicePathsText(r: SandboxRoots): string;
|
|
12
12
|
/** Whether two sets of roots are the same paths. */
|
|
13
13
|
export declare const sameRoots: (a: SandboxRoots, b: SandboxRoots) => boolean;
|
|
14
14
|
/**
|
|
15
|
-
* The idempotency key of an `
|
|
15
|
+
* The idempotency key of an `device_paths` event for `r` that follows the conversation's
|
|
16
16
|
* event at `prevSeq` (0: none). Unique per change (A → B → A gets three events), while parallel
|
|
17
17
|
* calls that saw the same latest event write it once.
|
|
18
18
|
*/
|
|
19
|
-
export declare const
|
|
19
|
+
export declare const devicePathsIdemKey: (r: SandboxRoots, prevSeq: number) => string;
|
|
20
20
|
/**
|
|
21
|
-
* The `
|
|
21
|
+
* The `device_paths` event to append when a sandbox call holds an instance with `roots` and
|
|
22
22
|
* the conversation's latest such event is `latest`; null when nothing changed.
|
|
23
23
|
*/
|
|
24
|
-
export declare function
|
|
24
|
+
export declare function devicePathsChange(latest: {
|
|
25
25
|
seq: number;
|
|
26
26
|
payload: {
|
|
27
27
|
roots: SandboxRoots;
|
|
28
28
|
};
|
|
29
29
|
} | undefined, roots: SandboxRoots, runId: string | undefined): {
|
|
30
|
-
type: "
|
|
30
|
+
type: "device_paths";
|
|
31
31
|
runId?: string;
|
|
32
32
|
idemKey: string;
|
|
33
33
|
payload: {
|
|
34
34
|
roots: SandboxRoots;
|
|
35
35
|
};
|
|
36
36
|
} | null;
|
|
37
|
-
/** The latest `
|
|
38
|
-
export declare function
|
|
39
|
-
type: "
|
|
37
|
+
/** The latest `device_paths` event at or before `seq`; undefined without one. */
|
|
38
|
+
export declare function devicePathsAt(events: readonly ConversationEvent[], seq: number): Extract<ConversationEvent, {
|
|
39
|
+
type: "device_paths";
|
|
40
40
|
}> | undefined;
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
/**
|
|
3
|
-
* The `
|
|
3
|
+
* The `device_paths` event (environments spec §13.1, ruling R22): the first sandbox tool call
|
|
4
4
|
* of every conversation records the instance's roots (the defaults included), and a later call
|
|
5
5
|
* records them again whenever they differ from the conversation's latest recorded ones (a
|
|
6
6
|
* connected machine's real paths, a mode switch back to the defaults). Model-visible: rendered at
|
|
7
7
|
* its position as a system message; in the log, so it needs no `DriftReason`.
|
|
8
8
|
*/
|
|
9
|
-
/** The system line of an `
|
|
10
|
-
export function
|
|
11
|
-
return `This
|
|
9
|
+
/** The system line of an `device_paths` event (model-visible, English). */
|
|
10
|
+
export function devicePathsText(r) {
|
|
11
|
+
return `This device's directories: workspace ${r.workspace}, skills ${r.skills} (read only), temporary files ${r.tmp}. Use these paths in commands and tool calls.`;
|
|
12
12
|
}
|
|
13
13
|
/** Whether two sets of roots are the same paths. */
|
|
14
14
|
export const sameRoots = (a, b) => a.workspace === b.workspace && a.skills === b.skills && a.tmp === b.tmp;
|
|
15
15
|
/**
|
|
16
|
-
* The idempotency key of an `
|
|
16
|
+
* The idempotency key of an `device_paths` event for `r` that follows the conversation's
|
|
17
17
|
* event at `prevSeq` (0: none). Unique per change (A → B → A gets three events), while parallel
|
|
18
18
|
* calls that saw the same latest event write it once.
|
|
19
19
|
*/
|
|
20
|
-
export const
|
|
20
|
+
export const devicePathsIdemKey = (r, prevSeq) => `device_paths:${createHash("sha256")
|
|
21
21
|
.update(JSON.stringify([r.workspace, r.skills, r.tmp]))
|
|
22
22
|
.digest("hex")
|
|
23
23
|
.slice(0, 16)}:${prevSeq}`;
|
|
24
24
|
/**
|
|
25
|
-
* The `
|
|
25
|
+
* The `device_paths` event to append when a sandbox call holds an instance with `roots` and
|
|
26
26
|
* the conversation's latest such event is `latest`; null when nothing changed.
|
|
27
27
|
*/
|
|
28
|
-
export function
|
|
28
|
+
export function devicePathsChange(latest, roots, runId) {
|
|
29
29
|
if (latest && sameRoots(latest.payload.roots, roots))
|
|
30
30
|
return null;
|
|
31
31
|
return {
|
|
32
|
-
type: "
|
|
32
|
+
type: "device_paths",
|
|
33
33
|
...(runId !== undefined && { runId }),
|
|
34
|
-
idemKey:
|
|
34
|
+
idemKey: devicePathsIdemKey(roots, latest?.seq ?? 0),
|
|
35
35
|
payload: { roots: { workspace: roots.workspace, skills: roots.skills, tmp: roots.tmp } },
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
-
/** The latest `
|
|
39
|
-
export function
|
|
38
|
+
/** The latest `device_paths` event at or before `seq`; undefined without one. */
|
|
39
|
+
export function devicePathsAt(events, seq) {
|
|
40
40
|
let found;
|
|
41
41
|
for (const e of events) {
|
|
42
42
|
if (e.seq > seq)
|
|
43
43
|
break;
|
|
44
|
-
if (e.type === "
|
|
44
|
+
if (e.type === "device_paths")
|
|
45
45
|
found = e;
|
|
46
46
|
}
|
|
47
47
|
return found;
|
|
@@ -32,7 +32,7 @@ export declare class MaintenanceProcessor extends WorkerHost<Worker> {
|
|
|
32
32
|
private readonly scheduled;
|
|
33
33
|
private readonly log;
|
|
34
34
|
private readonly queue;
|
|
35
|
-
constructor(waits: Pick<Waits, "processTimeout">, sandbox: Pick<SandboxService, "
|
|
35
|
+
constructor(waits: Pick<Waits, "processTimeout">, sandbox: Pick<SandboxService, "destroyDevice" | "resetFileSystem">, drift: Pick<ToolDrift, "check">, directory: Pick<DirectorySync, "runSyncJob">, runs: Pick<RunQueue, "ensureRun">, ownedCleanup: Pick<OwnedPluginCleanup, "run">, scheduled: Pick<ScheduledRuns, "runNow">, log: Pick<KernelLogger, "error" | "warn">, queue: Pick<Queue, "removeJobScheduler">);
|
|
36
36
|
/**
|
|
37
37
|
* Removes the retired job schedulers (`RETIRED_SCHEDULER_IDS`, runtime/retired-schedulers.ts): every fixed-period
|
|
38
38
|
* maintenance job is a `@LockedCron` / `@LockedInterval` now. Idempotent; called once when a
|
package/dist/sandbox/jobs.d.ts
CHANGED
|
@@ -7,20 +7,20 @@ export declare const SANDBOX_SUSPEND_JOB = "sandbox-suspend-idle";
|
|
|
7
7
|
/** The inactivity destruction sweep (hourly, once per tick across replicas). */
|
|
8
8
|
export declare const SANDBOX_DESTROY_JOB = "sandbox-destroy-inactive";
|
|
9
9
|
/**
|
|
10
|
-
* One-off job: destroy a batch of
|
|
11
|
-
* deletion, offboarding; data `{
|
|
10
|
+
* One-off job: destroy a batch of devices now, instance and file system (device
|
|
11
|
+
* deletion, offboarding; data `{ deviceIds }`).
|
|
12
12
|
*/
|
|
13
13
|
export declare const SANDBOX_DESTROY_FOR_JOB = "sandbox-destroy-for";
|
|
14
14
|
/**
|
|
15
|
-
* One-off job: start
|
|
16
|
-
* `{
|
|
15
|
+
* One-off job: start a device over with empty files (`resetFileSystem`; data
|
|
16
|
+
* `{ deviceId }`, job id {@link resetFilesJobId}).
|
|
17
17
|
*/
|
|
18
18
|
export declare const SANDBOX_RESET_FILES_JOB = "sandbox-reset-files";
|
|
19
19
|
/**
|
|
20
|
-
* The deterministic id of
|
|
20
|
+
* The deterministic id of a device's reset job: a second request while one is waiting or
|
|
21
21
|
* running joins it (that reset still empties the files); once it ended, a new request is a new job.
|
|
22
22
|
*/
|
|
23
|
-
export declare const resetFilesJobId: (
|
|
23
|
+
export declare const resetFilesJobId: (deviceId: string) => string;
|
|
24
24
|
/**
|
|
25
25
|
* The producer of the sandbox maintenance jobs: {@link SANDBOX_DESTROY_FOR_JOB} (BullMQ's own job
|
|
26
26
|
* ids, as before: every enqueue is a new job, also after a batch failed all its attempts) and
|
|
@@ -30,16 +30,16 @@ export declare class SandboxJobs {
|
|
|
30
30
|
private readonly queue;
|
|
31
31
|
constructor(queue: Pick<Queue, "add">);
|
|
32
32
|
/**
|
|
33
|
-
* Enqueues the destruction of these
|
|
33
|
+
* Enqueues the destruction of these devices: a failed batch is retried whole (destroying
|
|
34
34
|
* one already destroyed does nothing).
|
|
35
35
|
*/
|
|
36
|
-
destroy(
|
|
36
|
+
destroy(deviceIds: string[]): Promise<void>;
|
|
37
37
|
/**
|
|
38
|
-
* Enqueues the reset of
|
|
38
|
+
* Enqueues the reset of a device's files (see {@link resetFilesJobId}): retried on failure
|
|
39
39
|
* (the exclusive lease not obtained in time, the provider failing); a job that failed all its
|
|
40
40
|
* attempts is removed, so the id never blocks a later request.
|
|
41
41
|
*/
|
|
42
|
-
resetFiles(
|
|
42
|
+
resetFiles(deviceId: string): Promise<void>;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* The worker side of {@link SANDBOX_RESET_FILES_JOB}: `resetFileSystem` under the exclusive lease;
|
|
@@ -47,14 +47,14 @@ export declare class SandboxJobs {
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function runSandboxResetFiles(sandbox: Pick<SandboxService, "resetFileSystem">, job: Pick<Job, "data">): Promise<void>;
|
|
49
49
|
/**
|
|
50
|
-
* The worker side of {@link SANDBOX_DESTROY_FOR_JOB}: `
|
|
50
|
+
* The worker side of {@link SANDBOX_DESTROY_FOR_JOB}: `destroyDevice` one by one; a failure is
|
|
51
51
|
* warned and fails the job (the whole batch is retried) after the others were destroyed.
|
|
52
52
|
*/
|
|
53
|
-
export declare function runSandboxDestroyFor(sandbox: Pick<SandboxService, "
|
|
53
|
+
export declare function runSandboxDestroyFor(sandbox: Pick<SandboxService, "destroyDevice">, log: Pick<KernelLogger, "warn">, job: Pick<Job, "data">): Promise<void>;
|
|
54
54
|
/**
|
|
55
55
|
* The sandbox sweeps (exactly once per tick across replicas): every minute the idle and overdue
|
|
56
56
|
* running instances are suspended, every hour the inactive instances are destroyed (files kept)
|
|
57
|
-
* and deleted
|
|
57
|
+
* and deleted devices, or those of deleted orgs, are destroyed with their files. Both do nothing without a sandbox provider. They replace the
|
|
58
58
|
* maintenance schedulers `sandbox-suspend-idle-every-minute` and `sandbox-destroy-inactive-hourly`
|
|
59
59
|
* (retired at worker start).
|
|
60
60
|
*/
|
package/dist/sandbox/jobs.js
CHANGED
|
@@ -19,20 +19,20 @@ export const SANDBOX_SUSPEND_JOB = "sandbox-suspend-idle";
|
|
|
19
19
|
/** The inactivity destruction sweep (hourly, once per tick across replicas). */
|
|
20
20
|
export const SANDBOX_DESTROY_JOB = "sandbox-destroy-inactive";
|
|
21
21
|
/**
|
|
22
|
-
* One-off job: destroy a batch of
|
|
23
|
-
* deletion, offboarding; data `{
|
|
22
|
+
* One-off job: destroy a batch of devices now, instance and file system (device
|
|
23
|
+
* deletion, offboarding; data `{ deviceIds }`).
|
|
24
24
|
*/
|
|
25
25
|
export const SANDBOX_DESTROY_FOR_JOB = "sandbox-destroy-for";
|
|
26
26
|
/**
|
|
27
|
-
* One-off job: start
|
|
28
|
-
* `{
|
|
27
|
+
* One-off job: start a device over with empty files (`resetFileSystem`; data
|
|
28
|
+
* `{ deviceId }`, job id {@link resetFilesJobId}).
|
|
29
29
|
*/
|
|
30
30
|
export const SANDBOX_RESET_FILES_JOB = "sandbox-reset-files";
|
|
31
31
|
/**
|
|
32
|
-
* The deterministic id of
|
|
32
|
+
* The deterministic id of a device's reset job: a second request while one is waiting or
|
|
33
33
|
* running joins it (that reset still empties the files); once it ended, a new request is a new job.
|
|
34
34
|
*/
|
|
35
|
-
export const resetFilesJobId = (
|
|
35
|
+
export const resetFilesJobId = (deviceId) => `${SANDBOX_RESET_FILES_JOB}-${deviceId}`;
|
|
36
36
|
/**
|
|
37
37
|
* The producer of the sandbox maintenance jobs: {@link SANDBOX_DESTROY_FOR_JOB} (BullMQ's own job
|
|
38
38
|
* ids, as before: every enqueue is a new job, also after a batch failed all its attempts) and
|
|
@@ -44,11 +44,11 @@ let SandboxJobs = class SandboxJobs {
|
|
|
44
44
|
this.queue = queue;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Enqueues the destruction of these
|
|
47
|
+
* Enqueues the destruction of these devices: a failed batch is retried whole (destroying
|
|
48
48
|
* one already destroyed does nothing).
|
|
49
49
|
*/
|
|
50
|
-
async destroy(
|
|
51
|
-
await this.queue.add(SANDBOX_DESTROY_FOR_JOB, {
|
|
50
|
+
async destroy(deviceIds) {
|
|
51
|
+
await this.queue.add(SANDBOX_DESTROY_FOR_JOB, { deviceIds }, {
|
|
52
52
|
attempts: 5,
|
|
53
53
|
backoff: { type: "exponential", delay: 30_000 },
|
|
54
54
|
removeOnComplete: true,
|
|
@@ -56,13 +56,13 @@ let SandboxJobs = class SandboxJobs {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Enqueues the reset of
|
|
59
|
+
* Enqueues the reset of a device's files (see {@link resetFilesJobId}): retried on failure
|
|
60
60
|
* (the exclusive lease not obtained in time, the provider failing); a job that failed all its
|
|
61
61
|
* attempts is removed, so the id never blocks a later request.
|
|
62
62
|
*/
|
|
63
|
-
async resetFiles(
|
|
64
|
-
await this.queue.add(SANDBOX_RESET_FILES_JOB, {
|
|
65
|
-
jobId: resetFilesJobId(
|
|
63
|
+
async resetFiles(deviceId) {
|
|
64
|
+
await this.queue.add(SANDBOX_RESET_FILES_JOB, { deviceId }, {
|
|
65
|
+
jobId: resetFilesJobId(deviceId),
|
|
66
66
|
attempts: 5,
|
|
67
67
|
backoff: { type: "exponential", delay: 30_000 },
|
|
68
68
|
removeOnComplete: true,
|
|
@@ -80,17 +80,17 @@ export { SandboxJobs };
|
|
|
80
80
|
* a failure fails the job (retried).
|
|
81
81
|
*/
|
|
82
82
|
export async function runSandboxResetFiles(sandbox, job) {
|
|
83
|
-
const id = job.data.
|
|
83
|
+
const id = job.data.deviceId;
|
|
84
84
|
if (typeof id !== "string")
|
|
85
85
|
return;
|
|
86
86
|
await sandbox.resetFileSystem(id);
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
|
-
* The worker side of {@link SANDBOX_DESTROY_FOR_JOB}: `
|
|
89
|
+
* The worker side of {@link SANDBOX_DESTROY_FOR_JOB}: `destroyDevice` one by one; a failure is
|
|
90
90
|
* warned and fails the job (the whole batch is retried) after the others were destroyed.
|
|
91
91
|
*/
|
|
92
92
|
export async function runSandboxDestroyFor(sandbox, log, job) {
|
|
93
|
-
const ids = job.data.
|
|
93
|
+
const ids = job.data.deviceIds;
|
|
94
94
|
if (!Array.isArray(ids))
|
|
95
95
|
return;
|
|
96
96
|
let failed = 0;
|
|
@@ -98,20 +98,20 @@ export async function runSandboxDestroyFor(sandbox, log, job) {
|
|
|
98
98
|
if (typeof id !== "string")
|
|
99
99
|
continue;
|
|
100
100
|
try {
|
|
101
|
-
await sandbox.
|
|
101
|
+
await sandbox.destroyDevice(id);
|
|
102
102
|
}
|
|
103
103
|
catch (err) {
|
|
104
104
|
failed++;
|
|
105
|
-
log.warn("cannot destroy
|
|
105
|
+
log.warn("cannot destroy device; will retry", { deviceId: id, err });
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
if (failed > 0)
|
|
109
|
-
throw new Error(`${failed} of ${ids.length}
|
|
109
|
+
throw new Error(`${failed} of ${ids.length} devices could not be destroyed`);
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
112
|
* The sandbox sweeps (exactly once per tick across replicas): every minute the idle and overdue
|
|
113
113
|
* running instances are suspended, every hour the inactive instances are destroyed (files kept)
|
|
114
|
-
* and deleted
|
|
114
|
+
* and deleted devices, or those of deleted orgs, are destroyed with their files. Both do nothing without a sandbox provider. They replace the
|
|
115
115
|
* maintenance schedulers `sandbox-suspend-idle-every-minute` and `sandbox-destroy-inactive-hourly`
|
|
116
116
|
* (retired at worker start).
|
|
117
117
|
*/
|
package/dist/sandbox/leases.d.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { LockService } from "../infra/lock/lock.service.js";
|
|
|
4
4
|
import type { KernelLogger } from "../log.js";
|
|
5
5
|
/**
|
|
6
6
|
* Shared and exclusive sandbox leases (sub-agents spec §10.3; environments spec §4.2): the Redis
|
|
7
|
-
* protocol that lets several holders (every conversation bound to the
|
|
8
|
-
* sub-agents) use one
|
|
7
|
+
* protocol that lets several holders (every conversation bound to the device, and their
|
|
8
|
+
* sub-agents) use one device's running instance concurrently (shared leases: commands, file
|
|
9
9
|
* reads and writes) while lifecycle changes (create, resume, rebuild, suspend, destroy, reset) stay
|
|
10
10
|
* alone (exclusive leases). Every `sandbox@2` provider runs commands concurrently and kills by tag,
|
|
11
|
-
* so there is no single-holder mode. Keys, env = the
|
|
11
|
+
* so there is no single-holder mode. Keys, env = the device id:
|
|
12
12
|
*
|
|
13
13
|
* - `capk:sandbox:<env>`: the lock key: an exclusive holder's token, or `shared` while shared
|
|
14
14
|
* leases exist.
|
|
@@ -28,17 +28,17 @@ import type { KernelLogger } from "../log.js";
|
|
|
28
28
|
* the renewal deadline (send time of the last successful renewal + 2/3 TTL): its `signal` aborts
|
|
29
29
|
* with {@link SandboxLockLostError}.
|
|
30
30
|
*/
|
|
31
|
-
/** Prefix of the lock key `capk:sandbox:<
|
|
31
|
+
/** Prefix of the lock key `capk:sandbox:<deviceId>`. */
|
|
32
32
|
export declare const SANDBOX_LOCK_PREFIX = "capk:sandbox:";
|
|
33
33
|
/** TTL of a lease (ms): renewed every TTL / 3 while held. */
|
|
34
34
|
export declare const SANDBOX_LOCK_TTL_MS = 60000;
|
|
35
|
-
/** The
|
|
35
|
+
/** The device's sandbox is busy: waited longer than `sandbox.lockWaitSeconds` (409). */
|
|
36
36
|
export declare const sandboxBusy: () => ApiError;
|
|
37
37
|
/** A lease was lost while held, or the record changed under it (generation mismatch). */
|
|
38
38
|
export declare class SandboxLockLostError extends Error {
|
|
39
39
|
/** `lock`: the lease was lost (renewal failed or none succeeded in time); `generation`: the record's fence changed. */
|
|
40
40
|
readonly reason: "lock" | "generation";
|
|
41
|
-
constructor(
|
|
41
|
+
constructor(deviceId: string, reason?: "lock" | "generation");
|
|
42
42
|
}
|
|
43
43
|
/** Another holder kept writing the same file longer than the path lease wait (model-visible text). */
|
|
44
44
|
export declare class SandboxPathBusyError extends Error {
|
|
@@ -49,7 +49,7 @@ export type LeaseKind = "shared" | "exclusive";
|
|
|
49
49
|
export interface SandboxLease {
|
|
50
50
|
readonly kind: LeaseKind;
|
|
51
51
|
readonly token: string;
|
|
52
|
-
readonly
|
|
52
|
+
readonly deviceId: string;
|
|
53
53
|
/** Aborts with {@link SandboxLockLostError} when the lease is lost. */
|
|
54
54
|
readonly signal: AbortSignal;
|
|
55
55
|
/** Renews once now; false when the lease is lost (the signal then aborts). */
|
|
@@ -131,9 +131,9 @@ export declare class SandboxLeases {
|
|
|
131
131
|
* (it should then {@link clearIntent}).
|
|
132
132
|
*/
|
|
133
133
|
tryShared(env: string, cap: number, token?: string): Promise<SandboxLease | null>;
|
|
134
|
-
/** Deletes the
|
|
134
|
+
/** Deletes the device's intent when it is `token`'s. */
|
|
135
135
|
clearIntent(env: string, token: string): Promise<void>;
|
|
136
|
-
/** Live shared leases of the
|
|
136
|
+
/** Live shared leases of the device. */
|
|
137
137
|
sharedCount(env: string): Promise<number>;
|
|
138
138
|
/**
|
|
139
139
|
* Records (or refreshes) a holder that may run commands (before its provider calls); `ttlMs`
|
package/dist/sandbox/leases.js
CHANGED
|
@@ -15,11 +15,11 @@ import { redisClockScript, sharedLeaseReadScript, } from "../infra/lock/shared-l
|
|
|
15
15
|
import { KERNEL_LOGGER, REDIS } from "../infra/tokens.js";
|
|
16
16
|
/**
|
|
17
17
|
* Shared and exclusive sandbox leases (sub-agents spec §10.3; environments spec §4.2): the Redis
|
|
18
|
-
* protocol that lets several holders (every conversation bound to the
|
|
19
|
-
* sub-agents) use one
|
|
18
|
+
* protocol that lets several holders (every conversation bound to the device, and their
|
|
19
|
+
* sub-agents) use one device's running instance concurrently (shared leases: commands, file
|
|
20
20
|
* reads and writes) while lifecycle changes (create, resume, rebuild, suspend, destroy, reset) stay
|
|
21
21
|
* alone (exclusive leases). Every `sandbox@2` provider runs commands concurrently and kills by tag,
|
|
22
|
-
* so there is no single-holder mode. Keys, env = the
|
|
22
|
+
* so there is no single-holder mode. Keys, env = the device id:
|
|
23
23
|
*
|
|
24
24
|
* - `capk:sandbox:<env>`: the lock key: an exclusive holder's token, or `shared` while shared
|
|
25
25
|
* leases exist.
|
|
@@ -39,7 +39,7 @@ import { KERNEL_LOGGER, REDIS } from "../infra/tokens.js";
|
|
|
39
39
|
* the renewal deadline (send time of the last successful renewal + 2/3 TTL): its `signal` aborts
|
|
40
40
|
* with {@link SandboxLockLostError}.
|
|
41
41
|
*/
|
|
42
|
-
/** Prefix of the lock key `capk:sandbox:<
|
|
42
|
+
/** Prefix of the lock key `capk:sandbox:<deviceId>`. */
|
|
43
43
|
export const SANDBOX_LOCK_PREFIX = "capk:sandbox:";
|
|
44
44
|
/** TTL of a lease (ms): renewed every TTL / 3 while held. */
|
|
45
45
|
export const SANDBOX_LOCK_TTL_MS = 60_000;
|
|
@@ -51,16 +51,16 @@ const PATH_PREFIX = "capk:sandbox-path:";
|
|
|
51
51
|
const PATH_LEASE_TTL_MS = 30_000;
|
|
52
52
|
/** Shortest life of an exclusive waiter's intent (ms): outlasts event-loop lag between polls. */
|
|
53
53
|
const INTENT_TTL_FLOOR_MS = 2000;
|
|
54
|
-
/** The
|
|
55
|
-
export const sandboxBusy = () => new ApiError("sandbox.busy", "The sandbox of this
|
|
54
|
+
/** The device's sandbox is busy: waited longer than `sandbox.lockWaitSeconds` (409). */
|
|
55
|
+
export const sandboxBusy = () => new ApiError("sandbox.busy", "The sandbox of this device is busy with other commands; wait for them to finish and try again");
|
|
56
56
|
/** A lease was lost while held, or the record changed under it (generation mismatch). */
|
|
57
57
|
export class SandboxLockLostError extends Error {
|
|
58
58
|
/** `lock`: the lease was lost (renewal failed or none succeeded in time); `generation`: the record's fence changed. */
|
|
59
59
|
reason;
|
|
60
|
-
constructor(
|
|
60
|
+
constructor(deviceId, reason = "lock") {
|
|
61
61
|
super(reason === "lock"
|
|
62
|
-
? `sandbox lock lost for
|
|
63
|
-
: `sandbox state of
|
|
62
|
+
? `sandbox lock lost for device ${deviceId}`
|
|
63
|
+
: `sandbox state of device ${deviceId} changed concurrently (generation mismatch)`);
|
|
64
64
|
this.name = "SandboxLockLostError";
|
|
65
65
|
this.reason = reason;
|
|
66
66
|
}
|
|
@@ -208,7 +208,7 @@ let SandboxLeases = class SandboxLeases {
|
|
|
208
208
|
}
|
|
209
209
|
catch (e) {
|
|
210
210
|
if (o.intent) {
|
|
211
|
-
await this.clearIntent(env, token).catch((err) => this.log.warn("cannot clear sandbox intent", {
|
|
211
|
+
await this.clearIntent(env, token).catch((err) => this.log.warn("cannot clear sandbox intent", { deviceId: env, err }));
|
|
212
212
|
}
|
|
213
213
|
throw e;
|
|
214
214
|
}
|
|
@@ -231,11 +231,11 @@ let SandboxLeases = class SandboxLeases {
|
|
|
231
231
|
const h = await this.locks.tryShared(this.keys(env), token, cap, this.ttlMs);
|
|
232
232
|
return h ? this.held(env, h) : null;
|
|
233
233
|
}
|
|
234
|
-
/** Deletes the
|
|
234
|
+
/** Deletes the device's intent when it is `token`'s. */
|
|
235
235
|
async clearIntent(env, token) {
|
|
236
236
|
await this.locks.releaseIf(this.keys(env).intent, token);
|
|
237
237
|
}
|
|
238
|
-
/** Live shared leases of the
|
|
238
|
+
/** Live shared leases of the device. */
|
|
239
239
|
sharedCount(env) {
|
|
240
240
|
return this.locks.sharedCount(this.keys(env));
|
|
241
241
|
}
|
|
@@ -291,7 +291,7 @@ let SandboxLeases = class SandboxLeases {
|
|
|
291
291
|
return {
|
|
292
292
|
kind,
|
|
293
293
|
token: h.token,
|
|
294
|
-
|
|
294
|
+
deviceId: env,
|
|
295
295
|
signal,
|
|
296
296
|
// a Redis error is warned, not thrown: the deadline decides whether the lease is lost
|
|
297
297
|
renew: async () => {
|
|
@@ -301,7 +301,7 @@ let SandboxLeases = class SandboxLeases {
|
|
|
301
301
|
return await h.renew();
|
|
302
302
|
}
|
|
303
303
|
catch (err) {
|
|
304
|
-
this.log.warn("sandbox lease renew failed", {
|
|
304
|
+
this.log.warn("sandbox lease renew failed", { deviceId: env, err });
|
|
305
305
|
return !signal.aborted;
|
|
306
306
|
}
|
|
307
307
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SandboxProvider } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
3
|
-
/** The kernel-internal provider of connected machines (
|
|
4
|
-
export declare const
|
|
3
|
+
/** The kernel-internal provider of connected machines (local devices). */
|
|
4
|
+
export declare const LOCAL_PROVIDER = "@local";
|
|
5
5
|
/**
|
|
6
6
|
* A kernel-internal provider name: it starts with `@`, which no extension name can
|
|
7
7
|
* (`EXTENSION_NAME_RE`), so it never collides with a loaded `sandbox@2` plugin.
|
|
@@ -15,7 +15,7 @@ export interface SandboxProviderEntry {
|
|
|
15
15
|
/**
|
|
16
16
|
* The sandbox providers of this process. The cloud provider is the loaded `sandbox@2` extension,
|
|
17
17
|
* read from the {@link ExtensionRegistry} at every call (providers are ready only after the
|
|
18
|
-
* extension load, and change with installs). Kernel-internal providers (`@
|
|
18
|
+
* extension load, and change with installs). Kernel-internal providers (`@local`) are registered
|
|
19
19
|
* by their module on init, in every replica: they are code, not shared state.
|
|
20
20
|
*
|
|
21
21
|
* Every `sandbox@2` extension is handed out guarded: a network-level failure to reach it is
|
|
@@ -38,9 +38,9 @@ export declare class SandboxProviders {
|
|
|
38
38
|
forName(name: string): SandboxProviderEntry | undefined;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* The provider
|
|
42
|
-
* (`@
|
|
43
|
-
* is a cloud
|
|
44
|
-
* refused by the sandbox service, `
|
|
41
|
+
* The provider a device works with, from its `devices.provider`: an internal one
|
|
42
|
+
* (`@local`) by that name only, never falling back to the cloud provider; any other device
|
|
43
|
+
* is a cloud device and uses the current cloud provider (files kept by another provider are
|
|
44
|
+
* refused by the sandbox service, `device.unavailable`).
|
|
45
45
|
*/
|
|
46
|
-
export declare function
|
|
46
|
+
export declare function providerForDevice(providers: Pick<SandboxProviders, "cloud" | "forName">, provider: string | null): SandboxProviderEntry | undefined;
|
|
@@ -11,8 +11,8 @@ import { SANDBOX_EXTENSION_POINT } from "@capybara-hq/plugin-sdk";
|
|
|
11
11
|
import { Inject, Injectable } from "@nestjs/common";
|
|
12
12
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
13
13
|
import { guardProviderConnection } from "./unreachable.js";
|
|
14
|
-
/** The kernel-internal provider of connected machines (
|
|
15
|
-
export const
|
|
14
|
+
/** The kernel-internal provider of connected machines (local devices). */
|
|
15
|
+
export const LOCAL_PROVIDER = "@local";
|
|
16
16
|
/**
|
|
17
17
|
* A kernel-internal provider name: it starts with `@`, which no extension name can
|
|
18
18
|
* (`EXTENSION_NAME_RE`), so it never collides with a loaded `sandbox@2` plugin.
|
|
@@ -21,7 +21,7 @@ export const isInternalProvider = (name) => name.startsWith("@");
|
|
|
21
21
|
/**
|
|
22
22
|
* The sandbox providers of this process. The cloud provider is the loaded `sandbox@2` extension,
|
|
23
23
|
* read from the {@link ExtensionRegistry} at every call (providers are ready only after the
|
|
24
|
-
* extension load, and change with installs). Kernel-internal providers (`@
|
|
24
|
+
* extension load, and change with installs). Kernel-internal providers (`@local`) are registered
|
|
25
25
|
* by their module on init, in every replica: they are code, not shared state.
|
|
26
26
|
*
|
|
27
27
|
* Every `sandbox@2` extension is handed out guarded: a network-level failure to reach it is
|
|
@@ -71,12 +71,12 @@ SandboxProviders = __decorate([
|
|
|
71
71
|
], SandboxProviders);
|
|
72
72
|
export { SandboxProviders };
|
|
73
73
|
/**
|
|
74
|
-
* The provider
|
|
75
|
-
* (`@
|
|
76
|
-
* is a cloud
|
|
77
|
-
* refused by the sandbox service, `
|
|
74
|
+
* The provider a device works with, from its `devices.provider`: an internal one
|
|
75
|
+
* (`@local`) by that name only, never falling back to the cloud provider; any other device
|
|
76
|
+
* is a cloud device and uses the current cloud provider (files kept by another provider are
|
|
77
|
+
* refused by the sandbox service, `device.unavailable`).
|
|
78
78
|
*/
|
|
79
|
-
export function
|
|
79
|
+
export function providerForDevice(providers, provider) {
|
|
80
80
|
if (provider !== null && isInternalProvider(provider))
|
|
81
81
|
return providers.forName(provider);
|
|
82
82
|
return providers.cloud();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sandboxes: the one {@link SandboxService} (
|
|
2
|
+
* Sandboxes: the one {@link SandboxService} (a device's file system and instance over the
|
|
3
3
|
* `sandbox@2` provider, with the shared / exclusive leases of {@link SandboxLeases}) and the
|
|
4
4
|
* producer of the
|
|
5
5
|
* one-off `sandbox-destroy-for` jobs (`MaintenanceProcessor` consumes them). The sweeps
|
|
@@ -14,7 +14,7 @@ import { SandboxLeases } from "./leases.js";
|
|
|
14
14
|
import { SandboxProviders } from "./providers.js";
|
|
15
15
|
import { SandboxService } from "./sandbox.service.js";
|
|
16
16
|
/**
|
|
17
|
-
* Sandboxes: the one {@link SandboxService} (
|
|
17
|
+
* Sandboxes: the one {@link SandboxService} (a device's file system and instance over the
|
|
18
18
|
* `sandbox@2` provider, with the shared / exclusive leases of {@link SandboxLeases}) and the
|
|
19
19
|
* producer of the
|
|
20
20
|
* one-off `sandbox-destroy-for` jobs (`MaintenanceProcessor` consumes them). The sweeps
|