@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.
Files changed (192) hide show
  1. package/dist/admin/admin.schemas.d.ts +13 -0
  2. package/dist/agents/agent-lookup.d.ts +5 -0
  3. package/dist/agents/agent-lookup.js +15 -0
  4. package/dist/background/background.module.js +2 -2
  5. package/dist/background/launch-lock.d.ts +1 -1
  6. package/dist/background/launch-lock.js +1 -1
  7. package/dist/background/poll.job.d.ts +2 -2
  8. package/dist/background/poll.job.js +10 -10
  9. package/dist/background/stop.d.ts +1 -1
  10. package/dist/background/stop.js +3 -3
  11. package/dist/background/store.d.ts +5 -5
  12. package/dist/background/store.js +5 -5
  13. package/dist/background/tasks.service.d.ts +6 -6
  14. package/dist/background/tasks.service.js +13 -13
  15. package/dist/catalog/marketplaces.service.d.ts +1 -1
  16. package/dist/channels/channels.module.js +2 -2
  17. package/dist/channels/inbound.d.ts +8 -8
  18. package/dist/channels/inbound.js +31 -31
  19. package/dist/channels/phrases.d.ts +27 -27
  20. package/dist/channels/phrases.js +27 -27
  21. package/dist/config/docs.js +1 -1
  22. package/dist/config/schema.d.ts +2 -2
  23. package/dist/config/schema.js +21 -21
  24. package/dist/conversations/conversations.controller.d.ts +11 -11
  25. package/dist/conversations/conversations.controller.js +15 -15
  26. package/dist/conversations/conversations.module.d.ts +1 -1
  27. package/dist/conversations/conversations.module.js +7 -7
  28. package/dist/conversations/conversations.schemas.js +1 -1
  29. package/dist/conversations/conversations.service.d.ts +14 -14
  30. package/dist/conversations/conversations.service.js +19 -19
  31. package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
  32. package/dist/conversations/{environment-status.js → device-status.js} +18 -18
  33. package/dist/conversations/event-log.d.ts +1 -1
  34. package/dist/conversations/event-log.js +1 -1
  35. package/dist/conversations/events.d.ts +1 -1
  36. package/dist/conversations/events.js +2 -2
  37. package/dist/ctx/create-ctx.d.ts +10 -1
  38. package/dist/ctx/create-ctx.js +86 -25
  39. package/dist/db/kernel-schema.d.ts +26 -23
  40. package/dist/{environments → devices}/access.d.ts +19 -19
  41. package/dist/{environments → devices}/access.js +28 -28
  42. package/dist/devices/conversation-devices.d.ts +75 -0
  43. package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
  44. package/dist/devices/devices.controller.d.ts +36 -0
  45. package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
  46. package/dist/devices/devices.module.d.ts +5 -13
  47. package/dist/devices/devices.module.js +16 -29
  48. package/dist/devices/devices.schemas.d.ts +3 -0
  49. package/dist/devices/devices.schemas.js +14 -0
  50. package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
  51. package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
  52. package/dist/devices/dto.d.ts +13 -54
  53. package/dist/devices/dto.js +7 -39
  54. package/dist/devices/label.d.ts +11 -0
  55. package/dist/{environments → devices}/label.js +7 -7
  56. package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
  57. package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
  58. package/dist/errors.d.ts +25 -25
  59. package/dist/errors.js +25 -25
  60. package/dist/evals/recorded-tools.d.ts +2 -2
  61. package/dist/evals/recorded-tools.js +6 -6
  62. package/dist/extensions/admin-ops.js +1 -0
  63. package/dist/extensions/admin-view.js +2 -0
  64. package/dist/extensions/effective-config.d.ts +6 -0
  65. package/dist/extensions/effective-config.js +18 -7
  66. package/dist/extensions/host.d.ts +13 -2
  67. package/dist/extensions/host.js +24 -3
  68. package/dist/extensions/instance.d.ts +12 -1
  69. package/dist/extensions/instance.js +13 -0
  70. package/dist/extensions/permission-view.d.ts +10 -1
  71. package/dist/files/previewers.d.ts +1 -1
  72. package/dist/files/previewers.js +1 -1
  73. package/dist/http/api.module.js +10 -6
  74. package/dist/http/gateway-routes.d.ts +1 -1
  75. package/dist/http/gateway-routes.js +1 -1
  76. package/dist/identity/settings.d.ts +32 -0
  77. package/dist/identity/settings.js +26 -2
  78. package/dist/infra/config/kernel-config.service.js +4 -4
  79. package/dist/kernel.module.js +3 -3
  80. package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
  81. package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
  82. package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
  83. package/dist/{devices → local-devices}/device-auth.js +51 -53
  84. package/dist/local-devices/device-auth.module.d.ts +7 -0
  85. package/dist/{devices → local-devices}/device-auth.module.js +5 -5
  86. package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
  87. package/dist/{devices → local-devices}/device-routes.js +2 -2
  88. package/dist/local-devices/dto.d.ts +66 -0
  89. package/dist/local-devices/dto.js +44 -0
  90. package/dist/{devices → local-devices}/keys.d.ts +11 -11
  91. package/dist/{devices → local-devices}/keys.js +11 -11
  92. package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
  93. package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
  94. package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
  95. package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
  96. package/dist/local-devices/local-devices.module.d.ts +16 -0
  97. package/dist/local-devices/local-devices.module.js +44 -0
  98. package/dist/{devices → local-devices}/machines.d.ts +26 -26
  99. package/dist/{devices → local-devices}/machines.js +71 -71
  100. package/dist/{devices → local-devices}/relay.d.ts +15 -15
  101. package/dist/{devices → local-devices}/relay.js +55 -55
  102. package/dist/{devices → local-devices}/targets.d.ts +8 -8
  103. package/dist/{devices → local-devices}/targets.js +14 -14
  104. package/dist/orgs/offboarding.d.ts +6 -6
  105. package/dist/orgs/offboarding.js +12 -12
  106. package/dist/orgs/settings.service.d.ts +28 -0
  107. package/dist/orgs/settings.service.js +20 -1
  108. package/dist/platform/exclusions.js +38 -3
  109. package/dist/platform/operation.js +6 -2
  110. package/dist/platform/ops/admin.ops.js +8 -2
  111. package/dist/platform/ops/conversations.ops.d.ts +3 -3
  112. package/dist/platform/ops/conversations.ops.js +9 -9
  113. package/dist/platform/ops/devices.ops.d.ts +26 -0
  114. package/dist/platform/ops/devices.ops.js +311 -0
  115. package/dist/platform/ops/org-settings.ops.js +2 -2
  116. package/dist/platform/ops/orgs.ops.js +1 -0
  117. package/dist/platform/ops/ui.ops.d.ts +8 -0
  118. package/dist/platform/ops/ui.ops.js +41 -0
  119. package/dist/platform/platform-ops.module.d.ts +3 -2
  120. package/dist/platform/platform-ops.module.js +8 -5
  121. package/dist/platform/route-schemas.js +6 -3
  122. package/dist/roles/gateway-role.d.ts +3 -3
  123. package/dist/roles/gateway-role.js +4 -4
  124. package/dist/roles/gateway.module.d.ts +1 -1
  125. package/dist/roles/gateway.module.js +5 -5
  126. package/dist/roles/worker.module.js +1 -1
  127. package/dist/runtime/context/build.d.ts +1 -1
  128. package/dist/runtime/context/build.js +6 -6
  129. package/dist/runtime/context/compaction.js +1 -1
  130. package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
  131. package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
  132. package/dist/runtime/maintenance.d.ts +1 -1
  133. package/dist/sandbox/jobs.d.ts +13 -13
  134. package/dist/sandbox/jobs.js +20 -20
  135. package/dist/sandbox/leases.d.ts +9 -9
  136. package/dist/sandbox/leases.js +14 -14
  137. package/dist/sandbox/providers.d.ts +8 -8
  138. package/dist/sandbox/providers.js +8 -8
  139. package/dist/sandbox/sandbox.module.d.ts +1 -1
  140. package/dist/sandbox/sandbox.module.js +1 -1
  141. package/dist/sandbox/sandbox.service.d.ts +76 -76
  142. package/dist/sandbox/sandbox.service.js +230 -230
  143. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  144. package/dist/tools/builtins/builtin-tools.js +5 -5
  145. package/dist/tools/builtins/platform.js +1 -1
  146. package/dist/tools/builtins/sandbox/bash.js +6 -6
  147. package/dist/tools/builtins/sandbox/common.d.ts +25 -25
  148. package/dist/tools/builtins/sandbox/common.js +51 -51
  149. package/dist/tools/builtins/sandbox/edit.js +2 -2
  150. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  151. package/dist/tools/builtins/sandbox/index.js +1 -1
  152. package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
  153. package/dist/tools/builtins/sandbox/task-output.js +10 -10
  154. package/dist/tools/builtins/sandbox/task-stop.js +2 -2
  155. package/dist/tools/builtins/sandbox/write.js +2 -2
  156. package/dist/tools/builtins/skill-load.d.ts +1 -1
  157. package/dist/tools/builtins/skill-load.js +2 -2
  158. package/dist/tools/pipeline.js +4 -3
  159. package/dist/tools/registry.d.ts +2 -2
  160. package/dist/tools/tools.module.js +3 -3
  161. package/dist/ui/admin-ui.controller.d.ts +56 -0
  162. package/dist/ui/admin-ui.controller.js +192 -0
  163. package/dist/ui/arrangement.d.ts +74 -0
  164. package/dist/ui/arrangement.js +98 -0
  165. package/dist/ui/embed-token.d.ts +2 -2
  166. package/dist/ui/embed-token.js +30 -5
  167. package/dist/ui/registry.d.ts +29 -14
  168. package/dist/ui/registry.js +31 -10
  169. package/dist/ui/slots.controller.d.ts +11 -0
  170. package/dist/ui/slots.controller.js +25 -0
  171. package/dist/ui/ui-stream.d.ts +20 -3
  172. package/dist/ui/ui-stream.js +25 -7
  173. package/dist/ui/ui.schemas.d.ts +66 -0
  174. package/dist/ui/ui.schemas.js +65 -0
  175. package/dist/ui/views.controller.d.ts +35 -49
  176. package/dist/ui/views.controller.js +48 -70
  177. package/dist/ui/views.d.ts +84 -18
  178. package/dist/ui/views.js +201 -38
  179. package/package.json +3 -3
  180. package/src/migrations/0105_devices_rename.sql +136 -0
  181. package/dist/devices/device-auth.module.d.ts +0 -7
  182. package/dist/environments/conversation-environments.d.ts +0 -75
  183. package/dist/environments/dto.d.ts +0 -25
  184. package/dist/environments/dto.js +0 -12
  185. package/dist/environments/environments.controller.d.ts +0 -36
  186. package/dist/environments/environments.module.d.ts +0 -8
  187. package/dist/environments/environments.module.js +0 -31
  188. package/dist/environments/environments.schemas.d.ts +0 -3
  189. package/dist/environments/environments.schemas.js +0 -14
  190. package/dist/environments/label.d.ts +0 -11
  191. package/dist/platform/ops/environments.ops.d.ts +0 -26
  192. package/dist/platform/ops/environments.ops.js +0 -311
