@capybara-hq/kernel 0.1.0-rc.12 → 0.1.0-rc.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) 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/admin-catalog.controller.d.ts +13 -2
  16. package/dist/catalog/admin-catalog.controller.js +24 -3
  17. package/dist/catalog/admin-catalog.schemas.d.ts +10 -0
  18. package/dist/catalog/admin-catalog.schemas.js +7 -0
  19. package/dist/catalog/catalog-content.d.ts +9 -1
  20. package/dist/catalog/catalog-content.js +2 -1
  21. package/dist/catalog/catalog-files.d.ts +3 -2
  22. package/dist/catalog/catalog-files.js +8 -5
  23. package/dist/catalog/component-scope.service.d.ts +14 -1
  24. package/dist/catalog/component-scope.service.js +12 -2
  25. package/dist/catalog/marketplaces.service.d.ts +1 -1
  26. package/dist/catalog/org-catalog.controller.d.ts +5 -4
  27. package/dist/catalog/org-catalog.controller.js +5 -4
  28. package/dist/catalog/org-catalog.schemas.d.ts +18 -2
  29. package/dist/catalog/org-catalog.schemas.js +16 -2
  30. package/dist/catalog/org-catalog.service.js +8 -2
  31. package/dist/catalog/plugin-import.js +1 -1
  32. package/dist/catalog/plugin-package.js +37 -9
  33. package/dist/catalog/plugin-upgrade.d.ts +15 -1
  34. package/dist/catalog/plugin-upgrade.js +18 -5
  35. package/dist/channels/channels.module.js +2 -2
  36. package/dist/channels/connections.controller.d.ts +1 -1
  37. package/dist/channels/connections.controller.js +1 -1
  38. package/dist/channels/connections.service.d.ts +22 -5
  39. package/dist/channels/connections.service.js +56 -10
  40. package/dist/channels/inbound.d.ts +8 -8
  41. package/dist/channels/inbound.js +31 -31
  42. package/dist/channels/phrases.d.ts +27 -27
  43. package/dist/channels/phrases.js +27 -27
  44. package/dist/channels/webhook.d.ts +21 -1
  45. package/dist/channels/webhook.js +39 -4
  46. package/dist/config/docs.js +1 -1
  47. package/dist/config/schema.d.ts +2 -2
  48. package/dist/config/schema.js +21 -21
  49. package/dist/conversations/conversations.controller.d.ts +11 -11
  50. package/dist/conversations/conversations.controller.js +15 -15
  51. package/dist/conversations/conversations.module.d.ts +1 -1
  52. package/dist/conversations/conversations.module.js +7 -7
  53. package/dist/conversations/conversations.schemas.js +1 -1
  54. package/dist/conversations/conversations.service.d.ts +14 -14
  55. package/dist/conversations/conversations.service.js +19 -19
  56. package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
  57. package/dist/conversations/{environment-status.js → device-status.js} +18 -18
  58. package/dist/conversations/event-log.d.ts +1 -1
  59. package/dist/conversations/event-log.js +1 -1
  60. package/dist/conversations/events.d.ts +1 -1
  61. package/dist/conversations/events.js +2 -2
  62. package/dist/ctx/create-ctx.d.ts +26 -3
  63. package/dist/ctx/create-ctx.js +134 -26
  64. package/dist/db/kernel-schema.d.ts +37 -25
  65. package/dist/{environments → devices}/access.d.ts +19 -19
  66. package/dist/{environments → devices}/access.js +28 -28
  67. package/dist/devices/conversation-devices.d.ts +75 -0
  68. package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
  69. package/dist/devices/devices.controller.d.ts +36 -0
  70. package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
  71. package/dist/devices/devices.module.d.ts +5 -13
  72. package/dist/devices/devices.module.js +16 -29
  73. package/dist/devices/devices.schemas.d.ts +3 -0
  74. package/dist/devices/devices.schemas.js +14 -0
  75. package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
  76. package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
  77. package/dist/devices/dto.d.ts +13 -54
  78. package/dist/devices/dto.js +7 -39
  79. package/dist/devices/label.d.ts +11 -0
  80. package/dist/{environments → devices}/label.js +7 -7
  81. package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
  82. package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
  83. package/dist/errors.d.ts +29 -25
  84. package/dist/errors.js +29 -25
  85. package/dist/evals/recorded-tools.d.ts +2 -2
  86. package/dist/evals/recorded-tools.js +6 -6
  87. package/dist/extensions/admin-ops.js +1 -0
  88. package/dist/extensions/admin-view.js +2 -0
  89. package/dist/extensions/effective-config.d.ts +6 -0
  90. package/dist/extensions/effective-config.js +18 -7
  91. package/dist/extensions/guide-places.d.ts +66 -0
  92. package/dist/extensions/guide-places.js +152 -0
  93. package/dist/extensions/host.d.ts +13 -2
  94. package/dist/extensions/host.js +27 -6
  95. package/dist/extensions/instance.d.ts +17 -2
  96. package/dist/extensions/instance.js +21 -0
  97. package/dist/extensions/ledger.d.ts +1 -1
  98. package/dist/extensions/permission-set.d.ts +16 -2
  99. package/dist/extensions/permission-set.js +17 -3
  100. package/dist/extensions/permission-view.d.ts +10 -1
  101. package/dist/extensions/plugin-guides.d.ts +207 -54
  102. package/dist/extensions/plugin-guides.js +436 -165
  103. package/dist/files/previewers.d.ts +1 -1
  104. package/dist/files/previewers.js +1 -1
  105. package/dist/http/api.module.js +16 -6
  106. package/dist/http/gateway-routes.d.ts +1 -1
  107. package/dist/http/gateway-routes.js +1 -1
  108. package/dist/identity/settings.d.ts +32 -0
  109. package/dist/identity/settings.js +26 -2
  110. package/dist/infra/config/kernel-config.service.js +4 -4
  111. package/dist/infra/lock/lock.service.d.ts +8 -0
  112. package/dist/infra/lock/lock.service.js +27 -0
  113. package/dist/infra/throttler/named-throttlers.d.ts +4 -1
  114. package/dist/infra/throttler/named-throttlers.js +16 -1
  115. package/dist/infra/throttler/throttler.guard.js +1 -1
  116. package/dist/kernel.module.js +3 -3
  117. package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
  118. package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
  119. package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
  120. package/dist/{devices → local-devices}/device-auth.js +51 -53
  121. package/dist/local-devices/device-auth.module.d.ts +7 -0
  122. package/dist/{devices → local-devices}/device-auth.module.js +5 -5
  123. package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
  124. package/dist/{devices → local-devices}/device-routes.js +2 -2
  125. package/dist/local-devices/dto.d.ts +66 -0
  126. package/dist/local-devices/dto.js +44 -0
  127. package/dist/{devices → local-devices}/keys.d.ts +11 -11
  128. package/dist/{devices → local-devices}/keys.js +11 -11
  129. package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
  130. package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
  131. package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
  132. package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
  133. package/dist/local-devices/local-devices.module.d.ts +16 -0
  134. package/dist/local-devices/local-devices.module.js +44 -0
  135. package/dist/{devices → local-devices}/machines.d.ts +26 -26
  136. package/dist/{devices → local-devices}/machines.js +71 -71
  137. package/dist/{devices → local-devices}/relay.d.ts +15 -15
  138. package/dist/{devices → local-devices}/relay.js +55 -55
  139. package/dist/{devices → local-devices}/targets.d.ts +8 -8
  140. package/dist/{devices → local-devices}/targets.js +14 -14
  141. package/dist/orgs/offboarding.d.ts +6 -6
  142. package/dist/orgs/offboarding.js +12 -12
  143. package/dist/orgs/settings.service.d.ts +28 -0
  144. package/dist/orgs/settings.service.js +20 -1
  145. package/dist/overrides.d.ts +3 -1
  146. package/dist/overrides.js +2 -0
  147. package/dist/platform/exclusions.js +48 -8
  148. package/dist/platform/operation.js +10 -2
  149. package/dist/platform/ops/admin.ops.js +8 -2
  150. package/dist/platform/ops/connectors.ops.js +2 -0
  151. package/dist/platform/ops/conversations.ops.d.ts +3 -3
  152. package/dist/platform/ops/conversations.ops.js +9 -9
  153. package/dist/platform/ops/devices.ops.d.ts +26 -0
  154. package/dist/platform/ops/devices.ops.js +311 -0
  155. package/dist/platform/ops/org-settings.ops.js +2 -2
  156. package/dist/platform/ops/orgs.ops.js +1 -0
  157. package/dist/platform/ops/setup.ops.d.ts +24 -0
  158. package/dist/platform/ops/setup.ops.js +212 -0
  159. package/dist/platform/ops/ui.ops.d.ts +8 -0
  160. package/dist/platform/ops/ui.ops.js +41 -0
  161. package/dist/platform/platform-ops.module.d.ts +4 -2
  162. package/dist/platform/platform-ops.module.js +13 -5
  163. package/dist/platform/route-schemas.js +11 -3
  164. package/dist/roles/gateway-role.d.ts +3 -3
  165. package/dist/roles/gateway-role.js +4 -4
  166. package/dist/roles/gateway.module.d.ts +1 -1
  167. package/dist/roles/gateway.module.js +5 -5
  168. package/dist/roles/worker.module.js +1 -1
  169. package/dist/runtime/context/build.d.ts +1 -1
  170. package/dist/runtime/context/build.js +6 -6
  171. package/dist/runtime/context/compaction.js +1 -1
  172. package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
  173. package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
  174. package/dist/runtime/maintenance.d.ts +1 -1
  175. package/dist/sandbox/jobs.d.ts +13 -13
  176. package/dist/sandbox/jobs.js +20 -20
  177. package/dist/sandbox/leases.d.ts +9 -9
  178. package/dist/sandbox/leases.js +14 -14
  179. package/dist/sandbox/providers.d.ts +8 -8
  180. package/dist/sandbox/providers.js +8 -8
  181. package/dist/sandbox/sandbox.module.d.ts +1 -1
  182. package/dist/sandbox/sandbox.module.js +1 -1
  183. package/dist/sandbox/sandbox.service.d.ts +76 -76
  184. package/dist/sandbox/sandbox.service.js +230 -230
  185. package/dist/setup/kernel-checks.d.ts +91 -0
  186. package/dist/setup/kernel-checks.js +295 -0
  187. package/dist/setup/oauth-token-probe.d.ts +47 -0
  188. package/dist/setup/oauth-token-probe.js +108 -0
  189. package/dist/setup/redact-check.d.ts +18 -0
  190. package/dist/setup/redact-check.js +46 -0
  191. package/dist/setup/setup-check-registry.d.ts +86 -0
  192. package/dist/setup/setup-check-registry.js +75 -0
  193. package/dist/setup/setup-checks.controller.d.ts +28 -0
  194. package/dist/setup/setup-checks.controller.js +78 -0
  195. package/dist/setup/setup-checks.schemas.d.ts +38 -0
  196. package/dist/setup/setup-checks.schemas.js +43 -0
  197. package/dist/setup/setup-checks.service.d.ts +144 -0
  198. package/dist/setup/setup-checks.service.js +683 -0
  199. package/dist/setup/setup-guides.controller.d.ts +18 -0
  200. package/dist/setup/setup-guides.controller.js +48 -0
  201. package/dist/setup/setup-guides.schemas.d.ts +10 -0
  202. package/dist/setup/setup-guides.schemas.js +6 -0
  203. package/dist/setup/setup-guides.service.d.ts +126 -0
  204. package/dist/setup/setup-guides.service.js +315 -0
  205. package/dist/setup/setup.module.d.ts +8 -0
  206. package/dist/setup/setup.module.js +31 -0
  207. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  208. package/dist/tools/builtins/builtin-tools.js +5 -5
  209. package/dist/tools/builtins/platform.js +1 -1
  210. package/dist/tools/builtins/sandbox/bash.js +6 -6
  211. package/dist/tools/builtins/sandbox/common.d.ts +25 -25
  212. package/dist/tools/builtins/sandbox/common.js +51 -51
  213. package/dist/tools/builtins/sandbox/edit.js +2 -2
  214. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  215. package/dist/tools/builtins/sandbox/index.js +1 -1
  216. package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
  217. package/dist/tools/builtins/sandbox/task-output.js +10 -10
  218. package/dist/tools/builtins/sandbox/task-stop.js +2 -2
  219. package/dist/tools/builtins/sandbox/write.js +2 -2
  220. package/dist/tools/builtins/skill-load.d.ts +1 -1
  221. package/dist/tools/builtins/skill-load.js +2 -2
  222. package/dist/tools/connectors.controller.d.ts +28 -11
  223. package/dist/tools/connectors.controller.js +49 -14
  224. package/dist/tools/connectors.schemas.d.ts +4 -0
  225. package/dist/tools/connectors.schemas.js +4 -0
  226. package/dist/tools/connectors.service.d.ts +30 -2
  227. package/dist/tools/connectors.service.js +98 -3
  228. package/dist/tools/credentials.d.ts +20 -0
  229. package/dist/tools/credentials.js +90 -1
  230. package/dist/tools/oauth/tokens.d.ts +20 -0
  231. package/dist/tools/oauth/tokens.js +49 -24
  232. package/dist/tools/pipeline.js +4 -3
  233. package/dist/tools/registry.d.ts +2 -2
  234. package/dist/tools/tools.module.js +3 -3
  235. package/dist/ui/admin-ui.controller.d.ts +56 -0
  236. package/dist/ui/admin-ui.controller.js +192 -0
  237. package/dist/ui/arrangement.d.ts +74 -0
  238. package/dist/ui/arrangement.js +98 -0
  239. package/dist/ui/embed-token.d.ts +2 -2
  240. package/dist/ui/embed-token.js +30 -5
  241. package/dist/ui/registry.d.ts +29 -14
  242. package/dist/ui/registry.js +31 -10
  243. package/dist/ui/slots.controller.d.ts +11 -0
  244. package/dist/ui/slots.controller.js +25 -0
  245. package/dist/ui/ui-stream.d.ts +20 -3
  246. package/dist/ui/ui-stream.js +25 -7
  247. package/dist/ui/ui.schemas.d.ts +66 -0
  248. package/dist/ui/ui.schemas.js +65 -0
  249. package/dist/ui/views.controller.d.ts +35 -49
  250. package/dist/ui/views.controller.js +48 -70
  251. package/dist/ui/views.d.ts +84 -18
  252. package/dist/ui/views.js +201 -38
  253. package/package.json +3 -3
  254. package/src/migrations/0105_devices_rename.sql +136 -0
  255. package/src/migrations/0106_setup_guides_v2.sql +10 -0
  256. package/dist/devices/device-auth.module.d.ts +0 -7
  257. package/dist/environments/conversation-environments.d.ts +0 -75
  258. package/dist/environments/dto.d.ts +0 -25
  259. package/dist/environments/dto.js +0 -12
  260. package/dist/environments/environments.controller.d.ts +0 -36
  261. package/dist/environments/environments.module.d.ts +0 -8
  262. package/dist/environments/environments.module.js +0 -31
  263. package/dist/environments/environments.schemas.d.ts +0 -3
  264. package/dist/environments/environments.schemas.js +0 -14
  265. package/dist/environments/label.d.ts +0 -11
  266. package/dist/platform/ops/environments.ops.d.ts +0 -26
  267. package/dist/platform/ops/environments.ops.js +0 -311
