@capybara-hq/kernel 0.1.0-rc.11 → 0.1.0-rc.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) 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/agents/agents.schemas.d.ts +3 -0
  5. package/dist/agents/agents.service.js +11 -1
  6. package/dist/agents/definition.d.ts +1 -0
  7. package/dist/agents/definition.js +7 -3
  8. package/dist/agents/org-templates.js +4 -0
  9. package/dist/agents/pending-connectors.service.js +1 -1
  10. package/dist/background/background.module.js +2 -2
  11. package/dist/background/launch-lock.d.ts +1 -1
  12. package/dist/background/launch-lock.js +1 -1
  13. package/dist/background/poll.job.d.ts +2 -2
  14. package/dist/background/poll.job.js +10 -10
  15. package/dist/background/stop.d.ts +1 -1
  16. package/dist/background/stop.js +3 -3
  17. package/dist/background/store.d.ts +5 -5
  18. package/dist/background/store.js +5 -5
  19. package/dist/background/tasks.service.d.ts +6 -6
  20. package/dist/background/tasks.service.js +13 -13
  21. package/dist/catalog/component-scope.controller.d.ts +18 -6
  22. package/dist/catalog/component-scope.controller.js +36 -13
  23. package/dist/catalog/component-scope.service.d.ts +11 -0
  24. package/dist/catalog/component-scope.service.js +4 -0
  25. package/dist/catalog/component-state.d.ts +8 -0
  26. package/dist/catalog/component-state.js +19 -11
  27. package/dist/catalog/marketplaces.service.d.ts +1 -1
  28. package/dist/catalog/plugin-import.js +4 -1
  29. package/dist/channels/channels.module.js +2 -2
  30. package/dist/channels/inbound.d.ts +8 -8
  31. package/dist/channels/inbound.js +31 -31
  32. package/dist/channels/phrases.d.ts +27 -27
  33. package/dist/channels/phrases.js +27 -27
  34. package/dist/config/docs.js +1 -1
  35. package/dist/config/schema.d.ts +2 -2
  36. package/dist/config/schema.js +21 -21
  37. package/dist/conversations/conversations.controller.d.ts +11 -11
  38. package/dist/conversations/conversations.controller.js +15 -15
  39. package/dist/conversations/conversations.module.d.ts +1 -1
  40. package/dist/conversations/conversations.module.js +7 -7
  41. package/dist/conversations/conversations.schemas.js +1 -1
  42. package/dist/conversations/conversations.service.d.ts +23 -14
  43. package/dist/conversations/conversations.service.js +28 -21
  44. package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
  45. package/dist/conversations/{environment-status.js → device-status.js} +18 -18
  46. package/dist/conversations/event-log.d.ts +1 -1
  47. package/dist/conversations/event-log.js +1 -1
  48. package/dist/conversations/events.d.ts +2 -1
  49. package/dist/conversations/events.js +2 -2
  50. package/dist/ctx/create-ctx.d.ts +10 -1
  51. package/dist/ctx/create-ctx.js +86 -25
  52. package/dist/db/kernel-schema.d.ts +39 -23
  53. package/dist/{environments → devices}/access.d.ts +19 -19
  54. package/dist/{environments → devices}/access.js +28 -28
  55. package/dist/devices/conversation-devices.d.ts +75 -0
  56. package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
  57. package/dist/devices/devices.controller.d.ts +36 -0
  58. package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
  59. package/dist/devices/devices.module.d.ts +5 -13
  60. package/dist/devices/devices.module.js +16 -29
  61. package/dist/devices/devices.schemas.d.ts +3 -0
  62. package/dist/devices/devices.schemas.js +14 -0
  63. package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
  64. package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
  65. package/dist/devices/dto.d.ts +13 -54
  66. package/dist/devices/dto.js +7 -39
  67. package/dist/devices/label.d.ts +11 -0
  68. package/dist/{environments → devices}/label.js +7 -7
  69. package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
  70. package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
  71. package/dist/errors.d.ts +27 -25
  72. package/dist/errors.js +27 -25
  73. package/dist/evals/recorded-tools.d.ts +2 -2
  74. package/dist/evals/recorded-tools.js +6 -6
  75. package/dist/extensions/admin-ops.js +1 -0
  76. package/dist/extensions/admin-view.js +2 -0
  77. package/dist/extensions/effective-config.d.ts +6 -0
  78. package/dist/extensions/effective-config.js +18 -7
  79. package/dist/extensions/host.d.ts +13 -2
  80. package/dist/extensions/host.js +24 -3
  81. package/dist/extensions/instance.d.ts +12 -1
  82. package/dist/extensions/instance.js +13 -0
  83. package/dist/extensions/permission-view.d.ts +10 -1
  84. package/dist/files/previewers.d.ts +1 -1
  85. package/dist/files/previewers.js +1 -1
  86. package/dist/http/api.module.js +10 -6
  87. package/dist/http/gateway-routes.d.ts +1 -1
  88. package/dist/http/gateway-routes.js +1 -1
  89. package/dist/identity/settings.d.ts +32 -0
  90. package/dist/identity/settings.js +26 -2
  91. package/dist/infra/config/kernel-config.service.js +4 -4
  92. package/dist/kernel.module.js +3 -3
  93. package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
  94. package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
  95. package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
  96. package/dist/{devices → local-devices}/device-auth.js +51 -53
  97. package/dist/local-devices/device-auth.module.d.ts +7 -0
  98. package/dist/{devices → local-devices}/device-auth.module.js +5 -5
  99. package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
  100. package/dist/{devices → local-devices}/device-routes.js +2 -2
  101. package/dist/local-devices/dto.d.ts +66 -0
  102. package/dist/local-devices/dto.js +44 -0
  103. package/dist/{devices → local-devices}/keys.d.ts +11 -11
  104. package/dist/{devices → local-devices}/keys.js +11 -11
  105. package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
  106. package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
  107. package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
  108. package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
  109. package/dist/local-devices/local-devices.module.d.ts +16 -0
  110. package/dist/local-devices/local-devices.module.js +44 -0
  111. package/dist/{devices → local-devices}/machines.d.ts +26 -26
  112. package/dist/{devices → local-devices}/machines.js +71 -71
  113. package/dist/{devices → local-devices}/relay.d.ts +15 -15
  114. package/dist/{devices → local-devices}/relay.js +55 -55
  115. package/dist/{devices → local-devices}/targets.d.ts +8 -8
  116. package/dist/{devices → local-devices}/targets.js +14 -14
  117. package/dist/orgs/offboarding.d.ts +6 -6
  118. package/dist/orgs/offboarding.js +12 -12
  119. package/dist/orgs/settings.service.d.ts +28 -0
  120. package/dist/orgs/settings.service.js +20 -1
  121. package/dist/platform/exclusions.js +48 -3
  122. package/dist/platform/operation.js +6 -2
  123. package/dist/platform/ops/admin.ops.js +8 -2
  124. package/dist/platform/ops/agents.ops.js +19 -6
  125. package/dist/platform/ops/conversations.ops.d.ts +3 -3
  126. package/dist/platform/ops/conversations.ops.js +9 -9
  127. package/dist/platform/ops/devices.ops.d.ts +26 -0
  128. package/dist/platform/ops/devices.ops.js +311 -0
  129. package/dist/platform/ops/org-settings.ops.js +2 -2
  130. package/dist/platform/ops/orgs.ops.js +1 -0
  131. package/dist/platform/ops/ui.ops.d.ts +8 -0
  132. package/dist/platform/ops/ui.ops.js +41 -0
  133. package/dist/platform/platform-ops.module.d.ts +3 -2
  134. package/dist/platform/platform-ops.module.js +8 -5
  135. package/dist/platform/route-schemas.js +6 -3
  136. package/dist/roles/gateway-role.d.ts +3 -3
  137. package/dist/roles/gateway-role.js +4 -4
  138. package/dist/roles/gateway.module.d.ts +1 -1
  139. package/dist/roles/gateway.module.js +5 -5
  140. package/dist/roles/worker.module.js +1 -1
  141. package/dist/runtime/context/build.d.ts +1 -1
  142. package/dist/runtime/context/build.js +6 -6
  143. package/dist/runtime/context/compaction.js +1 -1
  144. package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
  145. package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
  146. package/dist/runtime/maintenance.d.ts +1 -1
  147. package/dist/runtime/subagents/definition.d.ts +3 -2
  148. package/dist/runtime/subagents/definition.js +2 -1
  149. package/dist/sandbox/jobs.d.ts +13 -13
  150. package/dist/sandbox/jobs.js +20 -20
  151. package/dist/sandbox/leases.d.ts +9 -9
  152. package/dist/sandbox/leases.js +14 -14
  153. package/dist/sandbox/providers.d.ts +8 -8
  154. package/dist/sandbox/providers.js +8 -8
  155. package/dist/sandbox/sandbox.module.d.ts +1 -1
  156. package/dist/sandbox/sandbox.module.js +1 -1
  157. package/dist/sandbox/sandbox.service.d.ts +76 -76
  158. package/dist/sandbox/sandbox.service.js +230 -230
  159. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  160. package/dist/tools/builtins/builtin-tools.js +5 -5
  161. package/dist/tools/builtins/platform.js +1 -1
  162. package/dist/tools/builtins/sandbox/bash.js +6 -6
  163. package/dist/tools/builtins/sandbox/common.d.ts +25 -25
  164. package/dist/tools/builtins/sandbox/common.js +51 -51
  165. package/dist/tools/builtins/sandbox/edit.js +2 -2
  166. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  167. package/dist/tools/builtins/sandbox/index.js +1 -1
  168. package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
  169. package/dist/tools/builtins/sandbox/task-output.js +10 -10
  170. package/dist/tools/builtins/sandbox/task-stop.js +2 -2
  171. package/dist/tools/builtins/sandbox/write.js +2 -2
  172. package/dist/tools/builtins/skill-load.d.ts +1 -1
  173. package/dist/tools/builtins/skill-load.js +2 -2
  174. package/dist/tools/connector-account-policies.d.ts +51 -0
  175. package/dist/tools/connector-account-policies.js +165 -0
  176. package/dist/tools/connectors.controller.d.ts +35 -4
  177. package/dist/tools/connectors.controller.js +66 -7
  178. package/dist/tools/connectors.schemas.d.ts +11 -0
  179. package/dist/tools/connectors.schemas.js +11 -0
  180. package/dist/tools/connectors.service.d.ts +2 -0
  181. package/dist/tools/connectors.service.js +1 -0
  182. package/dist/tools/pipeline.d.ts +1 -1
  183. package/dist/tools/pipeline.js +4 -3
  184. package/dist/tools/policy.d.ts +23 -1
  185. package/dist/tools/policy.js +99 -24
  186. package/dist/tools/registry.d.ts +2 -2
  187. package/dist/tools/tools.module.js +6 -3
  188. package/dist/ui/admin-ui.controller.d.ts +56 -0
  189. package/dist/ui/admin-ui.controller.js +192 -0
  190. package/dist/ui/arrangement.d.ts +74 -0
  191. package/dist/ui/arrangement.js +98 -0
  192. package/dist/ui/embed-token.d.ts +2 -2
  193. package/dist/ui/embed-token.js +30 -5
  194. package/dist/ui/registry.d.ts +29 -14
  195. package/dist/ui/registry.js +31 -10
  196. package/dist/ui/slots.controller.d.ts +11 -0
  197. package/dist/ui/slots.controller.js +25 -0
  198. package/dist/ui/ui-stream.d.ts +20 -3
  199. package/dist/ui/ui-stream.js +25 -7
  200. package/dist/ui/ui.schemas.d.ts +66 -0
  201. package/dist/ui/ui.schemas.js +65 -0
  202. package/dist/ui/views.controller.d.ts +35 -49
  203. package/dist/ui/views.controller.js +48 -70
  204. package/dist/ui/views.d.ts +84 -18
  205. package/dist/ui/views.js +201 -38
  206. package/package.json +3 -3
  207. package/src/migrations/0104_connector_tool_account_policies.sql +16 -0
  208. package/src/migrations/0105_devices_rename.sql +136 -0
  209. package/dist/devices/device-auth.module.d.ts +0 -7
  210. package/dist/environments/conversation-environments.d.ts +0 -75
  211. package/dist/environments/dto.d.ts +0 -25
  212. package/dist/environments/dto.js +0 -12
  213. package/dist/environments/environments.controller.d.ts +0 -36
  214. package/dist/environments/environments.module.d.ts +0 -8
  215. package/dist/environments/environments.module.js +0 -31
  216. package/dist/environments/environments.schemas.d.ts +0 -3
  217. package/dist/environments/environments.schemas.js +0 -14
  218. package/dist/environments/label.d.ts +0 -11
  219. package/dist/platform/ops/environments.ops.d.ts +0 -26
  220. package/dist/platform/ops/environments.ops.js +0 -311