@@ -53,6 +53,19 @@ export declare const DeploymentSettingsBody: z.ZodObject<{
53
53
  uiTheme: z.ZodOptional<z.ZodObject<{
54
54
  id: z.ZodNullable<z.ZodString>;
55
55
  }, z.core.$strict>>;
56
+ uiArrangement: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
57
+ "agent.detail.section": "agent.detail.section";
58
+ "conversation.panel": "conversation.panel";
59
+ "conversation.properties.section": "conversation.properties.section";
60
+ "conversation.tool-result.card": "conversation.tool-result.card";
61
+ "file.preview": "file.preview";
62
+ "org.page": "org.page";
63
+ "org.settings.section": "org.settings.section";
64
+ "platform.page": "platform.page";
65
+ }> & z.core.$partial, z.ZodNullable<z.ZodObject<{
66
+ hidden: z.ZodArray<z.ZodString>;
67
+ order: z.ZodArray<z.ZodString>;
68
+ }, z.core.$strict>>>>;
56
69
  }, z.core.$strict>;
57
70
  export declare const PurposeParams: z.ZodObject<{
58
71
  purpose: z.ZodString;
@@ -49,6 +49,11 @@ export declare function visibleTo(viewerAccountId: string | null): (eb: Expressi
49
49
  * the live org). Deleted agents are never visible.
50
50
  */
51
51
  export declare function isAgentVisibleTo(db: KernelSchemaDb, agentId: string, accountId: string): Promise<boolean>;
52
+ /**
53
+ * {@link isAgentVisibleTo} for an agent of `orgId` only: an agent the account can read in another
54
+ * org is not visible here (UI slots spec R6, the `agent.detail.section` scope rule).
55
+ */
56
+ export declare function isAgentVisibleIn(db: KernelSchemaDb, orgId: string, agentId: string, accountId: string): Promise<boolean>;
52
57
  /**
53
58
  * Reads agents for a viewer (the visibility rule {@link visibleTo}): the part of `AgentsService`
54
59
  * the conversations, the skill invoker and the attachments read, with no dependency on the
@@ -67,6 +67,21 @@ export async function isAgentVisibleTo(db, agentId, accountId) {
67
67
  .executeTakeFirst();
68
68
  return row !== undefined;
69
69
  }
70
+ /**
71
+ * {@link isAgentVisibleTo} for an agent of `orgId` only: an agent the account can read in another
72
+ * org is not visible here (UI slots spec R6, the `agent.detail.section` scope rule).
73
+ */
74
+ export async function isAgentVisibleIn(db, orgId, agentId, accountId) {
75
+ const row = await db
76
+ .selectFrom("agents")
77
+ .select("id")
78
+ .where("id", "=", agentId)
79
+ .where("org_id", "=", orgId)
80
+ .where("deleted_at", "is", null)
81
+ .where(visibleTo(accountId))
82
+ .executeTakeFirst();
83
+ return row !== undefined;
84
+ }
70
85
  /**
71
86
  * Reads agents for a viewer (the visibility rule {@link visibleTo}): the part of `AgentsService`
72
87
  * the conversations, the skill invoker and the attachments read, with no dependency on the
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { Module } from "@nestjs/common";
8
8
  import { ConversationAccessModule } from "../conversations/access.js";
9
9
  import { EventLogModule } from "../conversations/event-log.js";
10
- import { EnvironmentsModule } from "../environments/environments.module.js";
10
+ import { DevicesModule } from "../devices/devices.module.js";
11
11
  import { SandboxModule } from "../sandbox/sandbox.module.js";
12
12
  import { BackgroundTaskFinisher } from "./finish.js";
13
13
  import { BackgroundTaskStopper } from "./stop.js";
@@ -28,7 +28,7 @@ BackgroundModule = __decorate([
28
28
  imports: [
29
29
  BackgroundStoreModule,
30
30
  SandboxModule,
31
- EnvironmentsModule,
31
+ DevicesModule,
32
32
  EventLogModule,
33
33
  ConversationAccessModule,
34
34
  ],
@@ -3,7 +3,7 @@ import { XactLock } from "../infra/database/xact-lock.js";
3
3
  /**
4
4
  * The launch lock of one root conversation (decision R9: one provider per transaction-scoped
5
5
  * lock): serializes background task reservations in its tree, so the count of running tasks
6
- * checked against `sandbox.background.maxTasks` (per root conversation, whatever environment it
6
+ * checked against `sandbox.background.maxTasks` (per root conversation, whatever device it
7
7
  * works in) and the insert of the new row are one step. Joins the
8
8
  * caller's transaction (`mandatory`), which holds it until it ends.
9
9
  */
@@ -14,7 +14,7 @@ import { XactLock } from "../infra/database/xact-lock.js";
14
14
  /**
15
15
  * The launch lock of one root conversation (decision R9: one provider per transaction-scoped
16
16
  * lock): serializes background task reservations in its tree, so the count of running tasks
17
- * checked against `sandbox.background.maxTasks` (per root conversation, whatever environment it
17
+ * checked against `sandbox.background.maxTasks` (per root conversation, whatever device it
18
18
  * works in) and the insert of the new row are one step. Joins the
19
19
  * caller's transaction (`mandatory`), which holds it until it ends.
20
20
  */
@@ -21,7 +21,7 @@ export declare const launchAbandonedAfterMs: (cfg: KernelConfig) => number;
21
21
  /**
22
22
  * The worker's background task jobs (spec 2026-11-05-background-bash-design §4.3), each once per
23
23
  * tick across replicas:
24
- * - `background-task-poll` (every `sandbox.background.pollSeconds`): for every environment
24
+ * - `background-task-poll` (every `sandbox.background.pollSeconds`): for every device
25
25
  * instance with running tasks (of any conversation using it), one exec through
26
26
  * `SandboxService.ifRunning` (which never creates or resumes an instance) reports each task's
27
27
  * exit file and liveness; ended tasks finish through {@link BackgroundTaskFinisher}. Each poll
@@ -47,7 +47,7 @@ export declare class BackgroundTaskPollJob {
47
47
  * result: they never started), with a `changed: "background"` frame to their conversations.
48
48
  */
49
49
  pollOnce(signal?: AbortSignal): Promise<number>;
50
- /** Polls the tasks of one environment instance; returns how many finished. */
50
+ /** Polls the tasks of one device instance; returns how many finished. */
51
51
  private pollSandbox;
52
52
  /** The poll exec of one instance: each task's report by id. */
53
53
  private pollExec;
@@ -44,7 +44,7 @@ const POLL_MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
44
44
  /**
45
45
  * The worker's background task jobs (spec 2026-11-05-background-bash-design §4.3), each once per
46
46
  * tick across replicas:
47
- * - `background-task-poll` (every `sandbox.background.pollSeconds`): for every environment
47
+ * - `background-task-poll` (every `sandbox.background.pollSeconds`): for every device
48
48
  * instance with running tasks (of any conversation using it), one exec through
49
49
  * `SandboxService.ifRunning` (which never creates or resumes an instance) reports each task's
50
50
  * exit file and liveness; ended tasks finish through {@link BackgroundTaskFinisher}. Each poll
@@ -93,8 +93,8 @@ let BackgroundTaskPollJob = class BackgroundTaskPollJob {
93
93
  for (const t of await this.store.runningStarted()) {
94
94
  if (t.sid === null || t.sandboxCreatedAt === null)
95
95
  continue;
96
- // one exec per instance: the tasks of every conversation sharing the environment
97
- const key = `${t.environmentId} ${t.sandboxCreatedAt.getTime()}`;
96
+ // one exec per instance: the tasks of every conversation sharing the device
97
+ const key = `${t.deviceId} ${t.sandboxCreatedAt.getTime()}`;
98
98
  groups.set(key, [...(groups.get(key) ?? []), t]);
99
99
  }
100
100
  let finished = 0;
@@ -102,9 +102,9 @@ let BackgroundTaskPollJob = class BackgroundTaskPollJob {
102
102
  if (signal.aborted)
103
103
  break;
104
104
  try {
105
- // the environment's provider is not there (no cloud provider, `@device` not served):
105
+ // the device's provider is not there (no cloud provider, `@local` not served):
106
106
  // its tasks stay as they are until it is
107
- const env = tasks[0]?.environmentId ?? null;
107
+ const env = tasks[0]?.deviceId ?? null;
108
108
  if (env === null ? !this.sandbox.cloudAvailable : !(await this.sandbox.availableFor(env))) {
109
109
  continue;
110
110
  }
@@ -114,7 +114,7 @@ let BackgroundTaskPollJob = class BackgroundTaskPollJob {
114
114
  if (signal.aborted)
115
115
  break;
116
116
  this.log.warn("cannot poll background tasks; retrying next tick", {
117
- environmentId: tasks[0]?.environmentId,
117
+ deviceId: tasks[0]?.deviceId,
118
118
  err,
119
119
  });
120
120
  }
@@ -123,13 +123,13 @@ let BackgroundTaskPollJob = class BackgroundTaskPollJob {
123
123
  this.log.info("background tasks finished", { count: finished });
124
124
  return finished;
125
125
  }
126
- /** Polls the tasks of one environment instance; returns how many finished. */
126
+ /** Polls the tasks of one device instance; returns how many finished. */
127
127
  async pollSandbox(tasks, signal) {
128
128
  const [first] = tasks;
129
- // a task from before environments has no instance any more
130
- const r = first.environmentId === null
129
+ // a task from before devices has no instance any more
130
+ const r = first.deviceId === null
131
131
  ? { kind: "not_running", status: "gone" }
132
- : await this.sandbox.ifRunning(first.environmentId, { createdAt: first.sandboxCreatedAt }, (p, h, sig) => this.pollExec(actingAs(p, taskActor(first)), h, tasks, sig), signal);
132
+ : await this.sandbox.ifRunning(first.deviceId, { createdAt: first.sandboxCreatedAt }, (p, h, sig) => this.pollExec(actingAs(p, taskActor(first)), h, tasks, sig), signal);
133
133
  const now = new Date();
134
134
  let n = 0;
135
135
  for (const t of tasks) {
@@ -43,7 +43,7 @@ export declare class BackgroundTaskStopper {
43
43
  stop(task: BackgroundTaskRow, why: StopReason, signal?: AbortSignal): Promise<BackgroundTaskRow>;
44
44
  /**
45
45
  * SIGTERM, the grace period, SIGKILL until the session is empty, then the last lines: in the
46
- * task's own instance only (`ifRunning`); a task from before environments has none.
46
+ * task's own instance only (`ifRunning`); a task from before devices has none.
47
47
  */
48
48
  private signalTask;
49
49
  /**
@@ -138,12 +138,12 @@ let BackgroundTaskStopper = class BackgroundTaskStopper {
138
138
  }
139
139
  /**
140
140
  * SIGTERM, the grace period, SIGKILL until the session is empty, then the last lines: in the
141
- * task's own instance only (`ifRunning`); a task from before environments has none.
141
+ * task's own instance only (`ifRunning`); a task from before devices has none.
142
142
  */
143
143
  async signalTask(cur, sid, signal) {
144
- if (cur.environmentId === null)
144
+ if (cur.deviceId === null)
145
145
  return { kind: "not_running", status: "gone" };
146
- return this.sandbox.ifRunning(cur.environmentId, { createdAt: cur.sandboxCreatedAt }, async (tp, h, sig) => {
146
+ return this.sandbox.ifRunning(cur.deviceId, { createdAt: cur.sandboxCreatedAt }, async (tp, h, sig) => {
147
147
  const p = actingAs(tp, taskActor(cur));
148
148
  const term = await p.exec(h, {
149
149
  command: termScript(cur.id, sid),
@@ -14,10 +14,10 @@ export interface BackgroundTaskRow {
14
14
  */
15
15
  sandboxConversationId: string;
16
16
  /**
17
- * The environment the task runs in (the root conversation's when it was launched): its instance
18
- * is where the task's processes are. Null only for tasks from before environments (all finished).
17
+ * The device the task runs in (the root conversation's when it was launched): its instance
18
+ * is where the task's processes are. Null only for tasks from before devices (all finished).
19
19
  */
20
- environmentId: string | null;
20
+ deviceId: string | null;
21
21
  runId: string;
22
22
  callId: string;
23
23
  triggerAccountId: string;
@@ -157,10 +157,10 @@ export declare class BackgroundTaskStore {
157
157
  /** Moves the read offset forward only (a concurrent reader never moves it back). */
158
158
  advanceOffset(id: string, to: number): Promise<void>;
159
159
  /**
160
- * Finished tasks of an environment whose process may still exist (any conversation's: they
160
+ * Finished tasks of a device whose process may still exist (any conversation's: they
161
161
  * share the instance).
162
162
  */
163
- pendingKills(environmentId: string): Promise<BackgroundTaskRow[]>;
163
+ pendingKills(deviceId: string): Promise<BackgroundTaskRow[]>;
164
164
  clearKill(ids: string[]): Promise<void>;
165
165
  /** Deletes finished tasks that ended before `before`; a running one is never deleted. */
166
166
  pruneFinished(before: Date): Promise<number>;
@@ -18,7 +18,7 @@ const toRow = (r) => ({
18
18
  orgId: r.org_id,
19
19
  conversationId: r.conversation_id,
20
20
  sandboxConversationId: r.sandbox_conversation_id,
21
- environmentId: r.environment_id,
21
+ deviceId: r.device_id,
22
22
  runId: r.run_id,
23
23
  callId: r.call_id,
24
24
  triggerAccountId: r.trigger_account_id,
@@ -195,7 +195,7 @@ let BackgroundTaskStore = class BackgroundTaskStore {
195
195
  org_id: row.orgId,
196
196
  conversation_id: row.conversationId,
197
197
  sandbox_conversation_id: row.sandboxConversationId,
198
- environment_id: row.environmentId,
198
+ device_id: row.deviceId,
199
199
  run_id: row.runId,
200
200
  call_id: row.callId,
201
201
  trigger_account_id: row.triggerAccountId,
@@ -314,14 +314,14 @@ let BackgroundTaskStore = class BackgroundTaskStore {
314
314
  .execute();
315
315
  }
316
316
  /**
317
- * Finished tasks of an environment whose process may still exist (any conversation's: they
317
+ * Finished tasks of a device whose process may still exist (any conversation's: they
318
318
  * share the instance).
319
319
  */
320
- async pendingKills(environmentId) {
320
+ async pendingKills(deviceId) {
321
321
  const rows = await this.db
322
322
  .selectFrom("background_tasks")
323
323
  .selectAll()
324
- .where("environment_id", "=", environmentId)
324
+ .where("device_id", "=", deviceId)
325
325
  .where("kill_pending", "=", true)
326
326
  .orderBy("started_at", "asc")
327
327
  .execute();
@@ -1,6 +1,6 @@
1
1
  import { ConversationAccess } from "../conversations/access.js";
2
2
  import { EventLog } from "../conversations/event-log.js";
3
- import { ConversationEnvironments } from "../environments/conversation-environments.js";
3
+ import { ConversationDevices } from "../devices/conversation-devices.js";
4
4
  import { KernelDb } from "../infra/database/kernel-db.js";
5
5
  import { SandboxService } from "../sandbox/sandbox.service.js";
6
6
  import { BackgroundTaskStopper } from "./stop.js";
@@ -45,8 +45,8 @@ export declare class BackgroundTasks {
45
45
  private readonly sandbox;
46
46
  private readonly eventLog;
47
47
  private readonly db;
48
- private readonly environments;
49
- constructor(access: Pick<ConversationAccess, "isAccessible">, store: Pick<BackgroundTaskStore, "listFor" | "get">, stopper: Pick<BackgroundTaskStopper, "stop">, sandbox: Pick<SandboxService, "availableFor" | "ifRunning">, eventLog: Pick<EventLog, "findByIdem">, db: KernelDb, environments: Pick<ConversationEnvironments, "forTool">);
48
+ private readonly devices;
49
+ constructor(access: Pick<ConversationAccess, "isAccessible">, store: Pick<BackgroundTaskStore, "listFor" | "get">, stopper: Pick<BackgroundTaskStopper, "stop">, sandbox: Pick<SandboxService, "availableFor" | "ifRunning">, eventLog: Pick<EventLog, "findByIdem">, db: KernelDb, devices: Pick<ConversationDevices, "forTool">);
50
50
  /**
51
51
  * The conversation and every sub-agent conversation below it (grandchildren too: their tasks run
52
52
  * in the root's sandbox, agent map spec §6); `conversation.not_found` when not visible.
@@ -63,12 +63,12 @@ export declare class BackgroundTasks {
63
63
  */
64
64
  stop(orgId: string, conversationId: string, accountId: string, taskId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<BackgroundTaskView>;
65
65
  /**
66
- * Whether the task's environment may still be used by its conversation's owner (the access
66
+ * Whether the task's device may still be used by its conversation's owner (the access
67
67
  * re-check every sandbox tool call makes); when it may not, the live read is skipped.
68
68
  */
69
- private environmentUsable;
69
+ private deviceUsable;
70
70
  /**
71
- * The end of the task's output, at most `tail` bytes. Read live when the task's environment
71
+ * The end of the task's output, at most `tail` bytes. Read live when the task's device
72
72
  * instance runs (never resuming a suspended one); a finished task whose sandbox does not run answers
73
73
  * with the last lines its finished event kept. Anything else is
74
74
  * `background_task.output_unavailable` (409).
@@ -12,7 +12,7 @@ import { Inject, Injectable } from "@nestjs/common";
12
12
  import { ConversationAccess } from "../conversations/access.js";
13
13
  import { EventLog } from "../conversations/event-log.js";
14
14
  import { conversationTree } from "../conversations/tree.js";
15
- import { ConversationEnvironments } from "../environments/conversation-environments.js";
15
+ import { ConversationDevices } from "../devices/conversation-devices.js";
16
16
  import { ApiError } from "../errors.js";
17
17
  import { audit } from "../identity/audit.js";
18
18
  import { KernelDb } from "../infra/database/kernel-db.js";
@@ -44,15 +44,15 @@ let BackgroundTasks = class BackgroundTasks {
44
44
  sandbox;
45
45
  eventLog;
46
46
  db;
47
- environments;
48
- constructor(access, store, stopper, sandbox, eventLog, db, environments) {
47
+ devices;
48
+ constructor(access, store, stopper, sandbox, eventLog, db, devices) {
49
49
  this.access = access;
50
50
  this.store = store;
51
51
  this.stopper = stopper;
52
52
  this.sandbox = sandbox;
53
53
  this.eventLog = eventLog;
54
54
  this.db = db;
55
- this.environments = environments;
55
+ this.devices = devices;
56
56
  }
57
57
  /**
58
58
  * The conversation and every sub-agent conversation below it (grandchildren too: their tasks run
@@ -119,12 +119,12 @@ let BackgroundTasks = class BackgroundTasks {
119
119
  return this.view(after, conversationId);
120
120
  }
121
121
  /**
122
- * Whether the task's environment may still be used by its conversation's owner (the access
122
+ * Whether the task's device may still be used by its conversation's owner (the access
123
123
  * re-check every sandbox tool call makes); when it may not, the live read is skipped.
124
124
  */
125
- async environmentUsable(orgId, taskConversationId) {
125
+ async deviceUsable(orgId, taskConversationId) {
126
126
  try {
127
- await this.environments.forTool(orgId, await rootConversationOf(this.db.db, taskConversationId));
127
+ await this.devices.forTool(orgId, await rootConversationOf(this.db.db, taskConversationId));
128
128
  return true;
129
129
  }
130
130
  catch (e) {
@@ -134,7 +134,7 @@ let BackgroundTasks = class BackgroundTasks {
134
134
  }
135
135
  }
136
136
  /**
137
- * The end of the task's output, at most `tail` bytes. Read live when the task's environment
137
+ * The end of the task's output, at most `tail` bytes. Read live when the task's device
138
138
  * instance runs (never resuming a suspended one); a finished task whose sandbox does not run answers
139
139
  * with the last lines its finished event kept. Anything else is
140
140
  * `background_task.output_unavailable` (409).
@@ -143,14 +143,14 @@ let BackgroundTasks = class BackgroundTasks {
143
143
  const task = await this.owned(orgId, conversationId, accountId, taskId);
144
144
  if (task.sid !== null &&
145
145
  task.sandboxCreatedAt !== null &&
146
- task.environmentId !== null &&
147
- (await this.sandbox.availableFor(task.environmentId)) &&
148
- (await this.environmentUsable(orgId, task.conversationId))) {
146
+ task.deviceId !== null &&
147
+ (await this.sandbox.availableFor(task.deviceId)) &&
148
+ (await this.deviceUsable(orgId, task.conversationId))) {
149
149
  const createdAt = task.sandboxCreatedAt;
150
150
  // the person reading it acts in the task's conversation
151
151
  const actor = { accountId, conversationId: task.conversationId };
152
152
  try {
153
- const r = await this.sandbox.ifRunning(task.environmentId, { createdAt }, async (p, h, signal) => {
153
+ const r = await this.sandbox.ifRunning(task.deviceId, { createdAt }, async (p, h, signal) => {
154
154
  const res = await actingAs(p, actor).exec(h, {
155
155
  command: tailScript(task.id, tail),
156
156
  cwd: rootsOf(h).workspace,
@@ -185,7 +185,7 @@ BackgroundTasks = __decorate([
185
185
  __param(3, Inject(SandboxService)),
186
186
  __param(4, Inject(EventLog)),
187
187
  __param(5, Inject(KernelDb)),
188
- __param(6, Inject(ConversationEnvironments))
188
+ __param(6, Inject(ConversationDevices))
189
189
  ], BackgroundTasks);
190
190
  export { BackgroundTasks };
191
191
  /** Prints `size <bytes>` and `out <base64 of the last `tail` bytes>`. Relative to the workspace root. */
@@ -188,7 +188,7 @@ export declare function headsToResolve(entries: readonly MarketplaceEntry[], imp
188
188
  /** The host versions (an entry's `minKernel` is judged against them). */
189
189
  export declare const HOST_VERSIONS: {
190
190
  readonly kernel: string;
191
- readonly sdk: "0.1.0-rc.8";
191
+ readonly sdk: "0.1.0-rc.9";
192
192
  };
193
193
  /** Whether this deployment satisfies the entry's `minKernel`. */
194
194
  export declare const entryCompatible: (e: Pick<MarketplaceEntry, "minKernel">) => boolean;
@@ -12,7 +12,7 @@ import { OnWorkerEvent, WorkerHost } from "@nestjs/bullmq";
12
12
  import { Inject, Injectable, Module } from "@nestjs/common";
13
13
  import { ConversationsModule } from "../conversations/conversations.module.js";
14
14
  import { EventLogModule } from "../conversations/event-log.js";
15
- import { EnvironmentsModule } from "../environments/environments.module.js";
15
+ import { DevicesModule } from "../devices/devices.module.js";
16
16
  import { ExtensionsModule } from "../extensions/extensions.module.js";
17
17
  import { IdentityModule } from "../identity/identity.module.js";
18
18
  import { configuredProcessor, } from "../infra/queue/configured-processor.js";
@@ -39,7 +39,7 @@ let ChannelsModule = class ChannelsModule {
39
39
  ChannelsModule = __decorate([
40
40
  Module({
41
41
  imports: [
42
- EnvironmentsModule,
42
+ DevicesModule,
43
43
  EventLogModule,
44
44
  ExtensionsModule,
45
45
  IdentityModule,
@@ -1,7 +1,7 @@
1
1
  import type { ChannelCard, InboundEvent, InboundSender, Logger } from "@capybara-hq/plugin-sdk";
2
2
  import type { Redis } from "ioredis";
3
3
  import { ConversationsService } from "../conversations/conversations.service.js";
4
- import { EnvironmentsService } from "../environments/environments.service.js";
4
+ import { DevicesService } from "../devices/devices.service.js";
5
5
  import { IdentityBinding } from "../identity/binding.js";
6
6
  import { ExternalIdentities } from "../identity/external.js";
7
7
  import { KernelDb } from "../infra/database/kernel-db.js";
@@ -63,7 +63,7 @@ export declare class ChannelInbound {
63
63
  /** The channel queue: inbound jobs (`onEvent` only dedupes and enqueues) and deliveries. */
64
64
  private readonly jobs;
65
65
  private readonly guests;
66
- private readonly environments;
66
+ private readonly devices;
67
67
  private readonly log;
68
68
  private readonly actions;
69
69
  constructor(kdb: KernelDb, redis: Pick<Redis, "set">,
@@ -74,7 +74,7 @@ export declare class ChannelInbound {
74
74
  /** The channel queue: inbound jobs (`onEvent` only dedupes and enqueues) and deliveries. */
75
75
  jobs: Pick<ChannelJobs, "enqueue" | "enqueueInbound">,
76
76
  /** 卡片操作:审批决定与提问回答(授权由这两个服务按点击者映射到的账号判定)。 */
77
- approvals: Pick<ApprovalsService, "decide">, questions: Pick<QuestionsService, "answer">, guests: Pick<AnonymousGuests, "ensure">, environments: Pick<EnvironmentsService, "list" | "imDefault" | "setImDefault">, log: Pick<Logger, "warn" | "info">);
77
+ approvals: Pick<ApprovalsService, "decide">, questions: Pick<QuestionsService, "answer">, guests: Pick<AnonymousGuests, "ensure">, devices: Pick<DevicesService, "list" | "imDefault" | "setImDefault">, log: Pick<Logger, "warn" | "info">);
78
78
  /**
79
79
  * 插件 `onEvent`:去重并入队后返回(见类注释)。返回后插件才向平台确认;抛错时插件不确认。
80
80
  */
@@ -95,13 +95,13 @@ export declare class ChannelInbound {
95
95
  handle(connectionId: string, e: InboundEvent): Promise<void>;
96
96
  private message;
97
97
  /**
98
- * Direct-message `/env` (environments spec §4.2 item 8): lists the person's usable environments,
98
+ * Direct-message `/device` (environments spec §4.2 item 8): lists the person's usable devices,
99
99
  * or with a name sets the IM default their next new conversation is bound to. The name matches
100
- * case-insensitively against each label (`environmentLabel`: a former default demoted by a
101
- * provider switch answers to e.g. "Personal (Docker sandbox)"); the default environment also
102
- * answers to 个人环境 / Personal.
100
+ * case-insensitively against each label (`deviceLabel`: a former default demoted by a
101
+ * provider switch answers to e.g. "Personal (Docker sandbox)"); the default device also
102
+ * answers to 个人设备 / Personal.
103
103
  */
104
- private envCommand;
104
+ private deviceCommand;
105
105
  /**
106
106
  * Posts the person's message: `/name args` as a skill invocation when the kernel accepts it, else
107
107
  * as typed (phase D spec §9). A retry of the job finds the first write by `clientMessageId`
@@ -11,8 +11,8 @@ import { randomUUID } from "node:crypto";
11
11
  import { Inject, Injectable } from "@nestjs/common";
12
12
  import { ConversationsService } from "../conversations/conversations.service.js";
13
13
  import { imSenderContext, recipientLocale, } from "../conversations/message-context.js";
14
- import { EnvironmentsService } from "../environments/environments.service.js";
15
- import { DEFAULT_ENVIRONMENT_ALIASES, environmentLabel } from "../environments/label.js";
14
+ import { DevicesService } from "../devices/devices.service.js";
15
+ import { DEFAULT_DEVICE_ALIASES, deviceLabel } from "../devices/label.js";
16
16
  import { ApiError } from "../errors.js";
17
17
  import { IdentityBinding } from "../identity/binding.js";
18
18
  import { ExternalIdentities } from "../identity/external.js";
@@ -75,7 +75,7 @@ let ChannelInbound = class ChannelInbound {
75
75
  directorySync;
76
76
  jobs;
77
77
  guests;
78
- environments;
78
+ devices;
79
79
  log;
80
80
  actions;
81
81
  constructor(kdb, redis,
@@ -86,7 +86,7 @@ let ChannelInbound = class ChannelInbound {
86
86
  /** The channel queue: inbound jobs (`onEvent` only dedupes and enqueues) and deliveries. */
87
87
  jobs,
88
88
  /** 卡片操作:审批决定与提问回答(授权由这两个服务按点击者映射到的账号判定)。 */
89
- approvals, questions, guests, environments, log) {
89
+ approvals, questions, guests, devices, log) {
90
90
  this.kdb = kdb;
91
91
  this.redis = redis;
92
92
  this.locks = locks;
@@ -97,7 +97,7 @@ let ChannelInbound = class ChannelInbound {
97
97
  this.directorySync = directorySync;
98
98
  this.jobs = jobs;
99
99
  this.guests = guests;
100
- this.environments = environments;
100
+ this.devices = devices;
101
101
  this.log = log;
102
102
  this.actions = new ChannelCardActions({
103
103
  get db() {
@@ -216,16 +216,16 @@ let ChannelInbound = class ChannelInbound {
216
216
  await reply("newConversation");
217
217
  return;
218
218
  }
219
- const envCommand = !isGroup && threadAccount !== null ? parseEnvCommand(e.text) : null;
220
- if (envCommand !== null) {
221
- await this.envCommand(row.orgId, accountId, envCommand.name, locale, replyText);
219
+ const deviceCommand = !isGroup && threadAccount !== null ? parseDeviceCommand(e.text) : null;
220
+ if (deviceCommand !== null) {
221
+ await this.deviceCommand(row.orgId, accountId, deviceCommand.name, locale, replyText);
222
222
  return;
223
223
  }
224
224
  let conversationId = await findThread(db, k);
225
225
  if (conversationId === undefined) {
226
226
  let created;
227
227
  try {
228
- // bound to the person's IM default environment, else their default (environments spec
228
+ // bound to the person's IM default device, else their default (environments spec
229
229
  // §4.2 item 8); an anonymous sender's stays unbound (no sandbox)
230
230
  created = (await this.conversations.create(row.orgId, accountId, row.agentId, { im: true }))
231
231
  .id;
@@ -294,49 +294,49 @@ let ChannelInbound = class ChannelInbound {
294
294
  await this.jobs.enqueue(conversationId);
295
295
  }
296
296
  /**
297
- * Direct-message `/env` (environments spec §4.2 item 8): lists the person's usable environments,
297
+ * Direct-message `/device` (environments spec §4.2 item 8): lists the person's usable devices,
298
298
  * or with a name sets the IM default their next new conversation is bound to. The name matches
299
- * case-insensitively against each label (`environmentLabel`: a former default demoted by a
300
- * provider switch answers to e.g. "Personal (Docker sandbox)"); the default environment also
301
- * answers to 个人环境 / Personal.
299
+ * case-insensitively against each label (`deviceLabel`: a former default demoted by a
300
+ * provider switch answers to e.g. "Personal (Docker sandbox)"); the default device also
301
+ * answers to 个人设备 / Personal.
302
302
  */
303
- async envCommand(orgId, accountId, name, locale, replyText) {
304
- const { items, defaultId } = await this.environments.list(orgId, accountId);
303
+ async deviceCommand(orgId, accountId, name, locale, replyText) {
304
+ const { items, defaultId } = await this.devices.list(orgId, accountId);
305
305
  const usable = items.filter((v) => v.available);
306
- const labelOf = (v) => environmentLabel(v, locale);
307
- const current = (await this.environments.imDefault(orgId, accountId)) ?? defaultId;
306
+ const labelOf = (v) => deviceLabel(v, locale);
307
+ const current = (await this.devices.imDefault(orgId, accountId)) ?? defaultId;
308
308
  const list = usable
309
- .map((v) => `- ${labelOf(v)}${v.id === current ? phrase("envCurrent", locale) : ""}`)
309
+ .map((v) => `- ${labelOf(v)}${v.id === current ? phrase("deviceCurrent", locale) : ""}`)
310
310
  .join("\n");
311
311
  const fill = (key, vars) => phrase(key, locale).replace(/\{(\w+)\}/g, (m, k) => vars[k] ?? m);
312
312
  if (usable.length === 0)
313
- return replyText(phrase("envNone", locale));
313
+ return replyText(phrase("deviceNone", locale));
314
314
  if (name === null)
315
- return replyText(fill("envList", { list }));
315
+ return replyText(fill("deviceList", { list }));
316
316
  const wanted = name.toLowerCase();
317
317
  const is = (v) => labelOf(v).toLowerCase() === wanted;
318
318
  // a name the person gave wins over a generated label, and both over the default's aliases
319
319
  const hit = usable.find((v) => v.name !== null && is(v)) ??
320
320
  usable.find(is) ??
321
- usable.find((v) => v.isDefault && DEFAULT_ENVIRONMENT_ALIASES.includes(wanted));
321
+ usable.find((v) => v.isDefault && DEFAULT_DEVICE_ALIASES.includes(wanted));
322
322
  if (hit === undefined) {
323
323
  const unavailable = items.find((v) => !v.available && is(v));
324
324
  if (unavailable !== undefined) {
325
- return replyText(fill("envUnavailable", { name: labelOf(unavailable), list }));
325
+ return replyText(fill("deviceUnavailable", { name: labelOf(unavailable), list }));
326
326
  }
327
- return replyText(fill("envUnknown", { name, list }));
327
+ return replyText(fill("deviceUnknown", { name, list }));
328
328
  }
329
329
  try {
330
- await this.environments.setImDefault(orgId, accountId, hit.id);
330
+ await this.devices.setImDefault(orgId, accountId, hit.id);
331
331
  }
332
332
  catch (err) {
333
333
  // deleted or made unusable since the list was read
334
- if (err instanceof ApiError && err.code.startsWith("environment.")) {
335
- return replyText(fill("envUnknown", { name, list }));
334
+ if (err instanceof ApiError && err.code.startsWith("device.")) {
335
+ return replyText(fill("deviceUnknown", { name, list }));
336
336
  }
337
337
  throw err;
338
338
  }
339
- return replyText(fill("envSwitched", { name: labelOf(hit) }));
339
+ return replyText(fill("deviceSwitched", { name: labelOf(hit) }));
340
340
  }
341
341
  /**
342
342
  * Posts the person's message: `/name args` as a skill invocation when the kernel accepts it, else
@@ -464,13 +464,13 @@ ChannelInbound = __decorate([
464
464
  __param(9, Inject(ApprovalsService)),
465
465
  __param(10, Inject(QuestionsService)),
466
466
  __param(11, Inject(AnonymousGuests)),
467
- __param(12, Inject(EnvironmentsService)),
467
+ __param(12, Inject(DevicesService)),
468
468
  __param(13, Inject(KERNEL_LOGGER))
469
469
  ], ChannelInbound);
470
470
  export { ChannelInbound };
471
- /** `/env` or `/env <name>` (the exact command word, case-insensitive); anything else is null. */
472
- function parseEnvCommand(text) {
473
- const m = /^\/env(?:\s+([\s\S]*))?$/i.exec(text.trim());
471
+ /** `/device` or `/device <name>` (the exact command word, case-insensitive); anything else is null. */
472
+ function parseDeviceCommand(text) {
473
+ const m = /^\/device(?:\s+([\s\S]*))?$/i.exec(text.trim());
474
474
  if (m === null)
475
475
  return null;
476
476
  const name = m[1]?.trim();