@@ -1,24 +1,24 @@
1
- import { EnvironmentsService, type EnvironmentView } from "../environments/environments.service.js";
1
+ import { DevicesService, type DeviceView } from "../devices/devices.service.js";
2
2
  import { KernelDb } from "../infra/database/kernel-db.js";
3
3
  import { ConversationAccess } from "./access.js";
4
4
  import { ConversationsService } from "./conversations.service.js";
5
5
  /**
6
- * The environment a conversation works in, for its page (environments spec §9: shown read only):
6
+ * The device a conversation works in, for its page (environments spec §9: shown read only):
7
7
  * a conversation the viewer may not see → `conversation.not_found`. A sub-agent shows its root
8
- * conversation's environment. Null while the conversation is unbound, or when its environment is
8
+ * conversation's device. Null while the conversation is unbound, or when its device is
9
9
  * deleted or no longer its owner's (its sandbox tools then fail).
10
10
  */
11
- export declare class ConversationEnvironmentStatus {
11
+ export declare class ConversationDeviceStatus {
12
12
  /** Who may see the conversation (the rule of its event stream). */
13
13
  private readonly access;
14
- /** The conversation whose environment it works in: a sub-agent's root, else itself. */
14
+ /** The conversation whose device it works in: a sub-agent's root, else itself. */
15
15
  private readonly conversations;
16
- private readonly environments;
16
+ private readonly devices;
17
17
  private readonly db;
18
18
  constructor(
19
19
  /** Who may see the conversation (the rule of its event stream). */
20
20
  access: Pick<ConversationAccess, "isAccessible">,
21
- /** The conversation whose environment it works in: a sub-agent's root, else itself. */
22
- conversations: Pick<ConversationsService, "sandboxConversationOf">, environments: Pick<EnvironmentsService, "get">, db: KernelDb);
23
- get(orgId: string, conversationId: string, viewerAccountId: string): Promise<EnvironmentView | null>;
21
+ /** The conversation whose device it works in: a sub-agent's root, else itself. */
22
+ conversations: Pick<ConversationsService, "sandboxConversationOf">, devices: Pick<DevicesService, "get">, db: KernelDb);
23
+ get(orgId: string, conversationId: string, viewerAccountId: string): Promise<DeviceView | null>;
24
24
  }
