@capybara-hq/kernel 0.1.0-rc.11 → 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/agents/agents.schemas.d.ts +3 -0
- package/dist/agents/agents.service.js +11 -1
- package/dist/agents/definition.d.ts +1 -0
- package/dist/agents/definition.js +7 -3
- package/dist/agents/org-templates.js +4 -0
- package/dist/agents/pending-connectors.service.js +1 -1
- 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/component-scope.controller.d.ts +18 -6
- package/dist/catalog/component-scope.controller.js +36 -13
- package/dist/catalog/component-scope.service.d.ts +11 -0
- package/dist/catalog/component-scope.service.js +4 -0
- package/dist/catalog/component-state.d.ts +8 -0
- package/dist/catalog/component-state.js +19 -11
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/plugin-import.js +4 -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 +23 -14
- package/dist/conversations/conversations.service.js +28 -21
- 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 +2 -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 +39 -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 +27 -25
- package/dist/errors.js +27 -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 +48 -3
- package/dist/platform/operation.js +6 -2
- package/dist/platform/ops/admin.ops.js +8 -2
- package/dist/platform/ops/agents.ops.js +19 -6
- 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/runtime/subagents/definition.d.ts +3 -2
- package/dist/runtime/subagents/definition.js +2 -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/connector-account-policies.d.ts +51 -0
- package/dist/tools/connector-account-policies.js +165 -0
- package/dist/tools/connectors.controller.d.ts +35 -4
- package/dist/tools/connectors.controller.js +66 -7
- package/dist/tools/connectors.schemas.d.ts +11 -0
- package/dist/tools/connectors.schemas.js +11 -0
- package/dist/tools/connectors.service.d.ts +2 -0
- package/dist/tools/connectors.service.js +1 -0
- package/dist/tools/pipeline.d.ts +1 -1
- package/dist/tools/pipeline.js +4 -3
- package/dist/tools/policy.d.ts +23 -1
- package/dist/tools/policy.js +99 -24
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/tools.module.js +6 -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/0104_connector_tool_account_policies.sql +16 -0
- 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
|
@@ -13,44 +13,44 @@ import { KernelDb } from "../infra/database/kernel-db.js";
|
|
|
13
13
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
14
14
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
15
15
|
import { isInternalProvider, SandboxProviders } from "../sandbox/providers.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
16
|
+
import { deviceNotFound, sandboxUnavailable } from "../sandbox/sandbox.service.js";
|
|
17
|
+
import { DeviceAccess } from "./access.js";
|
|
18
|
+
import { DevicesService } from "./devices.service.js";
|
|
19
19
|
/** `details[0].reason` of the error an anonymous IM conversation's sandbox call gets. */
|
|
20
|
-
export const
|
|
21
|
-
/** Anonymous IM senders have no
|
|
22
|
-
export const
|
|
20
|
+
export const ANONYMOUS_NO_DEVICE = "anonymous";
|
|
21
|
+
/** Anonymous IM senders have no device (spec §4.2 item 8): their sandbox tools are off. */
|
|
22
|
+
export const anonymousNoDevice = () => new ApiError("sandbox.unavailable", "Anonymous IM senders have no device, so the sandbox is not available", [{ reason: ANONYMOUS_NO_DEVICE }]);
|
|
23
23
|
/**
|
|
24
|
-
* Which
|
|
25
|
-
* §4.2 items 8, 9, 12). A conversation is bound once, to
|
|
24
|
+
* Which device a conversation works in (spec 2026-11-07-environments-design §4.1 items 1, 3;
|
|
25
|
+
* §4.2 items 8, 9, 12). A conversation is bound once, to a device of its owner
|
|
26
26
|
* (`conversations.account_id`): the one chosen at its first send, else the owner's IM default
|
|
27
|
-
* (IM threads), else the owner's default
|
|
27
|
+
* (IM threads), else the owner's default device. Its sub-agents use the root's. Access is
|
|
28
28
|
* checked when it is bound and again on every sandbox tool call ({@link forTool}); only the owner
|
|
29
|
-
* may use a personal
|
|
29
|
+
* may use a personal device, so a conversation never reaches another person's.
|
|
30
30
|
*/
|
|
31
|
-
let
|
|
31
|
+
let ConversationDevices = class ConversationDevices {
|
|
32
32
|
db;
|
|
33
33
|
txHost;
|
|
34
34
|
providers;
|
|
35
35
|
access;
|
|
36
|
-
|
|
37
|
-
constructor(db, txHost, providers, access,
|
|
36
|
+
devices;
|
|
37
|
+
constructor(db, txHost, providers, access, devices) {
|
|
38
38
|
this.db = db;
|
|
39
39
|
this.txHost = txHost;
|
|
40
40
|
this.providers = providers;
|
|
41
41
|
this.access = access;
|
|
42
|
-
this.
|
|
42
|
+
this.devices = devices;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
-
* The
|
|
46
|
-
* usable by the person (else `
|
|
47
|
-
* is created); without a choice the IM default (IM only) or the person's default
|
|
45
|
+
* The device a new conversation of `accountId` is bound to: the chosen one when it is
|
|
46
|
+
* usable by the person (else `device.not_found` / `device.unavailable`, and nothing
|
|
47
|
+
* is created); without a choice the IM default (IM only) or the person's default device.
|
|
48
48
|
* Null (unbound) for anonymous IM senders, and without a cloud sandbox provider when no usable
|
|
49
|
-
* IM default (a connected machine's
|
|
49
|
+
* IM default (a connected machine's device, say) applies.
|
|
50
50
|
*/
|
|
51
51
|
async forNew(orgId, accountId, pick = {}) {
|
|
52
|
-
if (pick.
|
|
53
|
-
return (await this.access.usable(orgId, accountId, pick.
|
|
52
|
+
if (pick.deviceId !== undefined) {
|
|
53
|
+
return (await this.access.usable(orgId, accountId, pick.deviceId)).id;
|
|
54
54
|
}
|
|
55
55
|
if (pick.im !== true && this.providers.cloud() === undefined)
|
|
56
56
|
return null;
|
|
@@ -59,75 +59,75 @@ let ConversationEnvironments = class ConversationEnvironments {
|
|
|
59
59
|
return this.defaultFor(orgId, accountId, pick.im === true);
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
* The
|
|
62
|
+
* The device a sandbox tool call of the conversation tree rooted at `rootConversationId`
|
|
63
63
|
* enters, checked for its owner now. A conversation still unbound (created before
|
|
64
|
-
*
|
|
65
|
-
* is an IM thread, else to the owner's default
|
|
66
|
-
* Throws `sandbox.unavailable` for a cloud
|
|
67
|
-
* provider and for an anonymous IM conversation, and `
|
|
68
|
-
* `
|
|
69
|
-
* connected machine's
|
|
64
|
+
* devices, or while no provider existed) is bound first, to the owner's IM default when it
|
|
65
|
+
* is an IM thread, else to the owner's default device; a racing call binds it once.
|
|
66
|
+
* Throws `sandbox.unavailable` for a cloud device (or none to bind) without a cloud
|
|
67
|
+
* provider and for an anonymous IM conversation, and `device.not_found` /
|
|
68
|
+
* `device.unavailable` when the owner may not use it now. A conversation bound to a
|
|
69
|
+
* connected machine's device (`@local`) does not need a cloud provider.
|
|
70
70
|
*/
|
|
71
71
|
async forTool(orgId, rootConversationId) {
|
|
72
72
|
const conv = await this.db
|
|
73
73
|
.selectFrom("conversations")
|
|
74
|
-
.select(["account_id", "
|
|
74
|
+
.select(["account_id", "device_id"])
|
|
75
75
|
.where("id", "=", rootConversationId)
|
|
76
76
|
.where("org_id", "=", orgId)
|
|
77
77
|
.executeTakeFirst();
|
|
78
78
|
if (!conv)
|
|
79
|
-
throw
|
|
79
|
+
throw deviceNotFound();
|
|
80
80
|
if (await this.isAnonymous(orgId, conv.account_id))
|
|
81
|
-
throw
|
|
82
|
-
let
|
|
83
|
-
if (
|
|
81
|
+
throw anonymousNoDevice();
|
|
82
|
+
let deviceId = conv.device_id;
|
|
83
|
+
if (deviceId === null) {
|
|
84
84
|
const im = await this.isImThread(rootConversationId);
|
|
85
85
|
const chosen = await this.defaultFor(orgId, conv.account_id, im);
|
|
86
86
|
if (chosen === null)
|
|
87
87
|
throw sandboxUnavailable();
|
|
88
|
-
|
|
88
|
+
deviceId = await this.bind(rootConversationId, chosen);
|
|
89
89
|
}
|
|
90
|
-
if (this.providers.cloud() === undefined && !(await this.isInternal(
|
|
90
|
+
if (this.providers.cloud() === undefined && !(await this.isInternal(deviceId))) {
|
|
91
91
|
throw sandboxUnavailable();
|
|
92
92
|
}
|
|
93
|
-
return (await this.access.usable(orgId, conv.account_id,
|
|
93
|
+
return (await this.access.usable(orgId, conv.account_id, deviceId)).id;
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
96
|
* Whether a sandbox tool call of the tree rooted at `rootConversationId` has a provider to run
|
|
97
97
|
* on, for tool listings (ruling R8; no binding, no access check, never throws): a cloud
|
|
98
|
-
* provider is loaded, or the
|
|
99
|
-
* its owner's IM default) runs on a registered kernel provider (`@
|
|
100
|
-
*
|
|
98
|
+
* provider is loaded, or the device the conversation is bound to (an unbound IM thread:
|
|
99
|
+
* its owner's IM default) runs on a registered kernel provider (`@local`). A forbidden or gone
|
|
100
|
+
* device still counts: the call then says why.
|
|
101
101
|
*/
|
|
102
102
|
async usableNow(orgId, rootConversationId) {
|
|
103
103
|
if (this.providers.cloud() !== undefined)
|
|
104
104
|
return true;
|
|
105
105
|
const conv = await this.db
|
|
106
106
|
.selectFrom("conversations")
|
|
107
|
-
.select(["account_id", "
|
|
107
|
+
.select(["account_id", "device_id"])
|
|
108
108
|
.where("id", "=", rootConversationId)
|
|
109
109
|
.where("org_id", "=", orgId)
|
|
110
110
|
.executeTakeFirst();
|
|
111
111
|
if (!conv)
|
|
112
112
|
return false;
|
|
113
|
-
let
|
|
114
|
-
if (
|
|
113
|
+
let deviceId = conv.device_id;
|
|
114
|
+
if (deviceId === null) {
|
|
115
115
|
if (!(await this.isImThread(rootConversationId)))
|
|
116
116
|
return false;
|
|
117
117
|
const row = await this.db
|
|
118
|
-
.selectFrom("
|
|
119
|
-
.select("
|
|
118
|
+
.selectFrom("device_defaults")
|
|
119
|
+
.select("device_id")
|
|
120
120
|
.where("org_id", "=", orgId)
|
|
121
121
|
.where("account_id", "=", conv.account_id)
|
|
122
122
|
.executeTakeFirst();
|
|
123
123
|
if (!row)
|
|
124
124
|
return false;
|
|
125
|
-
|
|
125
|
+
deviceId = row.device_id;
|
|
126
126
|
}
|
|
127
127
|
const env = await this.db
|
|
128
|
-
.selectFrom("
|
|
128
|
+
.selectFrom("devices")
|
|
129
129
|
.select("provider")
|
|
130
|
-
.where("id", "=",
|
|
130
|
+
.where("id", "=", deviceId)
|
|
131
131
|
.executeTakeFirst();
|
|
132
132
|
const provider = env?.provider ?? null;
|
|
133
133
|
return (provider !== null &&
|
|
@@ -136,24 +136,24 @@ let ConversationEnvironments = class ConversationEnvironments {
|
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
138
|
* The person's IM default when `im` and it is still theirs, live, in this org and usable (the
|
|
139
|
-
* table has no such guard), else their default
|
|
139
|
+
* table has no such guard), else their default device (created when missing); null when
|
|
140
140
|
* that is needed and there is no cloud provider to make or use it. The owner having left the org
|
|
141
|
-
* reads as `
|
|
141
|
+
* reads as `device.not_found`.
|
|
142
142
|
*/
|
|
143
143
|
async defaultFor(orgId, accountId, im) {
|
|
144
144
|
if (im) {
|
|
145
145
|
const row = await this.db
|
|
146
|
-
.selectFrom("
|
|
147
|
-
.select("
|
|
146
|
+
.selectFrom("device_defaults")
|
|
147
|
+
.select("device_id")
|
|
148
148
|
.where("org_id", "=", orgId)
|
|
149
149
|
.where("account_id", "=", accountId)
|
|
150
150
|
.executeTakeFirst();
|
|
151
151
|
if (row) {
|
|
152
152
|
try {
|
|
153
|
-
return (await this.access.usable(orgId, accountId, row.
|
|
153
|
+
return (await this.access.usable(orgId, accountId, row.device_id)).id;
|
|
154
154
|
}
|
|
155
155
|
catch (e) {
|
|
156
|
-
if (!
|
|
156
|
+
if (!isDeviceGone(e))
|
|
157
157
|
throw e;
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -161,35 +161,35 @@ let ConversationEnvironments = class ConversationEnvironments {
|
|
|
161
161
|
if (this.providers.cloud() === undefined)
|
|
162
162
|
return null;
|
|
163
163
|
try {
|
|
164
|
-
return await this.
|
|
164
|
+
return await this.devices.ensureDefault(orgId, accountId);
|
|
165
165
|
}
|
|
166
166
|
catch (e) {
|
|
167
167
|
if (e instanceof ApiError && e.code === "org.not_found")
|
|
168
|
-
throw
|
|
168
|
+
throw deviceNotFound();
|
|
169
169
|
throw e;
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
|
-
/** Binds an unbound conversation to `
|
|
173
|
-
async bind(conversationId,
|
|
172
|
+
/** Binds an unbound conversation to `deviceId`; returns what it is bound to now. */
|
|
173
|
+
async bind(conversationId, deviceId) {
|
|
174
174
|
await this.db
|
|
175
175
|
.updateTable("conversations")
|
|
176
|
-
.set({
|
|
176
|
+
.set({ device_id: deviceId })
|
|
177
177
|
.where("id", "=", conversationId)
|
|
178
|
-
.where("
|
|
178
|
+
.where("device_id", "is", null)
|
|
179
179
|
.execute();
|
|
180
180
|
const row = await this.db
|
|
181
181
|
.selectFrom("conversations")
|
|
182
|
-
.select("
|
|
182
|
+
.select("device_id")
|
|
183
183
|
.where("id", "=", conversationId)
|
|
184
184
|
.executeTakeFirstOrThrow();
|
|
185
|
-
return row.
|
|
185
|
+
return row.device_id ?? deviceId;
|
|
186
186
|
}
|
|
187
|
-
/** The
|
|
188
|
-
async isInternal(
|
|
187
|
+
/** The device runs on a kernel-internal provider (`@local`). */
|
|
188
|
+
async isInternal(deviceId) {
|
|
189
189
|
const row = await this.db
|
|
190
|
-
.selectFrom("
|
|
190
|
+
.selectFrom("devices")
|
|
191
191
|
.select("provider")
|
|
192
|
-
.where("id", "=",
|
|
192
|
+
.where("id", "=", deviceId)
|
|
193
193
|
.executeTakeFirst();
|
|
194
194
|
const provider = row?.provider ?? null;
|
|
195
195
|
return provider !== null && isInternalProvider(provider);
|
|
@@ -217,15 +217,14 @@ let ConversationEnvironments = class ConversationEnvironments {
|
|
|
217
217
|
};
|
|
218
218
|
__decorate([
|
|
219
219
|
Transactional()
|
|
220
|
-
],
|
|
221
|
-
|
|
220
|
+
], ConversationDevices.prototype, "bind", null);
|
|
221
|
+
ConversationDevices = __decorate([
|
|
222
222
|
Injectable(),
|
|
223
223
|
__param(0, Inject(KernelDb)),
|
|
224
224
|
__param(1, Inject(TransactionHost)),
|
|
225
225
|
__param(2, Inject(SandboxProviders)),
|
|
226
|
-
__param(3, Inject(
|
|
227
|
-
__param(4, Inject(
|
|
228
|
-
],
|
|
229
|
-
export {
|
|
230
|
-
const
|
|
231
|
-
(e.code === "environment.not_found" || e.code === "environment.unavailable");
|
|
226
|
+
__param(3, Inject(DeviceAccess)),
|
|
227
|
+
__param(4, Inject(DevicesService))
|
|
228
|
+
], ConversationDevices);
|
|
229
|
+
export { ConversationDevices };
|
|
230
|
+
const isDeviceGone = (e) => e instanceof ApiError && (e.code === "device.not_found" || e.code === "device.unavailable");
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import { type Principal } from "../identity/principal.js";
|
|
3
|
+
import { type OrgContext } from "../orgs/org.guard.js";
|
|
4
|
+
import { type DeviceList, DevicesService, type DeviceView } from "./devices.service.js";
|
|
5
|
+
import { type DeviceNameBody, type DeviceParams } from "./dto.js";
|
|
6
|
+
/**
|
|
7
|
+
* A person's devices in an org (`/api/v1/orgs/:orgId/devices`, spec
|
|
8
|
+
* 2026-11-07-environments-design §9; `agents.use`, human users only: a service token gets 403).
|
|
9
|
+
* Phase 1 has personal cloud devices only, each visible to its owner alone: another member
|
|
10
|
+
* gets 404 `device.not_found`.
|
|
11
|
+
* - `GET /` → `{ items, defaultId, lastUsedId, cloudAvailable }` (`cloudAvailable`: there is a
|
|
12
|
+
* current sandbox provider; ruling R4);
|
|
13
|
+
* - `POST / { name }` → 201 `{ device }`; `GET /:id`, `PATCH /:id { name }` → `{ device }`;
|
|
14
|
+
* - `DELETE /:id` → 202 (destroyed by a job after the response);
|
|
15
|
+
* - `POST /:id/files/reset` → 202 (the reset is enqueued: a worker empties the files, the next use
|
|
16
|
+
* starts empty);
|
|
17
|
+
* - `DELETE /:id/machine` → 204: a local device's machine is disconnected (its credential
|
|
18
|
+
* revoked; it must sign in again).
|
|
19
|
+
*/
|
|
20
|
+
export declare class DevicesController {
|
|
21
|
+
private readonly devices;
|
|
22
|
+
constructor(devices: DevicesService);
|
|
23
|
+
list(principal: Principal, org: OrgContext): Promise<DeviceList>;
|
|
24
|
+
create(principal: Principal, org: OrgContext, body: z.infer<typeof DeviceNameBody>): Promise<{
|
|
25
|
+
device: DeviceView;
|
|
26
|
+
}>;
|
|
27
|
+
get(principal: Principal, org: OrgContext, params: z.infer<typeof DeviceParams>): Promise<{
|
|
28
|
+
device: DeviceView;
|
|
29
|
+
}>;
|
|
30
|
+
rename(principal: Principal, org: OrgContext, params: z.infer<typeof DeviceParams>, body: z.infer<typeof DeviceNameBody>): Promise<{
|
|
31
|
+
device: DeviceView;
|
|
32
|
+
}>;
|
|
33
|
+
remove(principal: Principal, org: OrgContext, params: z.infer<typeof DeviceParams>): Promise<void>;
|
|
34
|
+
resetFiles(principal: Principal, org: OrgContext, params: z.infer<typeof DeviceParams>): Promise<void>;
|
|
35
|
+
revokeMachine(principal: Principal, org: OrgContext, params: z.infer<typeof DeviceParams>): Promise<void>;
|
|
36
|
+
}
|
|
@@ -11,58 +11,58 @@ import { Controller, Delete, Get, HttpCode, Inject, Patch, Post } from "@nestjs/
|
|
|
11
11
|
import { CurrentPrincipal, patTokenId, requireUser, } from "../identity/principal.js";
|
|
12
12
|
import { ZBody, ZParam } from "../infra/validation/zod-params.js";
|
|
13
13
|
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { DevicesService } from "./devices.service.js";
|
|
15
|
+
import { DeviceCreateBodyDto, DeviceParamsDto, DeviceRenameBodyDto, } from "./dto.js";
|
|
16
16
|
/**
|
|
17
|
-
* A person's
|
|
17
|
+
* A person's devices in an org (`/api/v1/orgs/:orgId/devices`, spec
|
|
18
18
|
* 2026-11-07-environments-design §9; `agents.use`, human users only: a service token gets 403).
|
|
19
|
-
* Phase 1 has personal cloud
|
|
20
|
-
* gets 404 `
|
|
19
|
+
* Phase 1 has personal cloud devices only, each visible to its owner alone: another member
|
|
20
|
+
* gets 404 `device.not_found`.
|
|
21
21
|
* - `GET /` → `{ items, defaultId, lastUsedId, cloudAvailable }` (`cloudAvailable`: there is a
|
|
22
22
|
* current sandbox provider; ruling R4);
|
|
23
|
-
* - `POST / { name }` → 201 `{
|
|
23
|
+
* - `POST / { name }` → 201 `{ device }`; `GET /:id`, `PATCH /:id { name }` → `{ device }`;
|
|
24
24
|
* - `DELETE /:id` → 202 (destroyed by a job after the response);
|
|
25
25
|
* - `POST /:id/files/reset` → 202 (the reset is enqueued: a worker empties the files, the next use
|
|
26
26
|
* starts empty);
|
|
27
|
-
* - `DELETE /:id/machine` → 204: a device
|
|
27
|
+
* - `DELETE /:id/machine` → 204: a local device's machine is disconnected (its credential
|
|
28
28
|
* revoked; it must sign in again).
|
|
29
29
|
*/
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
constructor(
|
|
33
|
-
this.
|
|
30
|
+
let DevicesController = class DevicesController {
|
|
31
|
+
devices;
|
|
32
|
+
constructor(devices) {
|
|
33
|
+
this.devices = devices;
|
|
34
34
|
}
|
|
35
35
|
async list(principal, org) {
|
|
36
36
|
const p = requireUser(principal);
|
|
37
|
-
return this.
|
|
37
|
+
return this.devices.list(org.orgId, p.account.id);
|
|
38
38
|
}
|
|
39
39
|
async create(principal, org, body) {
|
|
40
40
|
const p = requireUser(principal);
|
|
41
41
|
return {
|
|
42
|
-
|
|
42
|
+
device: await this.devices.create(org.orgId, p.account.id, { name: body.name }, patTokenId(p)),
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
async get(principal, org, params) {
|
|
46
46
|
const p = requireUser(principal);
|
|
47
|
-
return {
|
|
47
|
+
return { device: await this.devices.get(org.orgId, p.account.id, params.id) };
|
|
48
48
|
}
|
|
49
49
|
async rename(principal, org, params, body) {
|
|
50
50
|
const p = requireUser(principal);
|
|
51
51
|
return {
|
|
52
|
-
|
|
52
|
+
device: await this.devices.rename(org.orgId, p.account.id, params.id, body.name, patTokenId(p)),
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
async remove(principal, org, params) {
|
|
56
56
|
const p = requireUser(principal);
|
|
57
|
-
await this.
|
|
57
|
+
await this.devices.remove(org.orgId, p.account.id, params.id, patTokenId(p));
|
|
58
58
|
}
|
|
59
59
|
async resetFiles(principal, org, params) {
|
|
60
60
|
const p = requireUser(principal);
|
|
61
|
-
await this.
|
|
61
|
+
await this.devices.resetFiles(org.orgId, p.account.id, params.id, patTokenId(p));
|
|
62
62
|
}
|
|
63
63
|
async revokeMachine(principal, org, params) {
|
|
64
64
|
const p = requireUser(principal);
|
|
65
|
-
await this.
|
|
65
|
+
await this.devices.revokeMachine(org.orgId, p.account.id, params.id, patTokenId(p));
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
__decorate([
|
|
@@ -70,55 +70,55 @@ __decorate([
|
|
|
70
70
|
OrgAction("agents.use"),
|
|
71
71
|
__param(0, CurrentPrincipal()),
|
|
72
72
|
__param(1, CurrentOrg())
|
|
73
|
-
],
|
|
73
|
+
], DevicesController.prototype, "list", null);
|
|
74
74
|
__decorate([
|
|
75
75
|
Post(),
|
|
76
76
|
OrgAction("agents.use"),
|
|
77
77
|
__param(0, CurrentPrincipal()),
|
|
78
78
|
__param(1, CurrentOrg()),
|
|
79
|
-
__param(2, ZBody(
|
|
80
|
-
],
|
|
79
|
+
__param(2, ZBody(DeviceCreateBodyDto))
|
|
80
|
+
], DevicesController.prototype, "create", null);
|
|
81
81
|
__decorate([
|
|
82
82
|
Get(":id"),
|
|
83
83
|
OrgAction("agents.use"),
|
|
84
84
|
__param(0, CurrentPrincipal()),
|
|
85
85
|
__param(1, CurrentOrg()),
|
|
86
|
-
__param(2, ZParam(
|
|
87
|
-
],
|
|
86
|
+
__param(2, ZParam(DeviceParamsDto))
|
|
87
|
+
], DevicesController.prototype, "get", null);
|
|
88
88
|
__decorate([
|
|
89
89
|
Patch(":id"),
|
|
90
90
|
OrgAction("agents.use"),
|
|
91
91
|
__param(0, CurrentPrincipal()),
|
|
92
92
|
__param(1, CurrentOrg()),
|
|
93
|
-
__param(2, ZParam(
|
|
94
|
-
__param(3, ZBody(
|
|
95
|
-
],
|
|
93
|
+
__param(2, ZParam(DeviceParamsDto)),
|
|
94
|
+
__param(3, ZBody(DeviceRenameBodyDto))
|
|
95
|
+
], DevicesController.prototype, "rename", null);
|
|
96
96
|
__decorate([
|
|
97
97
|
Delete(":id"),
|
|
98
98
|
HttpCode(202),
|
|
99
99
|
OrgAction("agents.use"),
|
|
100
100
|
__param(0, CurrentPrincipal()),
|
|
101
101
|
__param(1, CurrentOrg()),
|
|
102
|
-
__param(2, ZParam(
|
|
103
|
-
],
|
|
102
|
+
__param(2, ZParam(DeviceParamsDto))
|
|
103
|
+
], DevicesController.prototype, "remove", null);
|
|
104
104
|
__decorate([
|
|
105
105
|
Post(":id/files/reset"),
|
|
106
106
|
HttpCode(202),
|
|
107
107
|
OrgAction("agents.use"),
|
|
108
108
|
__param(0, CurrentPrincipal()),
|
|
109
109
|
__param(1, CurrentOrg()),
|
|
110
|
-
__param(2, ZParam(
|
|
111
|
-
],
|
|
110
|
+
__param(2, ZParam(DeviceParamsDto))
|
|
111
|
+
], DevicesController.prototype, "resetFiles", null);
|
|
112
112
|
__decorate([
|
|
113
113
|
Delete(":id/machine"),
|
|
114
114
|
HttpCode(204),
|
|
115
115
|
OrgAction("agents.use"),
|
|
116
116
|
__param(0, CurrentPrincipal()),
|
|
117
117
|
__param(1, CurrentOrg()),
|
|
118
|
-
__param(2, ZParam(
|
|
119
|
-
],
|
|
120
|
-
|
|
121
|
-
Controller("api/v1/orgs/:orgId/
|
|
122
|
-
__param(0, Inject(
|
|
123
|
-
],
|
|
124
|
-
export {
|
|
118
|
+
__param(2, ZParam(DeviceParamsDto))
|
|
119
|
+
], DevicesController.prototype, "revokeMachine", null);
|
|
120
|
+
DevicesController = __decorate([
|
|
121
|
+
Controller("api/v1/orgs/:orgId/devices"),
|
|
122
|
+
__param(0, Inject(DevicesService))
|
|
123
|
+
], DevicesController);
|
|
124
|
+
export { DevicesController };
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import { type OnModuleInit } from "@nestjs/common";
|
|
2
|
-
import { SandboxProviders } from "../sandbox/providers.js";
|
|
3
|
-
import { DeviceSandboxProvider } from "./device-provider.js";
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* (the socket itself is held by the gateway role).
|
|
2
|
+
* Devices (spec 2026-11-07-environments-design): a person's devices
|
|
3
|
+
* ({@link DevicesService}), who may use one ({@link DeviceAccess}) and the one a
|
|
4
|
+
* conversation works in ({@link ConversationDevices}). The instances and file systems are the
|
|
5
|
+
* {@link SandboxModule}'s.
|
|
10
6
|
*/
|
|
11
|
-
export declare class DevicesModule
|
|
12
|
-
private readonly providers;
|
|
13
|
-
private readonly device;
|
|
14
|
-
constructor(providers: SandboxProviders, device: DeviceSandboxProvider);
|
|
15
|
-
onModuleInit(): void;
|
|
7
|
+
export declare class DevicesModule {
|
|
16
8
|
}
|
|
@@ -4,41 +4,28 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
import { Inject, Module } from "@nestjs/common";
|
|
11
|
-
import { DEVICE_PROVIDER, SandboxProviders } from "../sandbox/providers.js";
|
|
7
|
+
import { Module } from "@nestjs/common";
|
|
8
|
+
import { ExtensionsModule } from "../extensions/extensions.module.js";
|
|
9
|
+
import { LocalDevicesModule } from "../local-devices/local-devices.module.js";
|
|
12
10
|
import { SandboxModule } from "../sandbox/sandbox.module.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { DeviceTargets } from "./targets.js";
|
|
11
|
+
import { DeviceAccess } from "./access.js";
|
|
12
|
+
import { ConversationDevices } from "./conversation-devices.js";
|
|
13
|
+
import { DevicesService } from "./devices.service.js";
|
|
17
14
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* (the socket itself is held by the gateway role).
|
|
15
|
+
* Devices (spec 2026-11-07-environments-design): a person's devices
|
|
16
|
+
* ({@link DevicesService}), who may use one ({@link DeviceAccess}) and the one a
|
|
17
|
+
* conversation works in ({@link ConversationDevices}). The instances and file systems are the
|
|
18
|
+
* {@link SandboxModule}'s.
|
|
23
19
|
*/
|
|
24
20
|
let DevicesModule = class DevicesModule {
|
|
25
|
-
providers;
|
|
26
|
-
device;
|
|
27
|
-
constructor(providers, device) {
|
|
28
|
-
this.providers = providers;
|
|
29
|
-
this.device = device;
|
|
30
|
-
}
|
|
31
|
-
onModuleInit() {
|
|
32
|
-
this.providers.register({ plugin: DEVICE_PROVIDER, impl: this.device });
|
|
33
|
-
}
|
|
34
21
|
};
|
|
35
22
|
DevicesModule = __decorate([
|
|
36
23
|
Module({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
// ExtensionsModule: the provider display names of demoted defaults; LocalDevicesModule: deleting
|
|
25
|
+
// a local device revokes its machine
|
|
26
|
+
imports: [SandboxModule, ExtensionsModule, LocalDevicesModule],
|
|
27
|
+
providers: [DeviceAccess, DevicesService, ConversationDevices],
|
|
28
|
+
exports: [DeviceAccess, DevicesService, ConversationDevices],
|
|
29
|
+
})
|
|
43
30
|
], DevicesModule);
|
|
44
31
|
export { DevicesModule };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DeviceNameBody, DeviceParams } from "./dto.js";
|
|
2
|
+
/** The devices routes the Platform operations mirror (`check:platform-ops` keys). */
|
|
3
|
+
export const DEVICE_ROUTES = [
|
|
4
|
+
{ route: "GET /api/v1/orgs/:orgId/devices" },
|
|
5
|
+
{ route: "POST /api/v1/orgs/:orgId/devices", body: DeviceNameBody },
|
|
6
|
+
{ route: "GET /api/v1/orgs/:orgId/devices/:id", params: DeviceParams },
|
|
7
|
+
{
|
|
8
|
+
route: "PATCH /api/v1/orgs/:orgId/devices/:id",
|
|
9
|
+
params: DeviceParams,
|
|
10
|
+
body: DeviceNameBody,
|
|
11
|
+
},
|
|
12
|
+
{ route: "DELETE /api/v1/orgs/:orgId/devices/:id", params: DeviceParams },
|
|
13
|
+
{ route: "POST /api/v1/orgs/:orgId/devices/:id/files/reset", params: DeviceParams },
|
|
14
|
+
];
|