@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
|
@@ -257,8 +257,8 @@ export interface ConversationsTable {
|
|
|
257
257
|
deleted_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
|
|
258
258
|
/** 0074: levels below the root conversation (0 = a root; a sub-agent's is its parent's + 1). */
|
|
259
259
|
subagent_depth: ColumnType<number, number | undefined, number>;
|
|
260
|
-
/** 0088: the
|
|
261
|
-
|
|
260
|
+
/** 0088, renamed in 0105: the device the conversation runs in; null = not chosen yet. */
|
|
261
|
+
device_id: ColumnType<string | null, string | null | undefined, string | null>;
|
|
262
262
|
}
|
|
263
263
|
/** 0060: an org's order of file-preview@1 previewers (UI refresh B Task 11). */
|
|
264
264
|
export interface FilePreviewersTable {
|
|
@@ -783,8 +783,8 @@ export interface BackgroundTasksTable {
|
|
|
783
783
|
read_offset: ColumnType<string, number | string | undefined, number | string>;
|
|
784
784
|
/** Set while a stop is under way (0072); the poller skips such a task. */
|
|
785
785
|
stopping_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
|
|
786
|
-
/** 0088: the
|
|
787
|
-
|
|
786
|
+
/** 0088, renamed in 0105: the device the task runs in. */
|
|
787
|
+
device_id: ColumnType<string | null, string | null | undefined, string | null>;
|
|
788
788
|
}
|
|
789
789
|
/** 0023_sandboxes.sql: the legacy per-conversation sandbox; kept only for the cleanup job (0088). */
|
|
790
790
|
export interface LegacySandboxesTable {
|
|
@@ -818,26 +818,29 @@ type InstanceHandle = ColumnType<{
|
|
|
818
818
|
id: string;
|
|
819
819
|
[k: string]: unknown;
|
|
820
820
|
} | null, string | null | undefined, string | null>;
|
|
821
|
-
/**
|
|
822
|
-
|
|
821
|
+
/**
|
|
822
|
+
* 0088_environments.sql, renamed in 0105: a device. A cloud device is one instance plus a kept file
|
|
823
|
+
* system; a local device is a person's machine (device_machines).
|
|
824
|
+
*/
|
|
825
|
+
export interface DevicesTable {
|
|
823
826
|
id: string;
|
|
824
827
|
org_id: string;
|
|
825
828
|
owner_kind: "personal";
|
|
826
829
|
owner_account_id: string;
|
|
827
830
|
name: ColumnType<string | null, string | null | undefined, string | null>;
|
|
828
831
|
is_default: ColumnType<boolean, boolean | undefined, boolean>;
|
|
829
|
-
/** 0093: `
|
|
830
|
-
source: "cloud" | "
|
|
832
|
+
/** 0093, renamed in 0105: `local` is a person's machine (device_machines). */
|
|
833
|
+
source: "cloud" | "local";
|
|
831
834
|
provider: ColumnType<string | null, string | null | undefined, string | null>;
|
|
832
|
-
/** 0096: the provider a demoted default was demoted from; null for every other
|
|
835
|
+
/** 0096: the provider a demoted default was demoted from; null for every other device. */
|
|
833
836
|
demoted_from_provider: ColumnType<string | null, string | null | undefined, string | null>;
|
|
834
837
|
created_at: Ts;
|
|
835
838
|
updated_at: Ts;
|
|
836
839
|
deleted_at: TsNullable;
|
|
837
840
|
}
|
|
838
|
-
/** 0088_environments.sql: the instance and file system of
|
|
839
|
-
export interface
|
|
840
|
-
|
|
841
|
+
/** 0088_environments.sql, renamed in 0105: the instance and file system of a device. */
|
|
842
|
+
export interface DeviceInstancesTable {
|
|
843
|
+
device_id: string;
|
|
841
844
|
org_id: string;
|
|
842
845
|
provider: ColumnType<string | null, string | null | undefined, string | null>;
|
|
843
846
|
/** The provider's `FileSystemHandle`; null before the file system exists or after a reset. */
|
|
@@ -862,13 +865,13 @@ export interface EnvironmentInstancesTable {
|
|
|
862
865
|
sweep_failed_at: TsNullable;
|
|
863
866
|
}
|
|
864
867
|
/**
|
|
865
|
-
* 0093_connected_environments.sql: the machine
|
|
866
|
-
* unrevoked row per
|
|
868
|
+
* 0093_connected_environments.sql, renamed in 0105: the machine of a local device. At most one
|
|
869
|
+
* unrevoked row per device; revoking sets `revoked_at` and keeps the row.
|
|
867
870
|
*/
|
|
868
|
-
export interface
|
|
871
|
+
export interface DeviceMachinesTable {
|
|
869
872
|
id: Generated<string>;
|
|
870
873
|
org_id: string;
|
|
871
|
-
|
|
874
|
+
device_id: string;
|
|
872
875
|
account_id: string;
|
|
873
876
|
/** A hash of the machine credential, never the credential itself. */
|
|
874
877
|
credential_hash: string;
|
|
@@ -884,11 +887,11 @@ export interface EnvironmentMachinesTable {
|
|
|
884
887
|
created_at: Ts;
|
|
885
888
|
revoked_at: TsNullable;
|
|
886
889
|
}
|
|
887
|
-
/** 0088_environments.sql: the
|
|
888
|
-
export interface
|
|
890
|
+
/** 0088_environments.sql, renamed in 0105: the device a member's new conversations use by default. */
|
|
891
|
+
export interface DeviceDefaultsTable {
|
|
889
892
|
org_id: string;
|
|
890
893
|
account_id: string;
|
|
891
|
-
|
|
894
|
+
device_id: string;
|
|
892
895
|
updated_at: Ts;
|
|
893
896
|
}
|
|
894
897
|
/** pg numeric:驱动读出为字符串(精确小数),读取方自行 `Number()`。 */
|
|
@@ -1170,10 +1173,10 @@ export interface KernelDatabase {
|
|
|
1170
1173
|
directory_exclusions: DirectoryExclusionsTable;
|
|
1171
1174
|
attachments: AttachmentsTable;
|
|
1172
1175
|
sandboxes: LegacySandboxesTable;
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1176
|
+
devices: DevicesTable;
|
|
1177
|
+
device_instances: DeviceInstancesTable;
|
|
1178
|
+
device_defaults: DeviceDefaultsTable;
|
|
1179
|
+
device_machines: DeviceMachinesTable;
|
|
1177
1180
|
background_tasks: BackgroundTasksTable;
|
|
1178
1181
|
skills: SkillsTable;
|
|
1179
1182
|
skill_versions: SkillVersionsTable;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ApiError } from "../errors.js";
|
|
2
2
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
3
|
import { SandboxProviders } from "../sandbox/providers.js";
|
|
4
|
-
/** What decides
|
|
4
|
+
/** What decides a device's provider: its own record and its instance row's (if any). */
|
|
5
5
|
export interface ProviderFacts {
|
|
6
|
-
/** `
|
|
6
|
+
/** `devices.provider`: the provider current when it was created. */
|
|
7
7
|
provider: string | null;
|
|
8
|
-
/** `
|
|
8
|
+
/** `device_instances.provider`; null without an instance row. */
|
|
9
9
|
instanceProvider: string | null;
|
|
10
10
|
/** The instance row's `fs_status`; null without an instance row. */
|
|
11
11
|
fsStatus: "none" | "ready" | "lost" | null;
|
|
@@ -13,15 +13,15 @@ export interface ProviderFacts {
|
|
|
13
13
|
hasInstance: boolean;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* The provider
|
|
17
|
-
* cloud
|
|
16
|
+
* The provider a device works with: a kernel-internal one (`@local`) as recorded; for a
|
|
17
|
+
* cloud device the one keeping its files or instance once it has any (they are never
|
|
18
18
|
* migrated, spec §4.2 item 13); before that, the current cloud provider (its first use creates
|
|
19
19
|
* them there), else the one recorded at creation. The same rule as `SandboxService`'s use.
|
|
20
20
|
*/
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function deviceProvider(f: ProviderFacts, current: string | undefined): string | null;
|
|
22
22
|
/** It has files or an instance at some provider (a file system, even a lost one, or a handle). */
|
|
23
23
|
export declare const holdsResources: (f: ProviderFacts) => boolean;
|
|
24
|
-
/** `
|
|
24
|
+
/** `device_instances.status`. */
|
|
25
25
|
export type InstanceStatus = "none" | "creating" | "running" | "suspended" | "destroyed";
|
|
26
26
|
/**
|
|
27
27
|
* For replacing a default (which one is the person's default): it holds healthy files or an
|
|
@@ -36,30 +36,30 @@ export declare const inUseForDefault: (f: ProviderFacts & {
|
|
|
36
36
|
* The provider a former default belongs to (its label and the provider whose switch back restores
|
|
37
37
|
* it): the one holding its resources once it holds any, else the one it was demoted from (the
|
|
38
38
|
* marker). A former default demoted while empty and used afterwards keeps a stale marker; its
|
|
39
|
-
* resources decide. null for
|
|
39
|
+
* resources decide. null for a device that is not a former default.
|
|
40
40
|
*/
|
|
41
41
|
export declare function demotedProvider(marker: string | null, f: ProviderFacts): string | null;
|
|
42
42
|
/**
|
|
43
|
-
* The
|
|
44
|
-
* internal provider (`@
|
|
43
|
+
* The device's provider is not the current one, or there is no provider (503); for an
|
|
44
|
+
* internal provider (`@local`), this kernel does not serve it.
|
|
45
45
|
*/
|
|
46
|
-
export declare const
|
|
46
|
+
export declare const deviceUnavailable: (provider: string | null) => ApiError;
|
|
47
47
|
/**
|
|
48
|
-
* Who may use
|
|
49
|
-
*
|
|
48
|
+
* Who may use a device (spec §4.2 item 12): in phase 1 only the owner of a personal
|
|
49
|
+
* device. Anyone else gets `device.not_found`, never `forbidden`, so ids cannot be
|
|
50
50
|
* probed. Read live on every call (PG, no cache); phase 3 adds project membership.
|
|
51
51
|
*/
|
|
52
|
-
export declare class
|
|
52
|
+
export declare class DeviceAccess {
|
|
53
53
|
private readonly db;
|
|
54
54
|
private readonly providers;
|
|
55
55
|
constructor(db: KernelDb, providers: Pick<SandboxProviders, "cloud" | "forName">);
|
|
56
56
|
/**
|
|
57
|
-
* The
|
|
58
|
-
* missing, deleted, in another org or someone else's; `
|
|
59
|
-
* provider is not the current one (or there is none). A
|
|
60
|
-
* `@
|
|
57
|
+
* The device if `accountId` may use it in `orgId` now: `device.not_found` when it is
|
|
58
|
+
* missing, deleted, in another org or someone else's; `device.unavailable` when its
|
|
59
|
+
* provider is not the current one (or there is none). A local device is usable while
|
|
60
|
+
* `@local` is registered: whether its machine is online is the relay's concern, not access.
|
|
61
61
|
*/
|
|
62
|
-
usable(orgId: string, accountId: string,
|
|
62
|
+
usable(orgId: string, accountId: string, deviceId: string): Promise<{
|
|
63
63
|
id: string;
|
|
64
64
|
provider: string | null;
|
|
65
65
|
}>;
|
|
@@ -11,14 +11,14 @@ import { Inject, Injectable } from "@nestjs/common";
|
|
|
11
11
|
import { ApiError } from "../errors.js";
|
|
12
12
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
13
13
|
import { isInternalProvider, SandboxProviders } from "../sandbox/providers.js";
|
|
14
|
-
import {
|
|
14
|
+
import { deviceNotFound } from "../sandbox/sandbox.service.js";
|
|
15
15
|
/**
|
|
16
|
-
* The provider
|
|
17
|
-
* cloud
|
|
16
|
+
* The provider a device works with: a kernel-internal one (`@local`) as recorded; for a
|
|
17
|
+
* cloud device the one keeping its files or instance once it has any (they are never
|
|
18
18
|
* migrated, spec §4.2 item 13); before that, the current cloud provider (its first use creates
|
|
19
19
|
* them there), else the one recorded at creation. The same rule as `SandboxService`'s use.
|
|
20
20
|
*/
|
|
21
|
-
export function
|
|
21
|
+
export function deviceProvider(f, current) {
|
|
22
22
|
if (f.provider !== null && isInternalProvider(f.provider))
|
|
23
23
|
return f.provider;
|
|
24
24
|
if (holdsResources(f))
|
|
@@ -40,7 +40,7 @@ export const inUseForDefault = (f) => f.fsStatus === "ready" ||
|
|
|
40
40
|
* The provider a former default belongs to (its label and the provider whose switch back restores
|
|
41
41
|
* it): the one holding its resources once it holds any, else the one it was demoted from (the
|
|
42
42
|
* marker). A former default demoted while empty and used afterwards keeps a stale marker; its
|
|
43
|
-
* resources decide. null for
|
|
43
|
+
* resources decide. null for a device that is not a former default.
|
|
44
44
|
*/
|
|
45
45
|
export function demotedProvider(marker, f) {
|
|
46
46
|
if (marker === null)
|
|
@@ -48,20 +48,20 @@ export function demotedProvider(marker, f) {
|
|
|
48
48
|
return (holdsResources(f) ? f.instanceProvider : null) ?? marker;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
* The
|
|
52
|
-
* internal provider (`@
|
|
51
|
+
* The device's provider is not the current one, or there is no provider (503); for an
|
|
52
|
+
* internal provider (`@local`), this kernel does not serve it.
|
|
53
53
|
*/
|
|
54
|
-
export const
|
|
54
|
+
export const deviceUnavailable = (provider) => new ApiError("device.unavailable", provider === null
|
|
55
55
|
? "No cloud sandbox is available in this deployment; ask the super admin to enable a sandbox plugin"
|
|
56
56
|
: isInternalProvider(provider)
|
|
57
|
-
? `This
|
|
58
|
-
: `This
|
|
57
|
+
? `This device runs on a connected machine (${provider}), which this deployment does not serve`
|
|
58
|
+
: `This device is kept by the sandbox provider ${provider}, which is not the current provider; it can be used again once ${provider} is the deployment's sandbox provider`);
|
|
59
59
|
/**
|
|
60
|
-
* Who may use
|
|
61
|
-
*
|
|
60
|
+
* Who may use a device (spec §4.2 item 12): in phase 1 only the owner of a personal
|
|
61
|
+
* device. Anyone else gets `device.not_found`, never `forbidden`, so ids cannot be
|
|
62
62
|
* probed. Read live on every call (PG, no cache); phase 3 adds project membership.
|
|
63
63
|
*/
|
|
64
|
-
let
|
|
64
|
+
let DeviceAccess = class DeviceAccess {
|
|
65
65
|
db;
|
|
66
66
|
providers;
|
|
67
67
|
constructor(db, providers) {
|
|
@@ -69,45 +69,45 @@ let EnvironmentAccess = class EnvironmentAccess {
|
|
|
69
69
|
this.providers = providers;
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
* The
|
|
73
|
-
* missing, deleted, in another org or someone else's; `
|
|
74
|
-
* provider is not the current one (or there is none). A
|
|
75
|
-
* `@
|
|
72
|
+
* The device if `accountId` may use it in `orgId` now: `device.not_found` when it is
|
|
73
|
+
* missing, deleted, in another org or someone else's; `device.unavailable` when its
|
|
74
|
+
* provider is not the current one (or there is none). A local device is usable while
|
|
75
|
+
* `@local` is registered: whether its machine is online is the relay's concern, not access.
|
|
76
76
|
*/
|
|
77
|
-
async usable(orgId, accountId,
|
|
77
|
+
async usable(orgId, accountId, deviceId) {
|
|
78
78
|
const row = await this.db
|
|
79
|
-
.selectFrom("
|
|
80
|
-
.leftJoin("
|
|
79
|
+
.selectFrom("devices as e")
|
|
80
|
+
.leftJoin("device_instances as i", "i.device_id", "e.id")
|
|
81
81
|
.select(["e.id", "e.provider", "i.provider as instance_provider", "i.fs_status", "i.handle"])
|
|
82
|
-
.where("e.id", "=",
|
|
82
|
+
.where("e.id", "=", deviceId)
|
|
83
83
|
.where("e.org_id", "=", orgId)
|
|
84
84
|
.where("e.owner_kind", "=", "personal")
|
|
85
85
|
.where("e.owner_account_id", "=", accountId)
|
|
86
86
|
.where("e.deleted_at", "is", null)
|
|
87
87
|
.executeTakeFirst();
|
|
88
88
|
if (!row)
|
|
89
|
-
throw
|
|
89
|
+
throw deviceNotFound();
|
|
90
90
|
if (row.provider !== null && isInternalProvider(row.provider)) {
|
|
91
91
|
if (this.providers.forName(row.provider) === undefined) {
|
|
92
|
-
throw
|
|
92
|
+
throw deviceUnavailable(row.provider);
|
|
93
93
|
}
|
|
94
94
|
return { id: row.id, provider: row.provider };
|
|
95
95
|
}
|
|
96
96
|
const current = this.providers.cloud()?.plugin;
|
|
97
|
-
const provider =
|
|
97
|
+
const provider = deviceProvider({
|
|
98
98
|
provider: row.provider,
|
|
99
99
|
instanceProvider: row.instance_provider,
|
|
100
100
|
fsStatus: row.fs_status,
|
|
101
101
|
hasInstance: row.handle !== null,
|
|
102
102
|
}, current);
|
|
103
103
|
if (current === undefined || provider !== current)
|
|
104
|
-
throw
|
|
104
|
+
throw deviceUnavailable(provider);
|
|
105
105
|
return { id: row.id, provider };
|
|
106
106
|
}
|
|
107
107
|
};
|
|
108
|
-
|
|
108
|
+
DeviceAccess = __decorate([
|
|
109
109
|
Injectable(),
|
|
110
110
|
__param(0, Inject(KernelDb)),
|
|
111
111
|
__param(1, Inject(SandboxProviders))
|
|
112
|
-
],
|
|
113
|
-
export {
|
|
112
|
+
], DeviceAccess);
|
|
113
|
+
export { DeviceAccess };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ApiError } from "../errors.js";
|
|
2
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
4
|
+
import { SandboxProviders } from "../sandbox/providers.js";
|
|
5
|
+
import { DeviceAccess } from "./access.js";
|
|
6
|
+
import { DevicesService } from "./devices.service.js";
|
|
7
|
+
/** `details[0].reason` of the error an anonymous IM conversation's sandbox call gets. */
|
|
8
|
+
export declare const ANONYMOUS_NO_DEVICE = "anonymous";
|
|
9
|
+
/** Anonymous IM senders have no device (spec §4.2 item 8): their sandbox tools are off. */
|
|
10
|
+
export declare const anonymousNoDevice: () => ApiError;
|
|
11
|
+
/** How a new conversation picks its device. */
|
|
12
|
+
export interface NewConversationDevice {
|
|
13
|
+
/** The device the person chose (the composer's picker); checked with `usable`. */
|
|
14
|
+
deviceId?: string;
|
|
15
|
+
/** An IM thread: the person's IM default (`device_defaults`) when still usable. */
|
|
16
|
+
im?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Which device a conversation works in (spec 2026-11-07-environments-design §4.1 items 1, 3;
|
|
20
|
+
* §4.2 items 8, 9, 12). A conversation is bound once, to a device of its owner
|
|
21
|
+
* (`conversations.account_id`): the one chosen at its first send, else the owner's IM default
|
|
22
|
+
* (IM threads), else the owner's default device. Its sub-agents use the root's. Access is
|
|
23
|
+
* checked when it is bound and again on every sandbox tool call ({@link forTool}); only the owner
|
|
24
|
+
* may use a personal device, so a conversation never reaches another person's.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ConversationDevices {
|
|
27
|
+
private readonly db;
|
|
28
|
+
readonly txHost: TransactionHost;
|
|
29
|
+
private readonly providers;
|
|
30
|
+
private readonly access;
|
|
31
|
+
private readonly devices;
|
|
32
|
+
constructor(db: KernelDb, txHost: TransactionHost, providers: Pick<SandboxProviders, "cloud"> & Partial<Pick<SandboxProviders, "forName">>, access: Pick<DeviceAccess, "usable">, devices: Pick<DevicesService, "ensureDefault">);
|
|
33
|
+
/**
|
|
34
|
+
* The device a new conversation of `accountId` is bound to: the chosen one when it is
|
|
35
|
+
* usable by the person (else `device.not_found` / `device.unavailable`, and nothing
|
|
36
|
+
* is created); without a choice the IM default (IM only) or the person's default device.
|
|
37
|
+
* Null (unbound) for anonymous IM senders, and without a cloud sandbox provider when no usable
|
|
38
|
+
* IM default (a connected machine's device, say) applies.
|
|
39
|
+
*/
|
|
40
|
+
forNew(orgId: string, accountId: string, pick?: NewConversationDevice): Promise<string | null>;
|
|
41
|
+
/**
|
|
42
|
+
* The device a sandbox tool call of the conversation tree rooted at `rootConversationId`
|
|
43
|
+
* enters, checked for its owner now. A conversation still unbound (created before
|
|
44
|
+
* devices, or while no provider existed) is bound first, to the owner's IM default when it
|
|
45
|
+
* is an IM thread, else to the owner's default device; a racing call binds it once.
|
|
46
|
+
* Throws `sandbox.unavailable` for a cloud device (or none to bind) without a cloud
|
|
47
|
+
* provider and for an anonymous IM conversation, and `device.not_found` /
|
|
48
|
+
* `device.unavailable` when the owner may not use it now. A conversation bound to a
|
|
49
|
+
* connected machine's device (`@local`) does not need a cloud provider.
|
|
50
|
+
*/
|
|
51
|
+
forTool(orgId: string, rootConversationId: string): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Whether a sandbox tool call of the tree rooted at `rootConversationId` has a provider to run
|
|
54
|
+
* on, for tool listings (ruling R8; no binding, no access check, never throws): a cloud
|
|
55
|
+
* provider is loaded, or the device the conversation is bound to (an unbound IM thread:
|
|
56
|
+
* its owner's IM default) runs on a registered kernel provider (`@local`). A forbidden or gone
|
|
57
|
+
* device still counts: the call then says why.
|
|
58
|
+
*/
|
|
59
|
+
usableNow(orgId: string, rootConversationId: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* The person's IM default when `im` and it is still theirs, live, in this org and usable (the
|
|
62
|
+
* table has no such guard), else their default device (created when missing); null when
|
|
63
|
+
* that is needed and there is no cloud provider to make or use it. The owner having left the org
|
|
64
|
+
* reads as `device.not_found`.
|
|
65
|
+
*/
|
|
66
|
+
private defaultFor;
|
|
67
|
+
/** Binds an unbound conversation to `deviceId`; returns what it is bound to now. */
|
|
68
|
+
private bind;
|
|
69
|
+
/** The device runs on a kernel-internal provider (`@local`). */
|
|
70
|
+
private isInternal;
|
|
71
|
+
/** The account is the org's anonymous IM guest (no person behind it). */
|
|
72
|
+
private isAnonymous;
|
|
73
|
+
/** The conversation is (or was) an IM thread's. */
|
|
74
|
+
private isImThread;
|
|
75
|
+
}
|