@@ -8,31 +8,31 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
8
  return function (target, key) { decorator(target, key, paramIndex); }
9
9
  };
10
10
  import { Inject, Injectable } from "@nestjs/common";
11
- import { EnvironmentsService } from "../environments/environments.service.js";
11
+ import { DevicesService } from "../devices/devices.service.js";
12
12
  import { ApiError } from "../errors.js";
13
13
  import { KernelDb } from "../infra/database/kernel-db.js";
14
14
  import { UUID_RE } from "../ui/registry.js";
15
15
  import { ConversationAccess } from "./access.js";
16
16
  import { ConversationsService } from "./conversations.service.js";
17
17
  /**
18
- * The environment a conversation works in, for its page (environments spec §9: shown read only):
18
+ * The device a conversation works in, for its page (environments spec §9: shown read only):
19
19
  * a conversation the viewer may not see → `conversation.not_found`. A sub-agent shows its root
20
- * conversation's environment. Null while the conversation is unbound, or when its environment is
20
+ * conversation's device. Null while the conversation is unbound, or when its device is
21
21
  * deleted or no longer its owner's (its sandbox tools then fail).
22
22
  */
23
- let ConversationEnvironmentStatus = class ConversationEnvironmentStatus {
23
+ let ConversationDeviceStatus = class ConversationDeviceStatus {
24
24
  access;
25
25
  conversations;
26
- environments;
26
+ devices;
27
27
  db;
28
28
  constructor(
29
29
  /** Who may see the conversation (the rule of its event stream). */
30
30
  access,
31
- /** The conversation whose environment it works in: a sub-agent's root, else itself. */
32
- conversations, environments, db) {
31
+ /** The conversation whose device it works in: a sub-agent's root, else itself. */
32
+ conversations, devices, db) {
33
33
  this.access = access;
34
34
  this.conversations = conversations;
35
- this.environments = environments;
35
+ this.devices = devices;
36
36
  this.db = db;
37
37
  }
38
38
  async get(orgId, conversationId, viewerAccountId) {
@@ -40,32 +40,32 @@ let ConversationEnvironmentStatus = class ConversationEnvironmentStatus {
40
40
  !(await this.access.isAccessible(orgId, conversationId, viewerAccountId))) {
41
41
  throw new ApiError("conversation.not_found", "Conversation not found");
42
42
  }
43
- // a sub-agent works in its root conversation's environment (at every depth)
43
+ // a sub-agent works in its root conversation's device (at every depth)
44
44
  const root = await this.conversations.sandboxConversationOf(orgId, conversationId);
45
45
  const conv = await this.db
46
46
  .selectFrom("conversations")
47
- .select(["account_id", "environment_id"])
47
+ .select(["account_id", "device_id"])
48
48
  .where("id", "=", root)
49
49
  .where("org_id", "=", orgId)
50
50
  .executeTakeFirst();
51
- if (!conv?.environment_id)
51
+ if (!conv?.device_id)
52
52
  return null;
53
53
  try {
54
- // the environment as its owner sees it (only the owner may use a personal environment)
55
- return await this.environments.get(orgId, conv.account_id, conv.environment_id);
54
+ // the device as its owner sees it (only the owner may use a personal device)
55
+ return await this.devices.get(orgId, conv.account_id, conv.device_id);
56
56
  }
57
57
  catch (e) {
58
- if (e instanceof ApiError && e.code === "environment.not_found")
58
+ if (e instanceof ApiError && e.code === "device.not_found")
59
59
  return null;
60
60
  throw e;
61
61
  }
62
62
  }
63
63
  };
64
- ConversationEnvironmentStatus = __decorate([
64
+ ConversationDeviceStatus = __decorate([
65
65
  Injectable(),
66
66
  __param(0, Inject(ConversationAccess)),
67
67
  __param(1, Inject(ConversationsService)),
68
- __param(2, Inject(EnvironmentsService)),
68
+ __param(2, Inject(DevicesService)),
69
69
  __param(3, Inject(KernelDb))
70
- ], ConversationEnvironmentStatus);
71
- export { ConversationEnvironmentStatus };
70
+ ], ConversationDeviceStatus);
71
+ export { ConversationDeviceStatus };
@@ -132,7 +132,7 @@ export declare class EventLog {
132
132
  findByIdem(conversationId: string, idemKey: string): Promise<ConversationEvent | undefined>;
133
133
  /**
134
134
  * The conversation's latest event of `type` (by seq); undefined without one. `skills_catalog`
135
- * (0025) and `environment_paths` (0094) have partial indexes that answer it directly; other
135
+ * (0025) and `device_paths` (0094) have partial indexes that answer it directly; other
136
136
  * types scan the conversation's events backwards on the (conversation_id, seq) key, the whole
137
137
  * conversation when it has none.
138
138
  */
@@ -246,7 +246,7 @@ let EventLog = class EventLog {
246
246
  }
247
247
  /**
248
248
  * The conversation's latest event of `type` (by seq); undefined without one. `skills_catalog`
249
- * (0025) and `environment_paths` (0094) have partial indexes that answer it directly; other
249
+ * (0025) and `device_paths` (0094) have partial indexes that answer it directly; other
250
250
  * types scan the conversation's events backwards on the (conversation_id, seq) key, the whole
251
251
  * conversation when it has none.
252
252
  */
@@ -516,7 +516,7 @@ export declare const ConversationEventSchema: z.ZodDiscriminatedUnion<[z.ZodObje
516
516
  removed: z.ZodArray<z.ZodString>;
517
517
  }, z.core.$strip>;
518
518
  }, z.core.$strip>, z.ZodObject<{
519
- type: z.ZodLiteral<"environment_paths">;
519
+ type: z.ZodLiteral<"device_paths">;
520
520
  payload: z.ZodObject<{
521
521
  roots: z.ZodObject<{
522
522
  workspace: z.ZodString;
@@ -447,10 +447,10 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
447
447
  * The directories of the instance a sandbox tool call entered, when they differ from the
448
448
  * defaults (environments spec §13.1: a connected machine's real paths). Written once per
449
449
  * conversation and roots, before that call's result. **Model-visible**: rendered at its position
450
- * as a system message (`environmentPathsText`); a summary covering it is followed by the latest
450
+ * as a system message (`devicePathsText`); a summary covering it is followed by the latest
451
451
  * one again.
452
452
  */
453
- ev("environment_paths", z.object({
453
+ ev("device_paths", z.object({
454
454
  roots: z.object({
455
455
  workspace: z.string().min(1).max(4096),
456
456
  skills: z.string().min(1).max(4096),
@@ -1,4 +1,4 @@
1
- import { type ExtensionContext, type ExtensionManifest, type ExtensionPointRef, type Logger, type ToolHandler, type ToolSpec } from "@capybara-hq/plugin-sdk";
1
+ import { type ExtensionContext, type ExtensionManifest, type ExtensionPointRef, type Logger, resolveUiSlots, type SetupCheckArgs, type SetupGuidePlace, type ToolHandler, type ToolSpec } from "@capybara-hq/plugin-sdk";
2
2
  import type { Redis } from "ioredis";
3
3
  import { Kysely } from "kysely";
4
4
  import { type RegisteredHook } from "../extensions/hooks.js";
@@ -52,6 +52,15 @@ export type RegisteredTool = {
52
52
  spec: ToolSpec;
53
53
  handler: ToolHandler;
54
54
  };
55
+ /**
56
+ * A setup check registered through `ctx.setup.check`: `place` and `run` read once from the
57
+ * definition at registration and frozen, so the extension cannot swap them afterwards (a getter
58
+ * on the definition runs once, at registration, never when a check runs).
59
+ */
60
+ export type RegisteredSetupCheck = Readonly<{
61
+ place: SetupGuidePlace;
62
+ run: (args: SetupCheckArgs) => Promise<unknown>;
63
+ }>;
55
64
  /** 插件经 `ctx.extensionPoints` 取用其他插件能力时,内核注入的访问接口。 */
56
65
  export interface ExtensionPointAccess {
57
66
  /** 已加载(setup 完成)的提供方,按加载顺序;按完整引用(含主版本)精确匹配。 */
@@ -72,8 +81,15 @@ export interface ExtensionPointAccess {
72
81
  * required bootstrap plugins, see `extensions/enabled.ts`), not cached.
73
82
  */
74
83
  export declare function queryEnabledPlugins(db: Kysely<any>, orgId: string): Promise<Set<string>>;
84
+ /**
85
+ * Whether the account is, right now, an active super admin (one query): what a platform embed
86
+ * token and the platform refresh stream re-check.
87
+ */
88
+ export declare function currentPlatformAccount(db: KernelDeps["db"], accountId: string): Promise<boolean>;
75
89
  /** 插件的 PG schema 名:`plugin_<name>`,name 中的 `-` 换成 `_`。 */
76
90
  export declare function pluginSchemaName(name: string): string;
91
+ /** What {@link resolveUiSlots} returns for a manifest. */
92
+ export type UiResolution = ReturnType<typeof resolveUiSlots>;
77
93
  /** 内核视角的插件 ctx:插件契约之外还带宿主要用的登记信息与关闭方法。 */
78
94
  export type KernelExtensionContext = ExtensionContext & {
79
95
  /** 本实例的登记账(C17):每次登记记一笔,撤销时逐项撤销。 */
@@ -92,11 +108,17 @@ export type KernelExtensionContext = ExtensionContext & {
92
108
  registeredTools: RegisteredTool[];
93
109
  /** Hooks registered through `ctx.hooks.on` (registration order). */
94
110
  registeredHooks: RegisteredHook[];
111
+ /** The manifest's `ui` resolved against the slot catalog once per load (UI slots spec §3.2). */
112
+ uiResolution: UiResolution;
95
113
  /** 经 `ctx.ui.view` 注册的视图(按贡献 id)。 */
96
114
  uiViews: ReadonlyMap<string, UiRender>;
97
115
  /** 经 `ctx.ui.action` 注册的动作处理函数(按贡献 id)。 */
98
116
  uiActions: ReadonlyMap<string, UiActionHandler>;
99
- /** setup 结束后调用:此后 `tools.register`、`ui.view`、`ui.action`、`hooks.on` 抛错。 */
117
+ /** Setup checks registered through `ctx.setup.check`, by id. */
118
+ setupChecks: ReadonlyMap<string, RegisteredSetupCheck>;
119
+ /**
120
+ * setup 结束后调用:此后 `tools.register`、`ui.view`、`ui.action`、`hooks.on`、`setup.check` 抛错。
121
+ */
100
122
  sealTools(): void;
101
123
  /** 中止 signal、封账并逐项撤销仍在账上的登记、关闭队列连接(幂等)。 */
102
124
  close(): Promise<void>;
@@ -119,7 +141,8 @@ export declare class LiveConfig {
119
141
  * only with `permissions.models` (and only its `embedding` purposes, through `deps.models`); `http.route`
120
142
  * only the method + path declared in `permissions.http`; `tools.register` only names declared in
121
143
  * `permissions.tools`; `ui.view` / `ui.action` only ids declared in `permissions.ui.views` (during
122
- * setup only); `ui.invalidate` sends a refresh over the kernel bus (namespace `kernel`), across
144
+ * setup only); `setup.check` only ids declared in `permissions.setupChecks` (during setup only,
145
+ * `place` and `run` read once and frozen); `ui.invalidate` sends a refresh over the kernel bus (namespace `kernel`), across
123
146
  * replicas; `ui.verifyEmbedToken` checks an embed token the kernel signed: `claims.plugin` must be
124
147
  * this extension, the extension still enabled in that org and the caller still an active member of
125
148
  * the org (org not deleted); returns the current role;
@@ -1,4 +1,4 @@
1
- import { EXTENSION_POINTS, ExtensionPermissionError, ExtensionPointUnavailableError, FILE_PREVIEW_EXTENSION_POINT, OBJECT_STORE_EXTENSION_POINT, parseExtensionPoint, validateFilePreviewProvider, validateToolSpec, } from "@capybara-hq/plugin-sdk";
1
+ import { EXTENSION_POINTS, ExtensionPermissionError, ExtensionPointUnavailableError, FILE_PREVIEW_EXTENSION_POINT, OBJECT_STORE_EXTENSION_POINT, parseExtensionPoint, resolveUiSlots, SETUP_CHECK_ID_RE, SETUP_GUIDE_PLACES, validateFilePreviewProvider, validateToolSpec, } from "@capybara-hq/plugin-sdk";
2
2
  import { Command, ConnectionBuilder, ControlledTransactionBuilder, Kysely, TransactionBuilder, } from "kysely";
3
3
  import { conversationTopic } from "../conversations/event-log.js";
4
4
  import { kernelDb } from "../db/kernel-schema.js";
@@ -7,7 +7,7 @@ import { checkHookRegistration } from "../extensions/hooks.js";
7
7
  import { RegistrationLedger } from "../extensions/ledger.js";
8
8
  import { audit } from "../identity/audit.js";
9
9
  import { PrefixedStorage } from "../storage/storage.service.js";
10
- import { canUsePlace, orgUiTopic, PluginUiRegistration, } from "../ui/registry.js";
10
+ import { canUseSlot, orgUiTopic, PLATFORM_UI_TOPIC, PluginUiRegistration, } from "../ui/registry.js";
11
11
  import { createBus } from "./bus.js";
12
12
  import { createKv } from "./kv.js";
13
13
  import { createLock } from "./lock.js";
@@ -39,6 +39,20 @@ async function currentEmbedRole(db, plugin, orgId, accountId) {
39
39
  .executeTakeFirst();
40
40
  return row?.role;
41
41
  }
42
+ /**
43
+ * Whether the account is, right now, an active super admin (one query): what a platform embed
44
+ * token and the platform refresh stream re-check.
45
+ */
46
+ export async function currentPlatformAccount(db, accountId) {
47
+ const row = await kernelDb(db)
48
+ .selectFrom("accounts")
49
+ .select("accounts.id")
50
+ .where("accounts.id", "=", accountId)
51
+ .where("accounts.status", "=", "active")
52
+ .where("accounts.is_super_admin", "=", true)
53
+ .executeTakeFirst();
54
+ return row !== undefined;
55
+ }
42
56
  /** `ui.invalidate` 目标的一条查询:插件在该组织启用,且(带对话时)对话属于该组织。 */
43
57
  async function invalidateTargetOk(db, plugin, orgId, conversationId) {
44
58
  const k = kernelDb(db);
@@ -168,7 +182,8 @@ export class LiveConfig {
168
182
  * only with `permissions.models` (and only its `embedding` purposes, through `deps.models`); `http.route`
169
183
  * only the method + path declared in `permissions.http`; `tools.register` only names declared in
170
184
  * `permissions.tools`; `ui.view` / `ui.action` only ids declared in `permissions.ui.views` (during
171
- * setup only); `ui.invalidate` sends a refresh over the kernel bus (namespace `kernel`), across
185
+ * setup only); `setup.check` only ids declared in `permissions.setupChecks` (during setup only,
186
+ * `place` and `run` read once and frozen); `ui.invalidate` sends a refresh over the kernel bus (namespace `kernel`), across
172
187
  * replicas; `ui.verifyEmbedToken` checks an embed token the kernel signed: `claims.plugin` must be
173
188
  * this extension, the extension still enabled in that org and the caller still an active member of
174
189
  * the org (org not deleted); returns the current role;
@@ -247,8 +262,13 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
247
262
  ...(manifest.optional ?? []),
248
263
  ]);
249
264
  const uiReg = new PluginUiRegistration(manifest, deny);
265
+ const declaredSetupChecks = new Set(perms.setupChecks ?? []);
266
+ const setupChecks = new Map();
250
267
  const embedTokens = deps.embedTokens;
251
- const uiPlaces = new Map((manifest.ui ?? []).map((c) => [c.id, c.place]));
268
+ const uiResolution = resolveUiSlots(manifest.ui);
269
+ const uiSlots = new Map(uiResolution.resolved.map((r) => [r.contribution.id, r.slot]));
270
+ /** Ids of the extension's `platform.page` contributions (their invalidate takes no orgId). */
271
+ const platformUi = new Set([...uiSlots].filter(([, s]) => s.id === "platform.page").map(([id]) => id));
252
272
  /** 校验能力可取用(非 brokered、已在清单声明),返回其登记信息。 */
253
273
  const checkExtensionPoint = (ref) => {
254
274
  const capName = parseExtensionPoint(ref).name;
@@ -428,6 +448,49 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
428
448
  });
429
449
  },
430
450
  },
451
+ // Setup checks (setup guides v2 §10.2): only during setup, only ids declared in
452
+ // permissions.setupChecks (an undeclared or malformed id is a denial, audited); the kernel's
453
+ // SetupChecksService runs them (bounded, cached, redacted).
454
+ setup: {
455
+ check(id, def) {
456
+ if (toolsSealed) {
457
+ throw new Error(`plugin ${name}: setup.check is only allowed during setup; setup has completed`);
458
+ }
459
+ if (typeof id !== "string" || !SETUP_CHECK_ID_RE.test(id) || !declaredSetupChecks.has(id)) {
460
+ // the item names the id only when it has the id shape (an audit row never carries
461
+ // arbitrary extension text)
462
+ deny(`permissions.setupChecks ${typeof id === "string" && SETUP_CHECK_ID_RE.test(id) ? id : "(invalid id)"}`);
463
+ }
464
+ if (setupChecks.has(id)) {
465
+ throw new Error(`plugin ${name}: duplicate setup check "${id}"`);
466
+ }
467
+ if (typeof def !== "object" || def === null) {
468
+ throw new Error(`plugin ${name}: setup check "${id}" needs a definition object`);
469
+ }
470
+ // read once: what runs later is exactly what was checked here
471
+ const place = def.place;
472
+ const run = def.run;
473
+ if (!SETUP_GUIDE_PLACES.includes(place)) {
474
+ throw new Error(`plugin ${name}: setup check "${id}" place must be one of ${SETUP_GUIDE_PLACES.join(", ")}`);
475
+ }
476
+ if (typeof run !== "function") {
477
+ throw new Error(`plugin ${name}: setup check "${id}" run must be a function`);
478
+ }
479
+ const check = Object.freeze({
480
+ place: place,
481
+ run: run,
482
+ });
483
+ setupChecks.set(id, check);
484
+ ledger.add({
485
+ kind: "setup.check",
486
+ key: id,
487
+ dispose: async () => {
488
+ if (setupChecks.get(id) === check)
489
+ setupChecks.delete(id);
490
+ },
491
+ });
492
+ },
493
+ },
431
494
  hooks: {
432
495
  on(mount, handler, opts) {
433
496
  if (toolsSealed) {
@@ -482,9 +545,15 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
482
545
  });
483
546
  },
484
547
  // 目标先核对(一条查询):插件在 orgId 启用;带对话时对话属于 orgId。不满足就只记 debug、不发
485
- // (插件拿着过期或别的组织的 id 调用不是错误,但不能借它往别的组织的流里发刷新)
548
+ // (插件拿着过期或别的组织的 id 调用不是错误,但不能借它往别的组织的流里发刷新)。A `platform.page`
549
+ // contribution takes no orgId and refreshes the platform stream (super admins only)
486
550
  async invalidate(target) {
487
- const t = uiReg.target(target);
551
+ const t = uiReg.target(target, platformUi);
552
+ const msg = { kind: "ui", plugin: name, contribution: t.contribution };
553
+ if (t.scope === "platform") {
554
+ await kernelBus.publish(PLATFORM_UI_TOPIC, msg);
555
+ return;
556
+ }
488
557
  if (!(await invalidateTargetOk(deps.db, name, t.orgId, t.conversationId))) {
489
558
  deps.log.debug?.("plugin ui invalidate ignored: plugin not enabled or conversation not in org", {
490
559
  plugin: name,
@@ -494,22 +563,33 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
494
563
  });
495
564
  return;
496
565
  }
497
- const msg = { kind: "ui", plugin: name, contribution: t.contribution };
498
566
  await kernelBus.publish(t.conversationId !== undefined
499
567
  ? conversationTopic(t.conversationId)
500
568
  : orgUiTopic(t.orgId), msg);
501
569
  },
502
570
  // 只认签给本插件、未过期、未篡改的令牌(见 ui/embed-token.ts);再用一条查询核对此刻:本插件仍在该组织
503
571
  // 启用、组织未删除、账号 active 且仍是成员(每次查 PG、不缓存:停用插件、离职、停用账号后已签出的令牌立即失效)。
504
- // 返回的 role 是此刻的角色;组织页面的令牌在调用者已降为 guest 时失效(A38)。其余一律 null
572
+ // 返回的 role 是此刻的角色;令牌在此刻的角色低于贡献所在位置的 minRole 时失效(A38, UI slots spec §7)。
573
+ // A platform token: the contribution is a `platform.page` and the account is still an active
574
+ // super admin. A token of one scope never verifies for the other's slots. 其余一律 null
505
575
  async verifyEmbedToken(token) {
506
576
  const claims = embedTokens.verify(token, name);
507
577
  if (claims === null)
508
578
  return null;
509
- const role = await currentEmbedRole(deps.db, name, claims.orgId, claims.accountId);
510
- if (role === undefined)
579
+ const slot = uiSlots.get(claims.contribution);
580
+ if (claims.scope === "platform") {
581
+ if (slot?.id !== "platform.page")
582
+ return null;
583
+ return (await currentPlatformAccount(deps.db, claims.accountId)) ? claims : null;
584
+ }
585
+ if (claims.scope !== "org" || claims.orgId === undefined)
511
586
  return null;
512
- if (!canUsePlace(uiPlaces.get(claims.contribution) ?? "page", role))
587
+ // the contribution's slot as loaded now: never `platform.page` through an org token, and the
588
+ // current role still meets the slot's minRole (a demoted caller's token stops working)
589
+ if (slot === undefined || slot.id === "platform.page")
590
+ return null;
591
+ const role = await currentEmbedRole(deps.db, name, claims.orgId, claims.accountId);
592
+ if (role === undefined || !canUseSlot(slot, role))
513
593
  return null;
514
594
  return { ...claims, role };
515
595
  },
@@ -521,14 +601,15 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
521
601
  if (provided.has(extensionPoint)) {
522
602
  throw new Error(`plugin ${name}: extension point ${extensionPoint} provided more than once`);
523
603
  }
524
- if (extensionPoint === FILE_PREVIEW_EXTENSION_POINT)
525
- checkFilePreviewProvider(manifest, impl);
526
- provided.set(extensionPoint, impl);
604
+ const served = extensionPoint === FILE_PREVIEW_EXTENSION_POINT
605
+ ? checkFilePreviewProvider(manifest, impl, uiResolution, deps.log)
606
+ : impl;
607
+ provided.set(extensionPoint, served);
527
608
  ledger.add({
528
609
  kind: "provide",
529
610
  key: extensionPoint,
530
611
  dispose: async () => {
531
- if (provided.get(extensionPoint) === impl)
612
+ if (provided.get(extensionPoint) === served)
532
613
  provided.delete(extensionPoint);
533
614
  },
534
615
  });
@@ -547,8 +628,10 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
547
628
  provided,
548
629
  registeredTools,
549
630
  registeredHooks,
631
+ uiResolution,
550
632
  uiViews: uiReg.views,
551
633
  uiActions: uiReg.actions,
634
+ setupChecks,
552
635
  ledger,
553
636
  async beginDispose(deadline) {
554
637
  drainDeadline = deadline;
@@ -601,21 +684,46 @@ export function createExtensionContext(deps, manifest, deploymentConfig, extensi
601
684
  /**
602
685
  * A `file-preview@1` provider must be valid when it is provided (setup fails otherwise): the shape
603
686
  * ({@link validateFilePreviewProvider}), and every `embed` names a ui contribution of this extension
604
- * with `kind: "embed"` and `place: "file-preview"`.
687
+ * with `kind: "embed"` that resolved to the slot `file.preview` (from `slot` or the deprecated
688
+ * `place`). A previewer whose embed names an embed contribution dropped at load (unknown slot or
689
+ * slot version, UI slots spec §3.2) is left out instead, with one warn per load: the returned
690
+ * provider is what the kernel serves.
605
691
  */
606
- function checkFilePreviewProvider(manifest, impl) {
692
+ function checkFilePreviewProvider(manifest, impl, ui, log) {
607
693
  const problems = validateFilePreviewProvider(impl);
608
- if (problems.length === 0) {
609
- const embeds = new Set((manifest.ui ?? [])
610
- .filter((c) => c.kind === "embed" && c.place === "file-preview")
611
- .map((c) => c.id));
612
- impl.previewers.forEach((p, i) => {
613
- if (p.embed !== undefined && !embeds.has(p.embed)) {
614
- problems.push(`previewers[${i}].embed "${p.embed}" is not a ui contribution { kind: "embed", place: "file-preview" }`);
615
- }
616
- });
694
+ if (problems.length > 0) {
695
+ throw new Error(`plugin ${manifest.name}: invalid ${FILE_PREVIEW_EXTENSION_POINT} provider: ${problems.join("; ")}`);
617
696
  }
697
+ const embeds = new Set(ui.resolved
698
+ .filter((r) => r.contribution.kind === "embed" && r.slot.id === "file.preview")
699
+ .map((r) => r.contribution.id));
700
+ const droppedEmbeds = new Map(ui.dropped
701
+ .filter((d) => manifest.ui?.some((c) => c.id === d.id && c.kind === "embed"))
702
+ .map((d) => [d.id, d]));
703
+ const provider = impl;
704
+ const kept = [];
705
+ const dropped = [];
706
+ provider.previewers.forEach((p, i) => {
707
+ if (p.embed === undefined || embeds.has(p.embed)) {
708
+ kept.push(p);
709
+ return;
710
+ }
711
+ const d = droppedEmbeds.get(p.embed);
712
+ if (d !== undefined) {
713
+ dropped.push({ previewer: p.id, embed: p.embed, ref: d.ref, reason: d.reason });
714
+ return;
715
+ }
716
+ problems.push(`previewers[${i}].embed "${p.embed}" is not a ui contribution { kind: "embed", slot: "file.preview" }`);
717
+ });
618
718
  if (problems.length > 0) {
619
719
  throw new Error(`plugin ${manifest.name}: invalid ${FILE_PREVIEW_EXTENSION_POINT} provider: ${problems.join("; ")}`);
620
720
  }
721
+ if (dropped.length === 0)
722
+ return impl;
723
+ log.warn("plugin file previewers dropped", {
724
+ plugin: manifest.name,
725
+ version: manifest.version,
726
+ previewers: dropped,
727
+ });
728
+ return { ...provider, previewers: kept };
621
729
  }
@@ -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 environment the conversation runs in; null = not chosen yet. */
261
- environment_id: ColumnType<string | null, string | null | undefined, string | null>;
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 {
@@ -419,6 +419,11 @@ export interface ConnectorsTable {
419
419
  template_tool_policies: ColumnType<Record<string, "allow" | "ask" | "deny"> | null, string | null | undefined, string | null>;
420
420
  /** 0081: the platform connector template this connector was made from (null = none). */
421
421
  platform_template_id: ColumnType<string | null, string | null | undefined, string | null>;
422
+ /**
423
+ * 0106: the setup guide of its connector template it was last set up with (`{ guideId, version,
424
+ * hash, mode: null }`); null when unknown (custom connectors, connectors before 0106).
425
+ */
426
+ guide_ack: ColumnType<GuideAckJson | null, string | null | undefined, string | null>;
422
427
  }
423
428
  /**
424
429
  * 0104: a member's own policy for one tool of a personal-credential connector, for calls made with
@@ -567,12 +572,16 @@ export interface LgCheckpointWritesTable {
567
572
  task_path: Generated<string>;
568
573
  }
569
574
  /** 0018_channels.sql:组织的渠道连接(非密钥配置;密钥在 secrets `channels:<id>:config`)。 */
570
- /** `channel_connections.guide_ack` (0099): the setup guide a connection was set up with. */
575
+ /**
576
+ * `channel_connections.guide_ack` (0099) and `connectors.guide_ack` (0106): the setup guide a
577
+ * target was set up with; `hash` is the v2 drift hash (`setupGuideHash`, admin audience) of
578
+ * `mode` (null for a place without modes).
579
+ */
571
580
  export interface GuideAckJson {
572
581
  guideId: string;
573
582
  version: string;
574
583
  hash: string;
575
- mode: string;
584
+ mode: string | null;
576
585
  }
577
586
  export interface ChannelConnectionsTable {
578
587
  id: string;
@@ -783,8 +792,8 @@ export interface BackgroundTasksTable {
783
792
  read_offset: ColumnType<string, number | string | undefined, number | string>;
784
793
  /** Set while a stop is under way (0072); the poller skips such a task. */
785
794
  stopping_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
786
- /** 0088: the environment the task runs in. */
787
- environment_id: ColumnType<string | null, string | null | undefined, string | null>;
795
+ /** 0088, renamed in 0105: the device the task runs in. */
796
+ device_id: ColumnType<string | null, string | null | undefined, string | null>;
788
797
  }
789
798
  /** 0023_sandboxes.sql: the legacy per-conversation sandbox; kept only for the cleanup job (0088). */
790
799
  export interface LegacySandboxesTable {
@@ -818,26 +827,29 @@ type InstanceHandle = ColumnType<{
818
827
  id: string;
819
828
  [k: string]: unknown;
820
829
  } | null, string | null | undefined, string | null>;
821
- /** 0088_environments.sql: a long-lived environment (one instance plus a kept file system). */
822
- export interface EnvironmentsTable {
830
+ /**
831
+ * 0088_environments.sql, renamed in 0105: a device. A cloud device is one instance plus a kept file
832
+ * system; a local device is a person's machine (device_machines).
833
+ */
834
+ export interface DevicesTable {
823
835
  id: string;
824
836
  org_id: string;
825
837
  owner_kind: "personal";
826
838
  owner_account_id: string;
827
839
  name: ColumnType<string | null, string | null | undefined, string | null>;
828
840
  is_default: ColumnType<boolean, boolean | undefined, boolean>;
829
- /** 0093: `device` is a connected machine (environment_machines). */
830
- source: "cloud" | "device";
841
+ /** 0093, renamed in 0105: `local` is a person's machine (device_machines). */
842
+ source: "cloud" | "local";
831
843
  provider: ColumnType<string | null, string | null | undefined, string | null>;
832
- /** 0096: the provider a demoted default was demoted from; null for every other environment. */
844
+ /** 0096: the provider a demoted default was demoted from; null for every other device. */
833
845
  demoted_from_provider: ColumnType<string | null, string | null | undefined, string | null>;
834
846
  created_at: Ts;
835
847
  updated_at: Ts;
836
848
  deleted_at: TsNullable;
837
849
  }
838
- /** 0088_environments.sql: the instance and file system of an environment (replaces sandboxes). */
839
- export interface EnvironmentInstancesTable {
840
- environment_id: string;
850
+ /** 0088_environments.sql, renamed in 0105: the instance and file system of a device. */
851
+ export interface DeviceInstancesTable {
852
+ device_id: string;
841
853
  org_id: string;
842
854
  provider: ColumnType<string | null, string | null | undefined, string | null>;
843
855
  /** The provider's `FileSystemHandle`; null before the file system exists or after a reset. */
@@ -862,13 +874,13 @@ export interface EnvironmentInstancesTable {
862
874
  sweep_failed_at: TsNullable;
863
875
  }
864
876
  /**
865
- * 0093_connected_environments.sql: the machine connected to a `device` environment. At most one
866
- * unrevoked row per environment; revoking sets `revoked_at` and keeps the row.
877
+ * 0093_connected_environments.sql, renamed in 0105: the machine of a local device. At most one
878
+ * unrevoked row per device; revoking sets `revoked_at` and keeps the row.
867
879
  */
868
- export interface EnvironmentMachinesTable {
880
+ export interface DeviceMachinesTable {
869
881
  id: Generated<string>;
870
882
  org_id: string;
871
- environment_id: string;
883
+ device_id: string;
872
884
  account_id: string;
873
885
  /** A hash of the machine credential, never the credential itself. */
874
886
  credential_hash: string;
@@ -884,11 +896,11 @@ export interface EnvironmentMachinesTable {
884
896
  created_at: Ts;
885
897
  revoked_at: TsNullable;
886
898
  }
887
- /** 0088_environments.sql: the environment a member's new conversations use by default. */
888
- export interface EnvironmentDefaultsTable {
899
+ /** 0088_environments.sql, renamed in 0105: the device a member's new conversations use by default. */
900
+ export interface DeviceDefaultsTable {
889
901
  org_id: string;
890
902
  account_id: string;
891
- environment_id: string;
903
+ device_id: string;
892
904
  updated_at: Ts;
893
905
  }
894
906
  /** pg numeric:驱动读出为字符串(精确小数),读取方自行 `Number()`。 */
@@ -1170,10 +1182,10 @@ export interface KernelDatabase {
1170
1182
  directory_exclusions: DirectoryExclusionsTable;
1171
1183
  attachments: AttachmentsTable;
1172
1184
  sandboxes: LegacySandboxesTable;
1173
- environments: EnvironmentsTable;
1174
- environment_instances: EnvironmentInstancesTable;
1175
- environment_defaults: EnvironmentDefaultsTable;
1176
- environment_machines: EnvironmentMachinesTable;
1185
+ devices: DevicesTable;
1186
+ device_instances: DeviceInstancesTable;
1187
+ device_defaults: DeviceDefaultsTable;
1188
+ device_machines: DeviceMachinesTable;
1177
1189
  background_tasks: BackgroundTasksTable;
1178
1190
  skills: SkillsTable;
1179
1191
  skill_versions: SkillVersionsTable;