@capybara-hq/kernel 0.1.0-rc.12 → 0.1.0-rc.13
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/marketplaces.service.d.ts +1 -1
- package/dist/channels/channels.module.js +2 -2
- 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/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 +10 -1
- package/dist/ctx/create-ctx.js +86 -25
- package/dist/db/kernel-schema.d.ts +26 -23
- 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 +25 -25
- package/dist/errors.js +25 -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/host.d.ts +13 -2
- package/dist/extensions/host.js +24 -3
- package/dist/extensions/instance.d.ts +12 -1
- package/dist/extensions/instance.js +13 -0
- package/dist/extensions/permission-view.d.ts +10 -1
- package/dist/files/previewers.d.ts +1 -1
- package/dist/files/previewers.js +1 -1
- package/dist/http/api.module.js +10 -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/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/platform/exclusions.js +38 -3
- package/dist/platform/operation.js +6 -2
- package/dist/platform/ops/admin.ops.js +8 -2
- 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/ui.ops.d.ts +8 -0
- package/dist/platform/ops/ui.ops.js +41 -0
- package/dist/platform/platform-ops.module.d.ts +3 -2
- package/dist/platform/platform-ops.module.js +8 -5
- package/dist/platform/route-schemas.js +6 -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/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/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/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
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
|
|
@@ -3,7 +3,7 @@ import type { Redis } from "ioredis";
|
|
|
3
3
|
import { type Selectable } from "kysely";
|
|
4
4
|
import { BackgroundTaskStore } from "../background/store.js";
|
|
5
5
|
import { type KernelConfig } from "../config/schema.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { DeviceInstancesTable } from "../db/kernel-schema.js";
|
|
7
7
|
import { ApiError } from "../errors.js";
|
|
8
8
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
9
9
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
@@ -16,13 +16,13 @@ export interface SandboxUseInfo {
|
|
|
16
16
|
/** This call created the instance (first use, or a rebuild). */
|
|
17
17
|
fresh: boolean;
|
|
18
18
|
/**
|
|
19
|
-
* The
|
|
19
|
+
* The device had an instance before that is no longer there (destroyed after inactivity,
|
|
20
20
|
* gone at the provider, or rebuilt by another holder since this holder last used it): this is a
|
|
21
21
|
* new instance on the kept files, so earlier processes are gone.
|
|
22
22
|
*/
|
|
23
23
|
restarted: boolean;
|
|
24
24
|
/**
|
|
25
|
-
* The
|
|
25
|
+
* The device's files were reset since this holder last used it (on request, or after they
|
|
26
26
|
* were lost): earlier files are gone too. Set only when true; `restarted` is then false.
|
|
27
27
|
*/
|
|
28
28
|
filesReset?: true;
|
|
@@ -35,17 +35,17 @@ export interface SandboxUseInfo {
|
|
|
35
35
|
/** Who uses the sandbox in {@link SandboxService.withSandbox}. */
|
|
36
36
|
export interface SandboxUseContext {
|
|
37
37
|
orgId: string;
|
|
38
|
-
|
|
38
|
+
deviceId: string;
|
|
39
39
|
/** The agent conversation using it (a sub-agent's own for a child): what it last saw is tracked. */
|
|
40
40
|
holderConversationId: string;
|
|
41
41
|
/** Passed with every `exec` (audit and attribution). */
|
|
42
42
|
actor: SandboxActor;
|
|
43
43
|
}
|
|
44
44
|
export type { SandboxProviderEntry } from "./providers.js";
|
|
45
|
-
type Row = Selectable<
|
|
45
|
+
type Row = Selectable<DeviceInstancesTable>;
|
|
46
46
|
type ExecArgs = Parameters<SandboxProvider["exec"]>[1];
|
|
47
47
|
/**
|
|
48
|
-
* One instance of
|
|
48
|
+
* One instance of a device: its handle and the row's `created_at`, which the fenced write
|
|
49
49
|
* after every `create` sets. The handle alone is not enough: sandbox-docker's handle is the
|
|
50
50
|
* instance name, the same after a rebuild (spec §10.10).
|
|
51
51
|
*/
|
|
@@ -80,20 +80,20 @@ export type IfRunningResult<T> = {
|
|
|
80
80
|
kind: "not_running";
|
|
81
81
|
status: Row["status"] | "gone";
|
|
82
82
|
}
|
|
83
|
-
/** The
|
|
83
|
+
/** The device now records another instance (a rebuild). */
|
|
84
84
|
| {
|
|
85
85
|
kind: "other_instance";
|
|
86
86
|
};
|
|
87
|
-
/** The provider-side name of
|
|
88
|
-
export declare const
|
|
89
|
-
/** The
|
|
90
|
-
export declare const
|
|
87
|
+
/** The provider-side name of a device's file system and instance. */
|
|
88
|
+
export declare const deviceResourceName: (deviceId: string) => string;
|
|
89
|
+
/** The device is missing, deleted, or not in the caller's org (404; ids cannot be probed). */
|
|
90
|
+
export declare const deviceNotFound: () => ApiError;
|
|
91
91
|
/**
|
|
92
|
-
* The
|
|
93
|
-
* connected machine (`
|
|
94
|
-
* owner's: `capybara-device logout`, then `login` into the
|
|
92
|
+
* The device's file system is gone at the provider (409); never replaced silently. On a
|
|
93
|
+
* connected machine (`local`, details `[{ source: "local" }]`) the directory is the machine
|
|
94
|
+
* owner's: `capybara-device logout`, then `login` into the device, recreates it (ruling R24).
|
|
95
95
|
*/
|
|
96
|
-
export declare const
|
|
96
|
+
export declare const deviceFilesLost: (local?: boolean) => ApiError;
|
|
97
97
|
/**
|
|
98
98
|
* The row still records the instance `gone` (same handle and same `created_at`). Handles compare
|
|
99
99
|
* canonically: a jsonb round trip reorders a multi-key handle's keys (final review m9).
|
|
@@ -115,19 +115,19 @@ export declare function sandboxConfigWarnings(cfg: Pick<KernelConfig, "runtime"
|
|
|
115
115
|
/** No sandbox provider (503). */
|
|
116
116
|
export declare const sandboxUnavailable: () => ApiError;
|
|
117
117
|
/**
|
|
118
|
-
* The kernel's sandbox service over the `sandbox@2` provider, keyed by **
|
|
119
|
-
* 2026-11-07-environments-design §4.2, §5.1): one file system kept until the
|
|
118
|
+
* The kernel's sandbox service over the `sandbox@2` provider, keyed by **device** (spec
|
|
119
|
+
* 2026-11-07-environments-design §4.2, §5.1): one file system kept until the device is
|
|
120
120
|
* deleted, plus one instance attached to it that comes and goes; all conversations bound to the
|
|
121
|
-
*
|
|
121
|
+
* device (and their sub-agents) share both.
|
|
122
122
|
*
|
|
123
123
|
* - **Lazy creation**: the first {@link withSandbox} creates the file system
|
|
124
|
-
* (`createFileSystem`, name `cap-
|
|
125
|
-
* in `
|
|
126
|
-
* `fs_status` becomes `lost` and uses fail with `
|
|
124
|
+
* (`createFileSystem`, name `cap-device-<deviceId>`) and then the instance on it; state lives
|
|
125
|
+
* in `device_instances`. A file system gone at the provider is never replaced silently:
|
|
126
|
+
* `fs_status` becomes `lost` and uses fail with `device.files_lost` until
|
|
127
127
|
* {@link resetFileSystem}.
|
|
128
|
-
* - **Leases** (phase C, spec §10, {@link SandboxLeases}), keyed by
|
|
128
|
+
* - **Leases** (phase C, spec §10, {@link SandboxLeases}), keyed by device id: using an
|
|
129
129
|
* instance recorded `running` with the current provider takes a **shared** lease, so up to
|
|
130
|
-
* `sandbox.maxConcurrentCommands` holders (all sessions of the
|
|
130
|
+
* `sandbox.maxConcurrentCommands` holders (all sessions of the device) run at once. Every
|
|
131
131
|
* lifecycle change (create, resume, rebuild, suspend, destroy, reset) takes the **exclusive**
|
|
132
132
|
* lease, alone; a caller that needs one on the use path sets the intent so new shared leases wait
|
|
133
133
|
* for it, and downgrades to a shared lease to run its own command once the instance runs.
|
|
@@ -140,9 +140,9 @@ export declare const sandboxUnavailable: () => ApiError;
|
|
|
140
140
|
* provider calls.
|
|
141
141
|
* - **Suspension and destruction**: the sweeps (`SandboxSweepJobs`, crons) call
|
|
142
142
|
* {@link suspendIdle} / {@link destroyInactive}; they try the exclusive lease once and skip an
|
|
143
|
-
*
|
|
143
|
+
* device with any holder; one past `maxRunningMinutes` gets the intent for a short window
|
|
144
144
|
* (about a second) so the suspension can get in when its commands end. Inactivity destroys only
|
|
145
|
-
* the instance (files kept); a deleted
|
|
145
|
+
* the instance (files kept); a deleted device or org loses its files too.
|
|
146
146
|
* - **Transparent recovery**: a suspended instance is resumed on next use; when `resume` returns
|
|
147
147
|
* `gone`, the instance was destroyed, or `fn` throws `SandboxGoneError` (retried once), a new
|
|
148
148
|
* instance is created on the kept files and `restarted` is true. Several holders hitting `gone`
|
|
@@ -150,7 +150,7 @@ export declare const sandboxUnavailable: () => ApiError;
|
|
|
150
150
|
* - **Takeover** (spec §10.5; environments spec §4.2): every holder records itself in
|
|
151
151
|
* `capk:sandbox-holders:<env>` (again before each `exec`) and its commands carry its lease token
|
|
152
152
|
* as `tag`. An acquirer that finds a record without a live lease (a crashed holder) kills only
|
|
153
|
-
* that holder's commands (`killTagged`): other conversations of the
|
|
153
|
+
* that holder's commands (`killTagged`): other conversations of the device may be running
|
|
154
154
|
* commands. `killAll` runs only under the exclusive lease, before the downgrade, on an instance
|
|
155
155
|
* this holder just resumed from `suspended` (nobody else can hold it; a provider that keeps
|
|
156
156
|
* memory across a pause brings old commands back); it also covers crashed holders' records,
|
|
@@ -160,16 +160,16 @@ export declare const sandboxUnavailable: () => ApiError;
|
|
|
160
160
|
* row's `created_at` (set by the fenced write after each `create`); the handle alone is the same
|
|
161
161
|
* after a rebuild on providers whose handle is the instance name (sandbox-docker).
|
|
162
162
|
*
|
|
163
|
-
* - **Provider per
|
|
164
|
-
* the
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* destroyed for inactivity; a deleted `@
|
|
163
|
+
* - **Provider per device** (environments spec §6): each call resolves the provider from
|
|
164
|
+
* the device's `devices.provider` ({@link providerForDevice}): a `device`
|
|
165
|
+
* device runs on the kernel-internal `@local` provider (never the cloud one), a cloud
|
|
166
|
+
* device on the loaded `sandbox@2` extension. A `@local` instance is never suspended or
|
|
167
|
+
* destroyed for inactivity; a deleted `@local` device (or one of a deleted org) is
|
|
168
168
|
* destroyed by the sweep like any other.
|
|
169
169
|
*
|
|
170
|
-
* Files kept by another provider than the current one make the
|
|
171
|
-
* (`
|
|
172
|
-
* provider is loaded ({@link SandboxProviders.forName}). Without the
|
|
170
|
+
* Files kept by another provider than the current one make the device unusable
|
|
171
|
+
* (`device.unavailable`) until that provider is back; deleting it still works while that
|
|
172
|
+
* provider is loaded ({@link SandboxProviders.forName}). Without the device's provider
|
|
173
173
|
* {@link availableFor} is false and uses throw `sandbox.unavailable` (503). No in-process state:
|
|
174
174
|
* replicas share it through PG and Redis.
|
|
175
175
|
*/
|
|
@@ -195,48 +195,48 @@ export declare class SandboxService {
|
|
|
195
195
|
private get pollMs();
|
|
196
196
|
/**
|
|
197
197
|
* Whether there is a cloud sandbox provider (a loaded `sandbox@2` extension). For gates that have
|
|
198
|
-
* no
|
|
198
|
+
* no device yet (tool listing, skill files); a call on a device asks
|
|
199
199
|
* {@link availableFor}.
|
|
200
200
|
*/
|
|
201
201
|
get cloudAvailable(): boolean;
|
|
202
|
-
/** Whether the
|
|
203
|
-
availableFor(
|
|
202
|
+
/** Whether the device's provider is there (`@local` registered, or a cloud provider). */
|
|
203
|
+
availableFor(deviceId: string): Promise<boolean>;
|
|
204
204
|
/**
|
|
205
|
-
* The provider the
|
|
206
|
-
* a missing row (or one of another org, with `orgId`) reads as a cloud
|
|
205
|
+
* The provider the device works with, read from its row ({@link providerForDevice});
|
|
206
|
+
* a missing row (or one of another org, with `orgId`) reads as a cloud device, whose use
|
|
207
207
|
* then fails as not found.
|
|
208
208
|
*/
|
|
209
209
|
private providerOf;
|
|
210
210
|
/** {@link providerOf}, or `sandbox.unavailable` (503) without it. */
|
|
211
211
|
private require;
|
|
212
|
-
/** Concurrent holders of one
|
|
212
|
+
/** Concurrent holders of one device (`sandbox.maxConcurrentCommands`, read at every use). */
|
|
213
213
|
private get cap();
|
|
214
214
|
/**
|
|
215
215
|
* The org's effective sandbox limits (spec §8.4): the deployment's `sandbox.limits`, egress
|
|
216
216
|
* narrowed by the org setting `sandboxEgress` (Ruling M19), cpu / memory per the super admin's
|
|
217
|
-
* org override (C19 / Ruling M16). Instances are created with them; phase 1
|
|
217
|
+
* org override (C19 / Ruling M16). Instances are created with them; phase 1 devices use
|
|
218
218
|
* them unchanged.
|
|
219
219
|
*/
|
|
220
220
|
orgLimits(orgId: string): Promise<SandboxLimits>;
|
|
221
221
|
/**
|
|
222
|
-
* The
|
|
222
|
+
* The device's instance state as shown to people (read only, no lease): `running` /
|
|
223
223
|
* `suspended` and the last use. No instance, a destroyed one, or one stuck in `creating` (being
|
|
224
224
|
* created, or a failed create the next use retries) is null.
|
|
225
225
|
*/
|
|
226
|
-
status(orgId: string,
|
|
226
|
+
status(orgId: string, deviceId: string): Promise<{
|
|
227
227
|
status: "running" | "suspended";
|
|
228
228
|
lastUsedAt: Date;
|
|
229
229
|
} | null>;
|
|
230
230
|
/**
|
|
231
|
-
* The instance the
|
|
231
|
+
* The instance the device records now (its `created_at`), while it has one that runs or is
|
|
232
232
|
* suspended; null otherwise. Read without a lease: a caller inside `withSandbox` reads the
|
|
233
233
|
* instance its own lease keeps.
|
|
234
234
|
*/
|
|
235
|
-
currentInstance(
|
|
235
|
+
currentInstance(deviceId: string): Promise<{
|
|
236
236
|
createdAt: Date;
|
|
237
237
|
} | null>;
|
|
238
238
|
/**
|
|
239
|
-
* Runs `fn` on the
|
|
239
|
+
* Runs `fn` on the device's instance only while it runs the instance created at
|
|
240
240
|
* `instance.createdAt` (background tasks, spec 2026-11-05-background-bash-design §4.3). It never
|
|
241
241
|
* creates, resumes or rebuilds one: an instance that is missing, suspended, being created or
|
|
242
242
|
* destroyed (or recorded with another provider) is `not_running`, one that records another
|
|
@@ -247,17 +247,17 @@ export declare class SandboxService {
|
|
|
247
247
|
* to `fn` aborts with `signal` or when the lease is lost. Errors of `fn` (`SandboxGoneError`
|
|
248
248
|
* too) are thrown as they are.
|
|
249
249
|
*/
|
|
250
|
-
ifRunning<T>(
|
|
250
|
+
ifRunning<T>(deviceId: string, instance: {
|
|
251
251
|
createdAt: Date;
|
|
252
252
|
}, fn: (p: TaggedProvider, h: SandboxHandle, signal: AbortSignal) => Promise<T>, signal?: AbortSignal): Promise<IfRunningResult<T>>;
|
|
253
253
|
/**
|
|
254
|
-
* A short lease on one path of the
|
|
254
|
+
* A short lease on one path of the device around the kernel's own read-modify-write of
|
|
255
255
|
* that file (spec §10.4); waits up to 30 s, then throws `SandboxPathBusyError`. Its `signal`
|
|
256
256
|
* aborts when a renewal finds it lost.
|
|
257
257
|
*/
|
|
258
|
-
pathLease(
|
|
258
|
+
pathLease(deviceId: string, path: string, signal: AbortSignal): Promise<SandboxPathLease>;
|
|
259
259
|
/**
|
|
260
|
-
* Runs `fn` on the
|
|
260
|
+
* Runs `fn` on the device's instance: take a lease → make sure the instance runs (file
|
|
261
261
|
* system, create / resume / rebuild, under the exclusive lease) → `fn` under a shared lease →
|
|
262
262
|
* update `last_used_at` → release.
|
|
263
263
|
* - Waiting longer than `sandbox.lockWaitSeconds` throws `sandbox.busy` (409); `signal` aborts
|
|
@@ -268,7 +268,7 @@ export declare class SandboxService {
|
|
|
268
268
|
* - When `fn` throws `SandboxGoneError` (the instance is gone) the instance is rebuilt on the
|
|
269
269
|
* kept files (or the one another holder rebuilt is taken) and `fn` runs once more with
|
|
270
270
|
* `restarted: true`; a second `gone` is thrown. Other errors are thrown as they are.
|
|
271
|
-
* - Lost files throw `
|
|
271
|
+
* - Lost files throw `device.files_lost` (409), also when `fn` throws
|
|
272
272
|
* `FileSystemGoneError` (the files are then recorded lost, ruling R24).
|
|
273
273
|
* - When `ctx.holderConversationId` last used another instance (another holder rebuilt it
|
|
274
274
|
* meanwhile), `info.restarted` is true, so it learns its processes are gone (final review m5).
|
|
@@ -278,7 +278,7 @@ export declare class SandboxService {
|
|
|
278
278
|
* Ruling R24: an operation on the held instance `e` found its file system gone. Records
|
|
279
279
|
* `fs_status = 'lost'` while the row still records that instance on its file system (the
|
|
280
280
|
* instance handle stays, so a reset still destroys it), moving the fence on, and returns
|
|
281
|
-
* `
|
|
281
|
+
* `device.files_lost` to throw. Uses then fail until the files are reset (a connected
|
|
282
282
|
* machine: until a new login, which resets the row). A failed write only logs.
|
|
283
283
|
*/
|
|
284
284
|
private filesGone;
|
|
@@ -288,7 +288,7 @@ export declare class SandboxService {
|
|
|
288
288
|
* holder last used another instance under the same reset count `e` is marked restarted (files
|
|
289
289
|
* kept); under another count it is marked `filesReset` instead. The count, not the provider's
|
|
290
290
|
* file system id, tells them apart: a provider may give the new file system the old id
|
|
291
|
-
* (sandbox-docker's volumes are named after the
|
|
291
|
+
* (sandbox-docker's volumes are named after the device). Best effort: a Redis error only
|
|
292
292
|
* logs.
|
|
293
293
|
*/
|
|
294
294
|
private seenBy;
|
|
@@ -335,7 +335,7 @@ export declare class SandboxService {
|
|
|
335
335
|
private kill;
|
|
336
336
|
/**
|
|
337
337
|
* Suspends running instances idle longer than `suspendAfterIdleMinutes` or running continuously
|
|
338
|
-
* longer than `maxRunningMinutes`. Skips
|
|
338
|
+
* longer than `maxRunningMinutes`. Skips a device with any holder; one past
|
|
339
339
|
* `maxRunningMinutes` gets the intent for one poll window (about a second) first. Returns how
|
|
340
340
|
* many it suspended. Called every minute by the `sandbox-suspend-idle` cron.
|
|
341
341
|
*/
|
|
@@ -343,30 +343,30 @@ export declare class SandboxService {
|
|
|
343
343
|
/**
|
|
344
344
|
* Destruction sweep: an instance unused for longer than `destroyAfterInactiveDays` is destroyed
|
|
345
345
|
* (the instance only; the file system is kept and the next use builds a new instance on it); an
|
|
346
|
-
*
|
|
347
|
-
* and its row is deleted (as {@link
|
|
348
|
-
* skipped. Inactivity never destroys a `@
|
|
349
|
-
* destroyed like any other while `@
|
|
346
|
+
* device that was deleted, or whose org was deleted, loses its instance and its file system
|
|
347
|
+
* and its row is deleted (as {@link destroyDevice} does). Devices with any holder are
|
|
348
|
+
* skipped. Inactivity never destroys a `@local` instance; a gone `@local` device is
|
|
349
|
+
* destroyed like any other while `@local` is registered. Returns how many it destroyed. Called
|
|
350
350
|
* hourly by the `sandbox-destroy-inactive` cron.
|
|
351
351
|
*/
|
|
352
352
|
destroyInactive(now: Date): Promise<number>;
|
|
353
353
|
/**
|
|
354
|
-
* Destroys the
|
|
355
|
-
* (
|
|
354
|
+
* Destroys the device's instance, then its file system, then deletes its instance row
|
|
355
|
+
* (device deletion, offboarding); nothing to do without a row. Waits for the exclusive lease
|
|
356
356
|
* (with intent, so running commands finish and new ones wait) up to 10 minutes. Without the
|
|
357
|
-
*
|
|
358
|
-
* retried, and the destruction sweep finishes a deleted
|
|
357
|
+
* device's provider it throws and the row stays, marked `sweep_failed_at` (the job is
|
|
358
|
+
* retried, and the destruction sweep finishes a deleted device once the provider is back).
|
|
359
359
|
* Files kept by another provider that is not loaded cannot be destroyed: it throws and the row
|
|
360
360
|
* stays.
|
|
361
361
|
*/
|
|
362
|
-
|
|
362
|
+
destroyDevice(deviceId: string): Promise<void>;
|
|
363
363
|
/**
|
|
364
|
-
* Starts the
|
|
365
|
-
* under the exclusive lease (waited for like {@link
|
|
364
|
+
* Starts the device over with empty files (after `device.files_lost`, or on request):
|
|
365
|
+
* under the exclusive lease (waited for like {@link destroyDevice}) destroys any instance and
|
|
366
366
|
* the file system (a `lost` one is only dropped), and records no file system; the next use
|
|
367
367
|
* creates a new one. Nothing to do without a row. Throws `sandbox.unavailable` without a provider.
|
|
368
368
|
*/
|
|
369
|
-
resetFileSystem(
|
|
369
|
+
resetFileSystem(deviceId: string): Promise<void>;
|
|
370
370
|
/**
|
|
371
371
|
* Under the exclusive lease (before the downgrade), on an instance just resumed from
|
|
372
372
|
* `suspended`: kills every command left in it (`killAll`), crashed holders' (`dead`, already
|
|
@@ -392,13 +392,13 @@ export declare class SandboxService {
|
|
|
392
392
|
private candidates;
|
|
393
393
|
/**
|
|
394
394
|
* One try at the exclusive lease: null → false; else runs `fn`. With `overdue` (past
|
|
395
|
-
* `maxRunningMinutes`) a busy
|
|
395
|
+
* `maxRunningMinutes`) a busy device gets the intent for about a second, so new commands
|
|
396
396
|
* wait briefly and the sweep gets in if the running ones end. Failures are warned, recorded in
|
|
397
397
|
* `sweep_failed_at` (sorted last next time) and return false.
|
|
398
398
|
*/
|
|
399
399
|
private tryLocked;
|
|
400
400
|
/**
|
|
401
|
-
* Under the exclusive lease: make the
|
|
401
|
+
* Under the exclusive lease: make the device's instance run. `gone`: the instance a holder
|
|
402
402
|
* found gone; when it is still the recorded one it is rebuilt, when another holder already
|
|
403
403
|
* rebuilt it the new one is used.
|
|
404
404
|
*/
|
|
@@ -407,14 +407,14 @@ export declare class SandboxService {
|
|
|
407
407
|
* Under the lease: fenced reset to `creating`, the file system when there is none
|
|
408
408
|
* (`createFileSystem`, its handle written fenced), then the instance on it, then a fenced write
|
|
409
409
|
* of the instance handle. `FileSystemGoneError` from `create` records `fs_status = 'lost'` and
|
|
410
|
-
* throws `
|
|
410
|
+
* throws `device.files_lost`. When the instance handle cannot be written (lease lost), the
|
|
411
411
|
* new instance is destroyed (best effort) before {@link SandboxLockLostError} is thrown.
|
|
412
412
|
*/
|
|
413
413
|
private create;
|
|
414
414
|
/**
|
|
415
|
-
* Destroys the file system another provider may have made under the
|
|
415
|
+
* Destroys the file system another provider may have made under the device's name without
|
|
416
416
|
* the kernel recording it (`destroyFileSystemByName`; not there is success). That provider not
|
|
417
|
-
* loaded, or a failure, is only warned (the files may leak there) so the
|
|
417
|
+
* loaded, or a failure, is only warned (the files may leak there) so the device stays
|
|
418
418
|
* usable; an abort is thrown.
|
|
419
419
|
*/
|
|
420
420
|
private dropUnrecordedFiles;
|
|
@@ -438,20 +438,20 @@ export declare class SandboxService {
|
|
|
438
438
|
private destroyFiles;
|
|
439
439
|
/**
|
|
440
440
|
* Under the lease: `instance` destroys the instance and marks the row `destroyed` (the file
|
|
441
|
-
* system stays); `
|
|
441
|
+
* system stays); `device` also destroys the file system and deletes the row.
|
|
442
442
|
*/
|
|
443
443
|
private destroyRow;
|
|
444
444
|
/** Due for suspension: made by this provider, running, and idle or running for too long. */
|
|
445
445
|
private suspendDue;
|
|
446
|
-
/** The provider of an instance row: an internal one (`@
|
|
446
|
+
/** The provider of an instance row: an internal one (`@local`) by name, else the cloud one. */
|
|
447
447
|
private rowProvider;
|
|
448
448
|
/**
|
|
449
|
-
* A row the idle sweeps may touch: not on a kernel-internal provider (`@
|
|
449
|
+
* A row the idle sweeps may touch: not on a kernel-internal provider (`@local` instances live on
|
|
450
450
|
* people's machines and are never suspended or destroyed for inactivity).
|
|
451
451
|
*/
|
|
452
452
|
private cloudRow;
|
|
453
|
-
/** The
|
|
454
|
-
private
|
|
453
|
+
/** The device was deleted, or its org was: the instance and the files go. */
|
|
454
|
+
private deviceGone;
|
|
455
455
|
/** Due for instance destruction: an instance (or a create in progress) unused for too long. */
|
|
456
456
|
private instanceDue;
|
|
457
457
|
}
|