@@ -9,6 +9,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
9
9
  };
10
10
  import { Controller, Get, HttpCode, Inject, Post, Put, Req } from "@nestjs/common";
11
11
  import { ApiError } from "../errors.js";
12
+ import { orgIconScope, PluginIcons } from "../extensions/plugin-icons.js";
12
13
  import { CurrentPrincipal, patTokenId, requireUser, SuperAdmin, } from "../identity/principal.js";
13
14
  import { createZodDto } from "../infra/validation/create-zod-dto.js";
14
15
  import { ZBody, ZParam, ZQuery } from "../infra/validation/zod-params.js";
@@ -36,6 +37,16 @@ class ComponentShownBody extends createZodDto(ShownBody, "ComponentShownBody") {
36
37
  }
37
38
  class ComponentSwitchBody extends createZodDto(SwitchBody, "ComponentSwitchBody") {
38
39
  }
40
+ /**
41
+ * Each component with `icon`: its plugin's icon URL on the reader's route (null without one, for
42
+ * a component without a plugin, or when the reader may not see the plugin; maintainer decision
43
+ * 2026-11-09: a connector template without an icon of its own shows its plugin's).
44
+ */
45
+ async function withIcons(icons, rows, scope) {
46
+ const ids = rows.flatMap((r) => (r.itemId === null ? [] : [r.itemId]));
47
+ const urls = await icons.ofItems(ids, scope);
48
+ return rows.map((r) => ({ ...r, icon: r.itemId === null ? null : (urls.get(r.itemId) ?? null) }));
49
+ }
39
50
  const actorOpts = (actor) => {
40
51
  const tokenId = patTokenId(actor);
41
52
  return tokenId !== undefined ? { actorTokenId: tokenId } : {};
@@ -49,9 +60,11 @@ const actorOpts = (actor) => {
49
60
  let AdminComponentsController = class AdminComponentsController {
50
61
  scope;
51
62
  components;
52
- constructor(scope, components) {
63
+ icons;
64
+ constructor(scope, components, icons) {
53
65
  this.scope = scope;
54
66
  this.components = components;
67
+ this.icons = icons;
55
68
  }
56
69
  /**
57
70
  * Updates a platform skill on its own (spec §7.2): the skill package (zip) as the raw body
@@ -73,9 +86,14 @@ let AdminComponentsController = class AdminComponentsController {
73
86
  const actor = requireUser(principal);
74
87
  return this.components.uploadAgentTemplateVersion({ accountId: actor.account.id, ...actorOpts(actor) }, p.id, body.content);
75
88
  }
76
- /** `GET ?kind=`: every platform component of the kind (plugin, owner, scope, version, orgs on). */
89
+ /**
90
+ * `GET ?kind=`: every platform component of the kind (plugin, owner, scope, version, orgs on),
91
+ * each with its display name and its plugin's icon (`icon`, the admin route; null without one).
92
+ */
77
93
  async list(q) {
78
- return { components: await this.scope.list(q.kind) };
94
+ return {
95
+ components: await withIcons(this.icons, await this.scope.list(q.kind), { kind: "admin" }),
96
+ };
79
97
  }
80
98
  /**
81
99
  * A component's versions, newest first: `{ versions: [{ version, catalogVersion, updatedOnOwn,
@@ -178,7 +196,8 @@ AdminComponentsController = __decorate([
178
196
  Controller("api/v1/admin/components"),
179
197
  SuperAdmin(),
180
198
  __param(0, Inject(ComponentScopeService)),
181
- __param(1, Inject(PlatformComponents))
199
+ __param(1, Inject(PlatformComponents)),
200
+ __param(2, Inject(PluginIcons))
182
201
  ], AdminComponentsController);
183
202
  export { AdminComponentsController };
184
203
  /**
@@ -189,21 +208,24 @@ export { AdminComponentsController };
189
208
  */
190
209
  let OrgComponentsController = class OrgComponentsController {
191
210
  scope;
192
- constructor(scope) {
211
+ icons;
212
+ constructor(scope, icons) {
193
213
  this.scope = scope;
214
+ this.icons = icons;
194
215
  }
195
216
  /**
196
217
  * The platform components offered to the org (`?kind=`, `?itemId=`: only those; Task 10): each
197
218
  * with its state in the org (`on`, `locked` for `all`, the org's `switch`) and whether an org
198
- * admin may switch it. Members read it (the workspace pages are read-only for them).
219
+ * admin may switch it. Members read it (the workspace pages are read-only for them). Each has
220
+ * its display name and `icon`, its plugin's icon on the org's catalog route (null without one,
221
+ * or when the org's catalog does not show the plugin to the reader: the share gate holds).
199
222
  */
200
223
  async list(org, q) {
201
- return {
202
- components: await this.scope.orgList(org.orgId, {
203
- ...(q.kind !== undefined && { kind: q.kind }),
204
- ...(q.itemId !== undefined && { itemId: q.itemId }),
205
- }),
206
- };
224
+ const rows = await this.scope.orgList(org.orgId, {
225
+ ...(q.kind !== undefined && { kind: q.kind }),
226
+ ...(q.itemId !== undefined && { itemId: q.itemId }),
227
+ });
228
+ return { components: await withIcons(this.icons, rows, orgIconScope(org)) };
207
229
  }
208
230
  async setSwitch(principal, org, p, body) {
209
231
  const actor = requireUser(principal);
@@ -229,6 +251,7 @@ __decorate([
229
251
  ], OrgComponentsController.prototype, "setSwitch", null);
230
252
  OrgComponentsController = __decorate([
231
253
  Controller("api/v1/orgs/:orgId/components"),
232
- __param(0, Inject(ComponentScopeService))
254
+ __param(0, Inject(ComponentScopeService)),
255
+ __param(1, Inject(PluginIcons))
233
256
  ], OrgComponentsController);
234
257
  export { OrgComponentsController };
@@ -68,7 +68,13 @@ export type ComponentTarget = {
68
68
  export interface ComponentView {
69
69
  kind: ComponentKind;
70
70
  id: string;
71
+ /** Skill or template name; a connector template's id (the file's base name). */
71
72
  name: string;
73
+ /** A connector template's localized display name (null: show `name`). */
74
+ displayName: {
75
+ zh: string;
76
+ en: string;
77
+ } | null;
72
78
  description: string | null;
73
79
  /** The plugin it came from (null: none). */
74
80
  plugin: string | null;
@@ -138,6 +144,11 @@ export interface OrgComponentView {
138
144
  * show with their switches. Never a component the org cannot see.
139
145
  */
140
146
  export interface OrgOfferedComponentView extends OrgComponentView {
147
+ /** A connector template's localized display name (null: show `name`). */
148
+ displayName: {
149
+ zh: string;
150
+ en: string;
151
+ } | null;
141
152
  description: string | null;
142
153
  itemId: string | null;
143
154
  version: string;
@@ -204,6 +204,7 @@ let ComponentScopeService = class ComponentScopeService {
204
204
  kind,
205
205
  id: c.id,
206
206
  name: c.name,
207
+ displayName: c.displayName,
207
208
  description: c.description,
208
209
  plugin: c.plugin,
209
210
  itemId: c.itemId,
@@ -258,6 +259,7 @@ let ComponentScopeService = class ComponentScopeService {
258
259
  kind,
259
260
  id: c.id,
260
261
  name: c.name,
262
+ displayName: c.displayName,
261
263
  description: c.description,
262
264
  plugin: c.plugin,
263
265
  itemId: c.itemId,
@@ -360,6 +362,7 @@ let ComponentScopeService = class ComponentScopeService {
360
362
  kind,
361
363
  id: r.id,
362
364
  name: r.name,
365
+ displayName: null,
363
366
  description: r.description,
364
367
  plugin: r.plugin,
365
368
  itemId: r.catalog_item_id,
@@ -1084,6 +1087,7 @@ const virtualOf = (o) => ({
1084
1087
  plugin: o.plugin,
1085
1088
  version: String(o.version),
1086
1089
  description: null,
1090
+ displayName: null,
1087
1091
  itemId: null,
1088
1092
  scopeMode: "own",
1089
1093
  scope: "named",
@@ -68,6 +68,14 @@ export interface ComponentRow extends ComponentScopeFacts {
68
68
  /** The current version (a connector template: the catalog version that last changed it). */
69
69
  version: string;
70
70
  description: string | null;
71
+ /**
72
+ * A connector template's localized display name (its file's `displayName`); null for skills and
73
+ * agent templates, whose name is what they are shown by.
74
+ */
75
+ displayName: {
76
+ zh: string;
77
+ en: string;
78
+ } | null;
71
79
  shownToOthers: boolean;
72
80
  /** The owning org (null: the platform; ruling P3-1). */
73
81
  ownerOrgId: string | null;
@@ -63,6 +63,11 @@ export function componentOffered(c, p, listed) {
63
63
  export function componentLocked(_c, p) {
64
64
  return p?.builtin === true;
65
65
  }
66
+ /** A `{ zh, en }` display name from stored JSON (a template file's), else null. */
67
+ function localizedName(v) {
68
+ const n = v;
69
+ return typeof n?.zh === "string" && typeof n.en === "string" ? { zh: n.zh, en: n.en } : null;
70
+ }
66
71
  /** The live platform components of `kind` (`ids` / `itemId`: only those). */
67
72
  export async function loadComponents(db, kind, filter = {}) {
68
73
  if (filter.ids !== undefined && filter.ids.length === 0)
@@ -105,17 +110,19 @@ export async function loadComponents(db, kind, filter = {}) {
105
110
  q = q.where("p.template_id", "=", filter.name);
106
111
  if (filter.forUpdate)
107
112
  q = q.forUpdate("p");
108
- return (await q.orderBy("p.id").execute()).map((r) => ({
109
- ...common(r),
110
- ...(r.file?.defaultEnabled === false && {
111
- defaultOff: true,
112
- }),
113
- name: r.template_id,
114
- plugin: r.item_name,
115
- version: r.current_version,
116
- description: null,
117
- originOrgId: null,
118
- }));
113
+ return (await q.orderBy("p.id").execute()).map((r) => {
114
+ const file = r.file;
115
+ return {
116
+ ...common(r),
117
+ ...(file?.defaultEnabled === false && { defaultOff: true }),
118
+ name: r.template_id,
119
+ plugin: r.item_name,
120
+ version: r.current_version,
121
+ description: typeof file?.description === "string" ? file.description : null,
122
+ displayName: localizedName(file?.displayName),
123
+ originOrgId: null,
124
+ };
125
+ });
119
126
  }
120
127
  const table = kind === "skill"
121
128
  ? "platform_skills"
@@ -154,6 +161,7 @@ export async function loadComponents(db, kind, filter = {}) {
154
161
  plugin: r.plugin_name,
155
162
  version: String(r.current_version),
156
163
  description: r.description,
164
+ displayName: null,
157
165
  originOrgId: r.origin_org_id,
158
166
  }));
159
167
  }
@@ -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;
@@ -1714,7 +1714,10 @@ function actionOf(s, sha256, version) {
1714
1714
  export function pluginReviewHash(r, files) {
1715
1715
  const e = r.extension;
1716
1716
  const lic = r.licenseText;
1717
- const canonical = JSON.stringify([
1717
+ // canonicalJson, not JSON.stringify: the review is stored as jsonb, which reorders object keys,
1718
+ // so a template's auth / endpoint object would hash differently at confirm (plugin.review_stale
1719
+ // on every import of a plugin whose connector template has a non-trivial auth block).
1720
+ const canonical = canonicalJson([
1718
1721
  r.name,
1719
1722
  r.version,
1720
1723
  r.contentDigest,
@@ -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();
@@ -11,33 +11,33 @@ export declare const CHANNEL_PHRASES: {
11
11
  readonly zh: "已开始新对话";
12
12
  readonly en: "Started a new conversation.";
13
13
  };
14
- /** 私聊 `/env`:列出可用环境(`{list}` 每行一个,当前的带标记)。 */
15
- readonly envList: {
16
- readonly zh: "你的环境:\n{list}\n发送 /env <名称> 选择下一个新对话使用的环境。";
17
- readonly en: "Your environments:\n{list}\nSend /env <name> to choose the one your next new conversation uses.";
18
- };
19
- /** 私聊 `/env <名称>` 之后(`{name}` 是环境名)。 */
20
- readonly envSwitched: {
21
- readonly zh: "下一个新对话将使用环境「{name}」,发送 /new 开始。";
22
- readonly en: "Your next new conversation will use the environment “{name}”; send /new to start one.";
23
- };
24
- /** 私聊 `/env <名称>` 没有匹配的可用环境(`{list}` 同 envList)。 */
25
- readonly envUnknown: {
26
- readonly zh: "没有找到名为「{name}」的环境。你的环境:\n{list}";
27
- readonly en: "No environment named “{name}”. Your environments:\n{list}";
28
- };
29
- /** `/env <name>` names an existing environment that is unavailable now (`{list}` as in envList). */
30
- readonly envUnavailable: {
31
- readonly zh: "环境「{name}」当前不可用(它的文件由未启用的沙箱提供方保存)。你的环境:\n{list}";
32
- readonly en: "The environment “{name}” is unavailable: its files are kept by a sandbox provider that is not active. Your environments:\n{list}";
33
- };
34
- /** 私聊 `/env` 时此人没有可用环境(部署没有云沙箱)。 */
35
- readonly envNone: {
36
- readonly zh: "你目前没有可用的环境。";
37
- readonly en: "You have no usable environments.";
38
- };
39
- /** 环境列表里当前 IM 默认环境的标记。 */
40
- readonly envCurrent: {
14
+ /** Direct message `/device`: lists the usable devices (`{list}` one per line, the current one marked). */
15
+ readonly deviceList: {
16
+ readonly zh: "你的设备:\n{list}\n发送 /device <名称> 选择下一个新对话使用的设备。";
17
+ readonly en: "Your devices:\n{list}\nSend /device <name> to choose the one your next new conversation uses.";
18
+ };
19
+ /** After a direct message `/device <name>` (`{name}` is the device's name). */
20
+ readonly deviceSwitched: {
21
+ readonly zh: "下一个新对话将使用设备「{name}」,发送 /new 开始。";
22
+ readonly en: "Your next new conversation will use the device “{name}”; send /new to start one.";
23
+ };
24
+ /** `/device <name>` matches no usable device (`{list}` as in deviceList). */
25
+ readonly deviceUnknown: {
26
+ readonly zh: "没有找到名为「{name}」的设备。你的设备:\n{list}";
27
+ readonly en: "No device named “{name}”. Your devices:\n{list}";
28
+ };
29
+ /** `/device <name>` names an existing device that is unavailable now (`{list}` as in deviceList). */
30
+ readonly deviceUnavailable: {
31
+ readonly zh: "设备「{name}」当前不可用(它的文件由未启用的沙箱提供方保存)。你的设备:\n{list}";
32
+ readonly en: "The device “{name}” is unavailable: its files are kept by a sandbox provider that is not active. Your devices:\n{list}";
33
+ };
34
+ /** Direct message `/device` when the person has no usable device (no cloud sandbox in the deployment). */
35
+ readonly deviceNone: {
36
+ readonly zh: "你目前没有可用的设备。";
37
+ readonly en: "You have no usable devices.";
38
+ };
39
+ /** The mark of the current IM default device in the device list. */
40
+ readonly deviceCurrent: {
41
41
  readonly zh: "(当前)";
42
42
  readonly en: " (current)";
43
43
  };
@@ -6,33 +6,33 @@
6
6
  export const CHANNEL_PHRASES = {
7
7
  /** 私聊 `/new` 之后。 */
8
8
  newConversation: { zh: "已开始新对话", en: "Started a new conversation." },
9
- /** 私聊 `/env`:列出可用环境(`{list}` 每行一个,当前的带标记)。 */
10
- envList: {
11
- zh: "你的环境:\n{list}\n发送 /env <名称> 选择下一个新对话使用的环境。",
12
- en: "Your environments:\n{list}\nSend /env <name> to choose the one your next new conversation uses.",
13
- },
14
- /** 私聊 `/env <名称>` 之后(`{name}` 是环境名)。 */
15
- envSwitched: {
16
- zh: "下一个新对话将使用环境「{name}」,发送 /new 开始。",
17
- en: "Your next new conversation will use the environment \u201c{name}\u201d; send /new to start one.",
18
- },
19
- /** 私聊 `/env <名称>` 没有匹配的可用环境(`{list}` 同 envList)。 */
20
- envUnknown: {
21
- zh: "没有找到名为「{name}」的环境。你的环境:\n{list}",
22
- en: "No environment named \u201c{name}\u201d. Your environments:\n{list}",
23
- },
24
- /** `/env <name>` names an existing environment that is unavailable now (`{list}` as in envList). */
25
- envUnavailable: {
26
- zh: "环境「{name}」当前不可用(它的文件由未启用的沙箱提供方保存)。你的环境:\n{list}",
27
- en: "The environment \u201c{name}\u201d is unavailable: its files are kept by a sandbox provider that is not active. Your environments:\n{list}",
28
- },
29
- /** 私聊 `/env` 时此人没有可用环境(部署没有云沙箱)。 */
30
- envNone: {
31
- zh: "你目前没有可用的环境。",
32
- en: "You have no usable environments.",
33
- },
34
- /** 环境列表里当前 IM 默认环境的标记。 */
35
- envCurrent: { zh: "(当前)", en: " (current)" },
9
+ /** Direct message `/device`: lists the usable devices (`{list}` one per line, the current one marked). */
10
+ deviceList: {
11
+ zh: "你的设备:\n{list}\n发送 /device <名称> 选择下一个新对话使用的设备。",
12
+ en: "Your devices:\n{list}\nSend /device <name> to choose the one your next new conversation uses.",
13
+ },
14
+ /** After a direct message `/device <name>` (`{name}` is the device's name). */
15
+ deviceSwitched: {
16
+ zh: "下一个新对话将使用设备「{name}」,发送 /new 开始。",
17
+ en: "Your next new conversation will use the device \u201c{name}\u201d; send /new to start one.",
18
+ },
19
+ /** `/device <name>` matches no usable device (`{list}` as in deviceList). */
20
+ deviceUnknown: {
21
+ zh: "没有找到名为「{name}」的设备。你的设备:\n{list}",
22
+ en: "No device named \u201c{name}\u201d. Your devices:\n{list}",
23
+ },
24
+ /** `/device <name>` names an existing device that is unavailable now (`{list}` as in deviceList). */
25
+ deviceUnavailable: {
26
+ zh: "设备「{name}」当前不可用(它的文件由未启用的沙箱提供方保存)。你的设备:\n{list}",
27
+ en: "The device \u201c{name}\u201d is unavailable: its files are kept by a sandbox provider that is not active. Your devices:\n{list}",
28
+ },
29
+ /** Direct message `/device` when the person has no usable device (no cloud sandbox in the deployment). */
30
+ deviceNone: {
31
+ zh: "你目前没有可用的设备。",
32
+ en: "You have no usable devices.",
33
+ },
34
+ /** The mark of the current IM default device in the device list. */
35
+ deviceCurrent: { zh: "(当前)", en: " (current)" },
36
36
  /** 未绑定的人在私聊里发消息:附绑定卡片。 */
37
37
  bindPrompt: {
38
38
  zh: "请先绑定你的 Capybara 账号,再与我对话。",
@@ -82,7 +82,7 @@ export function renderConfigDocs(schema) {
82
82
  "| `CAPYBARA_WEB_OBJECT_STORE_URL` | Object storage on the web origin: the object store's address as web reaches it (e.g. `http://seaweedfs-s3:8333`). When set, web proxies `/<bucket>/**` (and `/<bucket>` itself for POST only) there, so browsers upload attachments (presigned POST) and download attachments and artifacts (presigned GET) through web; set the object-store extension's `publicEndpoint` to the web origin with `forcePathStyle: true`. Only GET, HEAD and POST; the path is forwarded unchanged; cookies and authorization are not forwarded; responses carry `X-Content-Type-Options: nosniff` and `Content-Security-Policy: sandbox`; uploads are capped at `CAPYBARA_WEB_MAX_PACKAGE_BYTES`. Unset (default): off |",
83
83
  "| `CAPYBARA_WEB_OBJECT_STORE_BUCKET` | With `CAPYBARA_WEB_OBJECT_STORE_URL`: the bucket, equal to the object-store extension's `bucket` (it is the first path segment web proxies) |",
84
84
  "| `CAPYBARA_WEB_OBJECT_STORE_PUBLIC_HOST` | With `CAPYBARA_WEB_OBJECT_STORE_URL`: the host of the extension's `publicEndpoint` (a host such as `capybara.example.com`, or that URL). Sent upstream as `Host` instead of the incoming one, because presigned URLs sign the host they were issued for and front proxies rewrite it |",
85
- "| `CAPYBARA_WEB_GATEWAY_URL` | Connected machines on the web origin: a `gateway` replica's address as web reaches it (an http(s) URL, e.g. `http://gateway:8080`). WebSocket upgrades on exactly `/device/connect` are forwarded to it (`capybara-device` connects at `<http.publicUrl>/device/connect`). Unset, they go to `CAPYBARA_KERNEL_URL` (the kernel runs every role unless the deployment splits them), so only deployments with separate gateway replicas set it (compose does). A malformed value stops the web tier at startup |",
85
+ "| `CAPYBARA_WEB_GATEWAY_URL` | Local devices on the web origin: a `gateway` replica's address as web reaches it (an http(s) URL, e.g. `http://gateway:8080`). WebSocket upgrades on exactly `/device/connect` are forwarded to it (`capybara-device` connects at `<http.publicUrl>/device/connect`). Unset, they go to `CAPYBARA_KERNEL_URL` (the kernel runs every role unless the deployment splits them), so only deployments with separate gateway replicas set it (compose does). A malformed value stops the web tier at startup |",
86
86
  "| `CAPYBARA_DEV_UI` | When set to `1`, production builds also serve the `/dev/ui` component catalog page (off by default) |",
87
87
  "",
88
88
  ].join("\n");
@@ -219,9 +219,9 @@ export declare const KernelConfigSchema: z.ZodObject<{
219
219
  allowHosts: z.ZodDefault<z.ZodArray<z.ZodString>>;
220
220
  }, z.core.$strip>>;
221
221
  }, z.core.$strip>>;
222
- environments: z.ZodPrefault<z.ZodObject<{
222
+ devices: z.ZodPrefault<z.ZodObject<{
223
223
  maxPersonal: z.ZodDefault<z.ZodNumber>;
224
- device: z.ZodPrefault<z.ZodObject<{
224
+ local: z.ZodPrefault<z.ZodObject<{
225
225
  reconnectGraceSeconds: z.ZodDefault<z.ZodNumber>;
226
226
  leaseTtlMs: z.ZodDefault<z.ZodNumber>;
227
227
  authCodeTtlSeconds: z.ZodDefault<z.ZodNumber>;