@capybara-hq/kernel 0.1.0-rc.21 → 0.1.0-rc.23

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 (263) hide show
  1. package/dist/admin/admin.controller.d.ts +3 -3
  2. package/dist/admin/admin.controller.js +6 -2
  3. package/dist/admin/admin.schemas.d.ts +13 -0
  4. package/dist/agents/admin-agents.d.ts +16 -3
  5. package/dist/agents/admin-agents.js +65 -7
  6. package/dist/agents/agents.schemas.d.ts +24 -6
  7. package/dist/agents/agents.service.d.ts +4 -3
  8. package/dist/agents/agents.service.js +39 -26
  9. package/dist/agents/definition.d.ts +44 -6
  10. package/dist/agents/definition.js +86 -18
  11. package/dist/agents/from-template.d.ts +6 -3
  12. package/dist/agents/from-template.js +57 -44
  13. package/dist/agents/org-templates.js +97 -41
  14. package/dist/agents/templates.d.ts +6 -0
  15. package/dist/agents/templates.js +15 -1
  16. package/dist/background/launch.d.ts +43 -5
  17. package/dist/background/launch.js +88 -8
  18. package/dist/background/session.d.ts +14 -2
  19. package/dist/background/session.js +26 -4
  20. package/dist/background/status.d.ts +1 -1
  21. package/dist/background/status.js +3 -3
  22. package/dist/background/stop.d.ts +0 -2
  23. package/dist/background/stop.js +1 -21
  24. package/dist/catalog/admin-catalog.controller.d.ts +2 -4
  25. package/dist/catalog/admin-catalog.controller.js +2 -6
  26. package/dist/catalog/catalog-content.d.ts +5 -0
  27. package/dist/catalog/catalog-content.js +1 -0
  28. package/dist/catalog/catalog.module.js +3 -0
  29. package/dist/catalog/claude/report.d.ts +9 -2
  30. package/dist/catalog/claude/report.js +1 -0
  31. package/dist/catalog/claude/translate.js +1 -1
  32. package/dist/catalog/component-promotion.js +1 -2
  33. package/dist/catalog/component-state.d.ts +13 -1
  34. package/dist/catalog/component-state.js +14 -5
  35. package/dist/catalog/marketplaces.service.d.ts +1 -1
  36. package/dist/catalog/marketplaces.service.js +2 -1
  37. package/dist/catalog/org-catalog.controller.d.ts +13 -3
  38. package/dist/catalog/org-catalog.controller.js +26 -4
  39. package/dist/catalog/org-catalog.schemas.d.ts +13 -0
  40. package/dist/catalog/org-catalog.schemas.js +34 -0
  41. package/dist/catalog/org-plugin-uploads.controller.js +0 -1
  42. package/dist/catalog/org-plugin-uploads.d.ts +0 -1
  43. package/dist/catalog/org-plugin-uploads.js +0 -3
  44. package/dist/catalog/org-plugin-uploads.schemas.d.ts +0 -1
  45. package/dist/catalog/org-plugin-uploads.schemas.js +0 -2
  46. package/dist/catalog/platform-components.d.ts +0 -1
  47. package/dist/catalog/platform-components.js +3 -8
  48. package/dist/catalog/plugin-import.d.ts +0 -8
  49. package/dist/catalog/plugin-import.js +4 -35
  50. package/dist/catalog/plugin-install.d.ts +2 -2
  51. package/dist/catalog/plugin-install.js +2 -2
  52. package/dist/catalog/plugin-package.d.ts +7 -0
  53. package/dist/catalog/plugin-package.js +27 -1
  54. package/dist/catalog/plugin-upgrade.d.ts +5 -6
  55. package/dist/catalog/plugin-upgrade.js +5 -23
  56. package/dist/catalog/requests.service.d.ts +66 -10
  57. package/dist/catalog/requests.service.js +196 -15
  58. package/dist/channels/actions.d.ts +2 -0
  59. package/dist/channels/actions.js +19 -4
  60. package/dist/channels/cards.d.ts +16 -2
  61. package/dist/channels/cards.js +40 -7
  62. package/dist/channels/channels.module.js +3 -0
  63. package/dist/channels/outbound.d.ts +22 -1
  64. package/dist/channels/outbound.js +116 -7
  65. package/dist/channels/phrases.d.ts +25 -0
  66. package/dist/channels/phrases.js +19 -0
  67. package/dist/channels/threads.d.ts +12 -0
  68. package/dist/channels/threads.js +34 -0
  69. package/dist/config/schema.d.ts +23 -1
  70. package/dist/config/schema.js +107 -5
  71. package/dist/conversations/conversations.service.d.ts +42 -9
  72. package/dist/conversations/conversations.service.js +57 -25
  73. package/dist/conversations/events.d.ts +106 -11
  74. package/dist/conversations/events.js +121 -18
  75. package/dist/conversations/message-context.d.ts +6 -3
  76. package/dist/conversations/message-context.js +14 -10
  77. package/dist/conversations/queue.d.ts +15 -2
  78. package/dist/conversations/queue.js +22 -3
  79. package/dist/conversations/queue.service.d.ts +12 -6
  80. package/dist/conversations/queue.service.js +36 -13
  81. package/dist/db/kernel-schema.d.ts +105 -3
  82. package/dist/devices/conversation-devices.d.ts +8 -1
  83. package/dist/devices/conversation-devices.js +8 -0
  84. package/dist/devices/devices.controller.d.ts +21 -4
  85. package/dist/devices/devices.controller.js +46 -8
  86. package/dist/devices/devices.schemas.d.ts +9 -1
  87. package/dist/devices/devices.schemas.js +11 -3
  88. package/dist/devices/devices.service.d.ts +176 -4
  89. package/dist/devices/devices.service.js +347 -6
  90. package/dist/devices/dto.d.ts +56 -3
  91. package/dist/devices/dto.js +51 -1
  92. package/dist/devices/public-suffix.d.ts +6 -0
  93. package/dist/devices/public-suffix.js +79 -0
  94. package/dist/errors.d.ts +50 -5
  95. package/dist/errors.js +50 -5
  96. package/dist/evals/reconstruct.d.ts +18 -13
  97. package/dist/evals/reconstruct.js +50 -36
  98. package/dist/evals/recorded-tools.d.ts +7 -7
  99. package/dist/evals/recorded-tools.js +4 -3
  100. package/dist/evals/trajectory.d.ts +6 -1
  101. package/dist/evals/trajectory.js +7 -0
  102. package/dist/extensions/package.js +2 -2
  103. package/dist/http/api.module.js +5 -0
  104. package/dist/identity/settings.d.ts +53 -3
  105. package/dist/identity/settings.js +92 -9
  106. package/dist/inbox/inbox.module.js +2 -1
  107. package/dist/inbox/inbox.service.d.ts +19 -4
  108. package/dist/inbox/inbox.service.js +14 -3
  109. package/dist/infra/config/kernel-config.service.d.ts +7 -0
  110. package/dist/infra/config/kernel-config.service.js +31 -0
  111. package/dist/infra/events/kernel-events.d.ts +2 -1
  112. package/dist/local-devices/device-policy.service.d.ts +65 -0
  113. package/dist/local-devices/device-policy.service.js +217 -0
  114. package/dist/local-devices/local-device-gateway.d.ts +4 -2
  115. package/dist/local-devices/local-device-gateway.js +39 -11
  116. package/dist/local-devices/local-device-provider.d.ts +40 -3
  117. package/dist/local-devices/local-device-provider.js +109 -7
  118. package/dist/local-devices/local-devices.module.d.ts +2 -1
  119. package/dist/local-devices/local-devices.module.js +19 -3
  120. package/dist/local-devices/machines.d.ts +30 -3
  121. package/dist/local-devices/machines.js +79 -3
  122. package/dist/local-devices/network-grants.d.ts +104 -0
  123. package/dist/local-devices/network-grants.js +288 -0
  124. package/dist/local-devices/policy-summary.d.ts +20 -0
  125. package/dist/local-devices/policy-summary.js +63 -0
  126. package/dist/orgs/orgs.module.js +4 -10
  127. package/dist/orgs/roles.d.ts +1 -1
  128. package/dist/orgs/roles.js +4 -0
  129. package/dist/orgs/settings.controller.js +4 -3
  130. package/dist/orgs/settings.service.d.ts +172 -14
  131. package/dist/orgs/settings.service.js +229 -27
  132. package/dist/platform/exclusions.js +11 -1
  133. package/dist/platform/operation.js +4 -0
  134. package/dist/platform/ops/admin-items.ops.js +1 -1
  135. package/dist/platform/ops/admin.ops.js +32 -7
  136. package/dist/platform/ops/agent-skills.ops.js +2 -2
  137. package/dist/platform/ops/agent-templates.ops.js +2 -2
  138. package/dist/platform/ops/agents.ops.js +11 -15
  139. package/dist/platform/ops/devices.ops.js +3 -1
  140. package/dist/platform/ops/inbox.ops.js +19 -0
  141. package/dist/platform/ops/org-settings.ops.js +15 -6
  142. package/dist/platform/ops/orgs.ops.js +1 -0
  143. package/dist/platform/ops/platform.ops.d.ts +9 -1
  144. package/dist/platform/ops/platform.ops.js +34 -12
  145. package/dist/platform/ops/requests.ops.js +3 -2
  146. package/dist/platform/ops/schedules.ops.d.ts +21 -0
  147. package/dist/platform/ops/schedules.ops.js +470 -0
  148. package/dist/platform/ops/skills.ops.js +3 -3
  149. package/dist/platform/platform-ops.module.d.ts +2 -1
  150. package/dist/platform/platform-ops.module.js +5 -0
  151. package/dist/platform/route-schemas.js +3 -0
  152. package/dist/roles/worker.module.js +3 -0
  153. package/dist/runtime/context/build.js +13 -4
  154. package/dist/runtime/context/compaction.js +6 -3
  155. package/dist/runtime/context/device-paths.d.ts +43 -21
  156. package/dist/runtime/context/device-paths.js +104 -21
  157. package/dist/runtime/context/run-context.d.ts +9 -0
  158. package/dist/runtime/context/run-context.js +8 -0
  159. package/dist/runtime/context/skills.d.ts +14 -1
  160. package/dist/runtime/context/skills.js +36 -5
  161. package/dist/runtime/maintenance.d.ts +4 -2
  162. package/dist/runtime/maintenance.js +16 -5
  163. package/dist/runtime/run-finish.d.ts +6 -1
  164. package/dist/runtime/run-finish.js +16 -2
  165. package/dist/runtime/run-queue.js +21 -2
  166. package/dist/runtime/run-worker.js +14 -33
  167. package/dist/runtime/runtime.module.js +3 -0
  168. package/dist/runtime/subagents/definition.d.ts +32 -14
  169. package/dist/runtime/subagents/definition.js +106 -109
  170. package/dist/runtime/subagents/dispatch.js +4 -3
  171. package/dist/runtime/subagents/preamble.d.ts +2 -1
  172. package/dist/runtime/subagents/preamble.js +2 -1
  173. package/dist/runtime/waits.js +14 -4
  174. package/dist/sandbox/platform-tiers.d.ts +86 -0
  175. package/dist/sandbox/platform-tiers.js +97 -0
  176. package/dist/sandbox/sandbox.service.d.ts +121 -11
  177. package/dist/sandbox/sandbox.service.js +351 -30
  178. package/dist/sandbox/tiers.d.ts +98 -0
  179. package/dist/sandbox/tiers.js +104 -0
  180. package/dist/schedules/effective-settings.d.ts +16 -0
  181. package/dist/schedules/effective-settings.js +17 -0
  182. package/dist/schedules/errors.d.ts +8 -0
  183. package/dist/schedules/errors.js +8 -0
  184. package/dist/schedules/fire.d.ts +118 -0
  185. package/dist/schedules/fire.js +625 -0
  186. package/dist/schedules/grant-rules.d.ts +94 -0
  187. package/dist/schedules/grant-rules.js +126 -0
  188. package/dist/schedules/job-ids.d.ts +32 -0
  189. package/dist/schedules/job-ids.js +27 -0
  190. package/dist/schedules/pause.d.ts +9 -0
  191. package/dist/schedules/pause.js +33 -0
  192. package/dist/schedules/run-tracker.d.ts +81 -0
  193. package/dist/schedules/run-tracker.js +333 -0
  194. package/dist/schedules/scan.job.d.ts +64 -0
  195. package/dist/schedules/scan.job.js +303 -0
  196. package/dist/schedules/schedule-math.d.ts +31 -0
  197. package/dist/schedules/schedule-math.js +223 -0
  198. package/dist/schedules/scheduled-tasks.service.d.ts +351 -0
  199. package/dist/schedules/scheduled-tasks.service.js +1193 -0
  200. package/dist/schedules/schedules.controller.d.ts +68 -0
  201. package/dist/schedules/schedules.controller.js +242 -0
  202. package/dist/schedules/schedules.module.d.ts +16 -0
  203. package/dist/schedules/schedules.module.js +65 -0
  204. package/dist/schedules/schedules.schemas.d.ts +316 -0
  205. package/dist/schedules/schedules.schemas.js +186 -0
  206. package/dist/schedules/store.d.ts +81 -0
  207. package/dist/schedules/store.js +390 -0
  208. package/dist/schedules/store.module.d.ts +6 -0
  209. package/dist/schedules/store.module.js +21 -0
  210. package/dist/schedules/types.d.ts +108 -0
  211. package/dist/schedules/types.js +1 -0
  212. package/dist/schedules/unattended.d.ts +117 -0
  213. package/dist/schedules/unattended.js +228 -0
  214. package/dist/setup/oauth-token-probe.js +8 -4
  215. package/dist/skills/agent-skills.service.d.ts +4 -8
  216. package/dist/skills/agent-skills.service.js +18 -53
  217. package/dist/skills/catalog.d.ts +65 -62
  218. package/dist/skills/catalog.js +109 -206
  219. package/dist/skills/conversation-catalog.d.ts +3 -3
  220. package/dist/skills/conversation-catalog.js +5 -12
  221. package/dist/skills/invoke.d.ts +2 -2
  222. package/dist/skills/skills.controller.d.ts +3 -1
  223. package/dist/skills/skills.service.d.ts +38 -37
  224. package/dist/skills/skills.service.js +168 -107
  225. package/dist/skills/usable.d.ts +57 -8
  226. package/dist/skills/usable.js +172 -38
  227. package/dist/tools/approvals.controller.d.ts +4 -2
  228. package/dist/tools/approvals.controller.js +17 -2
  229. package/dist/tools/approvals.schemas.d.ts +1 -0
  230. package/dist/tools/approvals.schemas.js +3 -1
  231. package/dist/tools/approvals.service.d.ts +182 -7
  232. package/dist/tools/approvals.service.js +597 -13
  233. package/dist/tools/builtin-names.d.ts +25 -4
  234. package/dist/tools/builtin-names.js +45 -4
  235. package/dist/tools/builtins/builtin-tools.d.ts +8 -0
  236. package/dist/tools/builtins/builtin-tools.js +23 -2
  237. package/dist/tools/builtins/sandbox/bash.js +16 -7
  238. package/dist/tools/builtins/sandbox/common.d.ts +1 -1
  239. package/dist/tools/builtins/sandbox/common.js +33 -10
  240. package/dist/tools/builtins/sandbox/edit.js +7 -3
  241. package/dist/tools/builtins/sandbox/file-state.d.ts +31 -1
  242. package/dist/tools/builtins/sandbox/file-state.js +33 -3
  243. package/dist/tools/builtins/sandbox/write.js +8 -4
  244. package/dist/tools/builtins/schedules.d.ts +107 -0
  245. package/dist/tools/builtins/schedules.js +789 -0
  246. package/dist/tools/elicitation.d.ts +2 -0
  247. package/dist/tools/elicitation.js +1 -1
  248. package/dist/tools/fixed-ask.d.ts +7 -0
  249. package/dist/tools/fixed-ask.js +9 -0
  250. package/dist/tools/network-asks.d.ts +109 -0
  251. package/dist/tools/network-asks.js +221 -0
  252. package/dist/tools/pipeline.d.ts +53 -6
  253. package/dist/tools/pipeline.js +202 -13
  254. package/dist/tools/policy.d.ts +21 -8
  255. package/dist/tools/policy.js +63 -9
  256. package/dist/tools/registry.d.ts +10 -1
  257. package/dist/tools/tools.module.js +12 -0
  258. package/package.json +2 -2
  259. package/src/migrations/0113_scheduled_tasks.sql +108 -0
  260. package/src/migrations/0114_network_asks.sql +23 -0
  261. package/src/migrations/0115_network_requests.sql +28 -0
  262. package/src/migrations/0116_skills_default_on.sql +37 -0
  263. package/src/migrations/0117_sandbox_tiers.sql +11 -0
@@ -0,0 +1,63 @@
1
+ import { isSandboxTier, } from "@capybara-hq/plugin-sdk";
2
+ const KNOWN_FEATURES = ["networkReport", "policyOp", "tiers"];
3
+ /**
4
+ * The known features in `v` (a hello's `features` or the stored column), in a fixed order and
5
+ * deduped; anything else (unknown names, a non-array) is dropped.
6
+ */
7
+ export function deviceFeaturesOf(v) {
8
+ if (!Array.isArray(v))
9
+ return [];
10
+ return KNOWN_FEATURES.filter((f) => v.includes(f));
11
+ }
12
+ /**
13
+ * `v` as a local policy summary (network ask-to-allow spec §5.4), or null when it is absent or not
14
+ * a valid one. The device is the authority on its policy: the kernel only keeps what it last said,
15
+ * for the device page and to pick a card's options, never to decide what a command may reach.
16
+ */
17
+ export function localPolicyOf(v) {
18
+ if (typeof v !== "object" || v === null || Array.isArray(v))
19
+ return null;
20
+ const o = v;
21
+ if (o.tier !== undefined && !isSandboxTier(o.tier))
22
+ return null;
23
+ if (!isSandboxTier(o.effectiveTier))
24
+ return null;
25
+ if (o.isolation !== "sandbox" && o.isolation !== "none")
26
+ return null;
27
+ if (o.localhost !== "on" && o.localhost !== "off-proxy-detected" && o.localhost !== "off") {
28
+ return null;
29
+ }
30
+ if (o.unixSockets !== "roots" && o.unixSockets !== "all-masked" && o.unixSockets !== "off") {
31
+ return null;
32
+ }
33
+ if (o.remoteGrants !== "owner" && o.remoteGrants !== "off")
34
+ return null;
35
+ if (!Array.isArray(o.allowedDomains))
36
+ return null;
37
+ if (!o.allowedDomains.every((d) => typeof d === "string"))
38
+ return null;
39
+ return {
40
+ ...(o.tier !== undefined && { tier: o.tier }),
41
+ effectiveTier: o.effectiveTier,
42
+ isolation: o.isolation,
43
+ localhost: o.localhost,
44
+ unixSockets: o.unixSockets,
45
+ allowedDomains: [...o.allowedDomains],
46
+ remoteGrants: o.remoteGrants,
47
+ };
48
+ }
49
+ /**
50
+ * The isolation a policy summary states, read from its `isolation` field alone (a hello's raw
51
+ * `policy` or the stored column), so a summary the kernel cannot otherwise read (a newer program's
52
+ * new value elsewhere, a broken one) still tells whether commands run without a sandbox: `sandbox`
53
+ * only when it says exactly that, `none` for any other present summary (fail closed), null when
54
+ * there is none.
55
+ */
56
+ export function isolationOf(v) {
57
+ if (v === undefined || v === null)
58
+ return null;
59
+ if (typeof v === "object" && !Array.isArray(v)) {
60
+ return v.isolation === "sandbox" ? "sandbox" : "none";
61
+ }
62
+ return "none";
63
+ }
@@ -21,7 +21,7 @@ import { MembersService } from "./members.service.js";
21
21
  import { Offboarding } from "./offboarding.js";
22
22
  import { OrgLockModule } from "./org-lock.js";
23
23
  import { OrgsService } from "./orgs.service.js";
24
- import { OrgSettingsService } from "./settings.service.js";
24
+ import { OrgSettingsModule } from "./settings.service.js";
25
25
  /**
26
26
  * Organizations: orgs, org settings, members, invitations, offboarding (with its sweep cron) and
27
27
  * directory sync (the hourly scan cron, one-off syncs on the maintenance queue).
@@ -35,6 +35,7 @@ OrgsModule = __decorate([
35
35
  // offboarding publishes the events it cancelled
36
36
  EventLogModule,
37
37
  OrgLockModule,
38
+ OrgSettingsModule,
38
39
  ExtensionsModule,
39
40
  // offboarding clears credentials and cancels approvals and questions
40
41
  ToolsModule,
@@ -49,18 +50,11 @@ OrgsModule = __decorate([
49
50
  // the producer side of directory-sync jobs (the maintenance processor consumes them)
50
51
  QueueModule.registerQueue(MAINTENANCE_QUEUE_NAME),
51
52
  ],
52
- providers: [
53
- OrgsService,
54
- OrgSettingsService,
55
- MembersService,
56
- InvitationsService,
57
- Offboarding,
58
- DirectorySync,
59
- ],
53
+ providers: [OrgsService, MembersService, InvitationsService, Offboarding, DirectorySync],
60
54
  exports: [
61
55
  OrgLockModule,
56
+ OrgSettingsModule,
62
57
  OrgsService,
63
- OrgSettingsService,
64
58
  MembersService,
65
59
  InvitationsService,
66
60
  Offboarding,
@@ -4,7 +4,7 @@ export type OrgRole = (typeof ORG_ROLES)[number];
4
4
  /** `role` 是否不低于 `min`。 */
5
5
  export declare function roleAtLeast(role: OrgRole, min: OrgRole): boolean;
6
6
  /** 组织级动作;路由用 `@OrgAction(action)` 声明所需动作。 */
7
- export type OrgAction = "org.read" | "org.update" | "org.delete" | "org.transfer" | "org.members.read" | "org.members.manage" | "org.invitations.manage" | "org.tokens.manage" | "org.extensions.read" | "org.extensions.manage" | "agents.create" | "agents.use" | "agents.manage" | "connectors.manage" | "connectors.use" | "approvals.decide" | "channels.manage" | "skills.read" | "skills.manage" | "ui.use" | "trajectories.read" | "evals.manage" | "org.models.manage" | "catalog.read" | "catalog.request" | "catalog.decide" | "catalog.upload";
7
+ export type OrgAction = "org.read" | "org.update" | "org.delete" | "org.transfer" | "org.members.read" | "org.members.manage" | "org.invitations.manage" | "org.tokens.manage" | "org.extensions.read" | "org.extensions.manage" | "agents.create" | "agents.use" | "agents.manage" | "connectors.manage" | "connectors.use" | "approvals.decide" | "channels.manage" | "skills.read" | "skills.manage" | "ui.use" | "trajectories.read" | "evals.manage" | "org.models.manage" | "catalog.read" | "catalog.request" | "catalog.decide" | "catalog.upload" | "schedules.use" | "schedules.manage";
8
8
  /** 每个动作所需的最低角色。 */
9
9
  export declare const ACTION_MIN_ROLE: Record<OrgAction, OrgRole>;
10
10
  /** 只允许 user principal 执行的动作:服务令牌即使角色足够也拒绝(除 SERVICE_ALLOWED 外全部)。 */
@@ -47,6 +47,10 @@ export const ACTION_MIN_ROLE = {
47
47
  "catalog.decide": "admin",
48
48
  // An org admin uploads a plugin package the org owns (spec §14.1 item 1, ruling P3-7)
49
49
  "catalog.upload": "admin",
50
+ // Scheduled tasks (spec 2026-11-11 §10): create, edit, pause, resume, run and delete one's own
51
+ "schedules.use": "member",
52
+ // list every task of the org, pause, resume and delete any (never edit another person's)
53
+ "schedules.manage": "admin",
50
54
  };
51
55
  /** 服务令牌也可执行的动作:只读的 org.read、org.members.read,以及使用 agent 的 agents.use。 */
52
56
  const SERVICE_ALLOWED = new Set([
@@ -23,15 +23,16 @@ let OrgSettingsController = class OrgSettingsController {
23
23
  async get(org) {
24
24
  return {
25
25
  settings: await this.settings.get(org.orgId),
26
- deployment: this.settings.deployment(),
26
+ deployment: await this.settings.deployment(),
27
27
  sandboxLimits: await this.settings.sandboxLimits(org.orgId),
28
28
  };
29
29
  }
30
30
  async update(principal, org, body) {
31
31
  const p = requireUser(principal);
32
32
  return {
33
- settings: await this.settings.update(org.orgId, body, p.account.id, patTokenId(p)),
34
- deployment: this.settings.deployment(),
33
+ // an API token may narrow the sandbox, never widen it (sandbox dev tiers spec §2)
34
+ settings: await this.settings.update(org.orgId, body, p.account.id, patTokenId(p), undefined, { onlyNarrows: patTokenId(p) !== undefined }),
35
+ deployment: await this.settings.deployment(),
35
36
  sandboxLimits: await this.settings.sandboxLimits(org.orgId),
36
37
  };
37
38
  }
@@ -1,9 +1,12 @@
1
- import { type SandboxLimits } from "@capybara-hq/plugin-sdk";
1
+ import { type SandboxLimits, type SandboxTier } from "@capybara-hq/plugin-sdk";
2
2
  import { z } from "zod";
3
3
  import type { KernelSchemaDb } from "../db/kernel-schema.js";
4
4
  import { KernelConfigService } from "../infra/config/kernel-config.service.js";
5
5
  import { KernelDb } from "../infra/database/kernel-db.js";
6
6
  import { TransactionHost } from "../infra/database/transaction-host.js";
7
+ import type { KernelLogger } from "../log.js";
8
+ import { type PlatformTiers } from "../sandbox/platform-tiers.js";
9
+ import { type EffectiveSandboxPolicy } from "../sandbox/tiers.js";
7
10
  import { OrgLock } from "./org-lock.js";
8
11
  /**
9
12
  * 组织设置(`capybara.orgs.settings` jsonb)。读取宽松:缺失或非法的字段按默认值,未知键保留不动
@@ -14,7 +17,10 @@ import { OrgLock } from "./org-lock.js";
14
17
  * `Read` / `Glob` / `Grep` 外都需要审批(执行时实时读取)。
15
18
  * - `wakeOnBackgroundTask`:组织对 `runtime.wakeOnBackgroundTask` 的覆盖(缺省跟随部署),见 {@link effectiveWakeOnBackgroundTask}。
16
19
  * - `sandboxEgress`:组织的沙箱出站(Ruling M19 / D6),缺省跟随部署的 `sandbox.limits.egress` + `allowHosts`。
17
- * 见 {@link effectiveSandboxEgress}。存量值非法时按 `none` 读(宁可断网,不悄悄放宽到部署默认)。
20
+ * See `baseSandboxEgress` (sandbox/tiers.ts). 存量值非法时按 `none` 读(宁可断网,不悄悄放宽到部署默认)。
21
+ * - `sandboxTier`: the org's sandbox tier ceiling, default and unsandboxed switch (sandbox dev tiers
22
+ * spec §4.1), each absent = follow the platform (`sandbox.tiers`); never above the platform. An
23
+ * invalid stored value reads as `{ max: "strict" }` (narrower, never wider).
18
24
  * - `platformTool`: the `Platform` builtin for the whole org (Platform tool spec §3): `on`,
19
25
  * `read-only` (writes listed as unavailable) or `off` (default `on`).
20
26
  * - `timeZone`: the org's default time zone (IANA; absent = UTC) for senders without one of their
@@ -38,6 +44,25 @@ export declare const SandboxEgressSettingSchema: z.ZodObject<{
38
44
  allowHosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
45
  }, z.core.$strict>;
40
46
  export type SandboxEgressSetting = z.infer<typeof SandboxEgressSettingSchema>;
47
+ /**
48
+ * The org's sandbox tier setting (sandbox dev tiers spec §4.1): `max` the highest tier its devices
49
+ * may reach, `default` the tier of a device that chose none, `allowUnsandboxed` false forbids
50
+ * unsandboxed local devices. Each absent = follow the platform's `sandbox.tiers`.
51
+ */
52
+ export declare const SandboxTierSettingSchema: z.ZodObject<{
53
+ max: z.ZodOptional<z.ZodEnum<{
54
+ dev: "dev";
55
+ open: "open";
56
+ strict: "strict";
57
+ }>>;
58
+ default: z.ZodOptional<z.ZodEnum<{
59
+ dev: "dev";
60
+ open: "open";
61
+ strict: "strict";
62
+ }>>;
63
+ allowUnsandboxed: z.ZodOptional<z.ZodBoolean>;
64
+ }, z.core.$strict>;
65
+ export type SandboxTierSetting = z.infer<typeof SandboxTierSettingSchema>;
41
66
  /**
42
67
  * The org's theme setting (themes spec §7): `id` a theme on in the org (a `platform_themes` id),
43
68
  * null = follow the platform's default; `personal: "locked"` hides the personal picker in the org
@@ -53,6 +78,45 @@ export declare const OrgThemeSettingSchema: z.ZodObject<{
53
78
  export type OrgThemeSetting = z.infer<typeof OrgThemeSettingSchema>;
54
79
  /** The theme setting of an org that has none: follow the platform, personal picks allowed. */
55
80
  export declare const DEFAULT_ORG_THEME: OrgThemeSetting;
81
+ /**
82
+ * Org settings of scheduled tasks (spec §9); every field reads leniently (invalid = default,
83
+ * except `forbiddenTools`, which keeps its valid entries).
84
+ */
85
+ export declare const ScheduledTasksSettingsSchema: z.ZodObject<{
86
+ enabled: z.ZodCatch<z.ZodDefault<z.ZodBoolean>>;
87
+ minIntervalMinutes: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
88
+ maxTasksPerMember: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
89
+ maxTasksPerOrg: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
90
+ maxRunsPerHour: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
91
+ defaultExpiryDays: z.ZodCatch<z.ZodDefault<z.ZodNullable<z.ZodNumber>>>;
92
+ catchUpWindowMinutes: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
93
+ unattendedAsk: z.ZodCatch<z.ZodDefault<z.ZodEnum<{
94
+ fail: "fail";
95
+ wait: "wait";
96
+ }>>>;
97
+ pauseAfterFailures: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
98
+ forbiddenTools: z.ZodCatch<z.ZodPreprocess<z.ZodDefault<z.ZodArray<z.ZodString>>, unknown>>;
99
+ }, z.core.$strip>;
100
+ export type ScheduledTasksSettings = z.infer<typeof ScheduledTasksSettingsSchema>;
101
+ /**
102
+ * The PATCH form: a partial merge into the group (fields left out keep their stored value; see
103
+ * `OrgSettingsService.update`). A field given replaces that field whole, `forbiddenTools` too.
104
+ */
105
+ export declare const ScheduledTasksPatchSchema: z.ZodObject<{
106
+ enabled: z.ZodOptional<z.ZodBoolean>;
107
+ minIntervalMinutes: z.ZodOptional<z.ZodNumber>;
108
+ maxTasksPerMember: z.ZodOptional<z.ZodNumber>;
109
+ maxTasksPerOrg: z.ZodOptional<z.ZodNumber>;
110
+ maxRunsPerHour: z.ZodOptional<z.ZodNumber>;
111
+ defaultExpiryDays: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
112
+ catchUpWindowMinutes: z.ZodOptional<z.ZodNumber>;
113
+ unattendedAsk: z.ZodOptional<z.ZodEnum<{
114
+ fail: "fail";
115
+ wait: "wait";
116
+ }>>;
117
+ pauseAfterFailures: z.ZodOptional<z.ZodNumber>;
118
+ forbiddenTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
119
+ }, z.core.$strict>;
56
120
  export declare const OrgSettingsSchema: z.ZodObject<{
57
121
  toolSearch: z.ZodCatch<z.ZodDefault<z.ZodEnum<{
58
122
  off: "off";
@@ -78,6 +142,19 @@ export declare const OrgSettingsSchema: z.ZodObject<{
78
142
  }>;
79
143
  allowHosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
80
144
  }, z.core.$strict>>>;
145
+ sandboxTier: z.ZodCatch<z.ZodOptional<z.ZodObject<{
146
+ max: z.ZodOptional<z.ZodEnum<{
147
+ dev: "dev";
148
+ open: "open";
149
+ strict: "strict";
150
+ }>>;
151
+ default: z.ZodOptional<z.ZodEnum<{
152
+ dev: "dev";
153
+ open: "open";
154
+ strict: "strict";
155
+ }>>;
156
+ allowUnsandboxed: z.ZodOptional<z.ZodBoolean>;
157
+ }, z.core.$strict>>>;
81
158
  wakeOnBackgroundTask: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
82
159
  timeZone: z.ZodCatch<z.ZodOptional<z.ZodString>>;
83
160
  theme: z.ZodCatch<z.ZodOptional<z.ZodObject<{
@@ -88,6 +165,21 @@ export declare const OrgSettingsSchema: z.ZodObject<{
88
165
  }>;
89
166
  }, z.core.$strict>>>;
90
167
  uiArrangement: z.ZodCatch<z.ZodOptional<z.ZodType<Partial<Record<"agent.detail.section" | "conversation.composer.frame" | "conversation.empty" | "conversation.panel" | "conversation.properties.section" | "conversation.tool-result.card" | "file.preview" | "org.page" | "org.settings.section" | "platform.page" | "shell.brand" | "shell.overlay", import("../ui/arrangement.js").UiArrangementEntry>>, unknown, z.core.$ZodTypeInternals<Partial<Record<"agent.detail.section" | "conversation.composer.frame" | "conversation.empty" | "conversation.panel" | "conversation.properties.section" | "conversation.tool-result.card" | "file.preview" | "org.page" | "org.settings.section" | "platform.page" | "shell.brand" | "shell.overlay", import("../ui/arrangement.js").UiArrangementEntry>>, unknown>>>>;
168
+ scheduledTasks: z.ZodCatch<z.ZodPrefault<z.ZodObject<{
169
+ enabled: z.ZodCatch<z.ZodDefault<z.ZodBoolean>>;
170
+ minIntervalMinutes: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
171
+ maxTasksPerMember: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
172
+ maxTasksPerOrg: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
173
+ maxRunsPerHour: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
174
+ defaultExpiryDays: z.ZodCatch<z.ZodDefault<z.ZodNullable<z.ZodNumber>>>;
175
+ catchUpWindowMinutes: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
176
+ unattendedAsk: z.ZodCatch<z.ZodDefault<z.ZodEnum<{
177
+ fail: "fail";
178
+ wait: "wait";
179
+ }>>>;
180
+ pauseAfterFailures: z.ZodCatch<z.ZodDefault<z.ZodNumber>>;
181
+ forbiddenTools: z.ZodCatch<z.ZodPreprocess<z.ZodDefault<z.ZodArray<z.ZodString>>, unknown>>;
182
+ }, z.core.$strip>>>;
91
183
  }, z.core.$strip>;
92
184
  export type OrgSettings = z.infer<typeof OrgSettingsSchema>;
93
185
  /** PATCH 体:只改给出的字段;未知字段 → 400。 */
@@ -117,6 +209,19 @@ export declare const OrgSettingsPatchSchema: z.ZodObject<{
117
209
  }>;
118
210
  allowHosts: z.ZodOptional<z.ZodArray<z.ZodString>>;
119
211
  }, z.core.$strict>>>;
212
+ sandboxTier: z.ZodOptional<z.ZodNullable<z.ZodObject<{
213
+ max: z.ZodOptional<z.ZodEnum<{
214
+ dev: "dev";
215
+ open: "open";
216
+ strict: "strict";
217
+ }>>;
218
+ default: z.ZodOptional<z.ZodEnum<{
219
+ dev: "dev";
220
+ open: "open";
221
+ strict: "strict";
222
+ }>>;
223
+ allowUnsandboxed: z.ZodOptional<z.ZodBoolean>;
224
+ }, z.core.$strict>>>;
120
225
  timeZone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
121
226
  theme: z.ZodOptional<z.ZodNullable<z.ZodObject<{
122
227
  id: z.ZodNullable<z.ZodString>;
@@ -126,15 +231,23 @@ export declare const OrgSettingsPatchSchema: z.ZodObject<{
126
231
  }>;
127
232
  }, z.core.$strict>>>;
128
233
  uiArrangement: z.ZodOptional<z.ZodType<Partial<Record<"agent.detail.section" | "conversation.composer.frame" | "conversation.empty" | "conversation.panel" | "conversation.properties.section" | "conversation.tool-result.card" | "file.preview" | "org.page" | "org.settings.section" | "platform.page" | "shell.brand" | "shell.overlay", import("../ui/arrangement.js").UiArrangementEntry | null>>, unknown, z.core.$ZodTypeInternals<Partial<Record<"agent.detail.section" | "conversation.composer.frame" | "conversation.empty" | "conversation.panel" | "conversation.properties.section" | "conversation.tool-result.card" | "file.preview" | "org.page" | "org.settings.section" | "platform.page" | "shell.brand" | "shell.overlay", import("../ui/arrangement.js").UiArrangementEntry | null>>, unknown>>>;
234
+ scheduledTasks: z.ZodOptional<z.ZodObject<{
235
+ enabled: z.ZodOptional<z.ZodBoolean>;
236
+ minIntervalMinutes: z.ZodOptional<z.ZodNumber>;
237
+ maxTasksPerMember: z.ZodOptional<z.ZodNumber>;
238
+ maxTasksPerOrg: z.ZodOptional<z.ZodNumber>;
239
+ maxRunsPerHour: z.ZodOptional<z.ZodNumber>;
240
+ defaultExpiryDays: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
241
+ catchUpWindowMinutes: z.ZodOptional<z.ZodNumber>;
242
+ unattendedAsk: z.ZodOptional<z.ZodEnum<{
243
+ fail: "fail";
244
+ wait: "wait";
245
+ }>>;
246
+ pauseAfterFailures: z.ZodOptional<z.ZodNumber>;
247
+ forbiddenTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
248
+ }, z.core.$strict>>;
129
249
  }, z.core.$strict>;
130
250
  export type OrgSettingsPatch = z.infer<typeof OrgSettingsPatchSchema>;
131
- /** 部署的沙箱出站(`sandbox.limits.egress` + `allowHosts`)。 */
132
- export type DeploymentEgress = Pick<SandboxLimits, "egress" | "allowHosts">;
133
- /**
134
- * 组织实际生效的沙箱出站:没有组织设置 → 部署默认;`none` → 只有回环;`allowlist` → 组织的白名单
135
- * (省略时用部署的),但部署是 `none` 时仍为 `none`(组织永远不比部署放得更开,部署改成 none 后存量设置也随之收紧)。
136
- */
137
- export declare function effectiveSandboxEgress(deployment: DeploymentEgress, org: SandboxEgressSetting | undefined): DeploymentEgress;
138
251
  /** Whether a finished background task wakes an idle conversation: the org's setting, else the deployment's. */
139
252
  export declare function effectiveWakeOnBackgroundTask(deployment: boolean, org: OrgSettings["wakeOnBackgroundTask"]): boolean;
140
253
  /**
@@ -154,14 +267,23 @@ export interface OrgSandboxLimits {
154
267
  /** 设置页展示用的部署默认值(`GET` 一并返回)。 */
155
268
  export interface OrgSettingsDeployment {
156
269
  sandboxEgress: {
157
- mode: SandboxLimits["egress"];
270
+ mode: "none" | "allowlist";
158
271
  allowHosts: string[];
159
272
  };
273
+ /** The platform's tiers (`sandbox.tiers`) and the dev hosts the dev tier adds. */
274
+ sandboxTiers: {
275
+ max: SandboxTier;
276
+ default: SandboxTier;
277
+ allowUnsandboxed: boolean;
278
+ devHosts: string[];
279
+ };
160
280
  }
161
281
  /** 把存储的 jsonb 解析为设置(宽松,见 {@link OrgSettingsSchema})。 */
162
282
  export declare function parseOrgSettings(raw: unknown): OrgSettings;
163
283
  /** 读组织设置(每次实时读 PG,多副本下改动立即生效);组织不存在或已删除按默认值。 */
164
284
  export declare function readOrgSettings(db: KernelSchemaDb, orgId: string): Promise<OrgSettings>;
285
+ /** Whether a stored settings object holds a `sandboxTier` this version reads as `{ max: "strict" }`. */
286
+ export declare function invalidStoredSandboxTier(raw: unknown): boolean;
165
287
  /** 组织设置服务:读取与修改(修改需 `org.update`,锁内实时复核角色,写审计)。 */
166
288
  export declare class OrgSettingsService {
167
289
  private readonly db;
@@ -169,18 +291,54 @@ export declare class OrgSettingsService {
169
291
  private readonly orgLock;
170
292
  /** The deployment config (`sandboxEgress` may not exceed the deployment's). */
171
293
  private readonly config;
294
+ private readonly log?;
172
295
  constructor(db: KernelDb, txHost: TransactionHost, orgLock: OrgLock,
173
296
  /** The deployment config (`sandboxEgress` may not exceed the deployment's). */
174
- config: Pick<KernelConfigService, "get">);
297
+ config: Pick<KernelConfigService, "get">, log?: KernelLogger | undefined);
298
+ /** Parses stored settings, warning when an invalid `sandboxTier` narrows to `{ max: "strict" }`. */
299
+ private parseStored;
300
+ /** The platform's effective sandbox tiers (the startup config over the admin console's choice). */
301
+ platformTiers(): Promise<PlatformTiers>;
175
302
  /** 部署默认值(设置页展示「跟随部署」时的实际取值)。 */
176
- deployment(): OrgSettingsDeployment;
303
+ deployment(): Promise<OrgSettingsDeployment>;
177
304
  /** 组织实际生效的沙箱 cpu / 内存(只读;由超级管理员在部署设置里覆盖)。 */
178
305
  sandboxLimits(orgId: string): Promise<OrgSandboxLimits>;
179
306
  get(orgId: string): Promise<OrgSettings>;
180
307
  /** The refusals of {@link update} that need no read of the org (the Platform tool's precheck). */
181
- check(patch: OrgSettingsPatch): void;
308
+ check(patch: OrgSettingsPatch): Promise<void>;
182
309
  update(orgId: string, patch: OrgSettingsPatch, actorAccountId: string, actorTokenId?: string,
183
310
  /** Merged into the audit detail (the Platform tool's `via: "agent"`). */
184
- auditDetail?: Record<string, unknown>): Promise<OrgSettings>;
311
+ auditDetail?: Record<string, unknown>,
312
+ /**
313
+ * `onlyNarrows` (the Platform tool, API tokens): refuse a `sandboxTier` or `sandboxEgress`
314
+ * change that widens (see {@link assertOnlyNarrows}); only a person in a session widens.
315
+ */
316
+ opts?: {
317
+ onlyNarrows?: boolean;
318
+ }): Promise<OrgSettings>;
319
+ /**
320
+ * The effective sandbox policy for the org's settings and a device's own tier (null = none);
321
+ * `tiers`: the platform's tiers when the caller already read them.
322
+ */
323
+ sandboxPolicy(settings: OrgSettings, deviceTier: SandboxTier | null, tiers?: PlatformTiers): Promise<EffectiveSandboxPolicy>;
324
+ /**
325
+ * Refuses a patch that widens the org's sandbox (sandbox dev tiers spec §2, §7.2: only a person
326
+ * widens it, never the Platform tool or an API token):
327
+ * - `sandboxTier`: the effective ceiling, default or unsandboxed switch rises, or a stored cap
328
+ * loosens (an absent `max` / `default` follows the platform, so it ranks above every tier and
329
+ * clearing a cap that equals today's platform value is a widening; an explicit
330
+ * `allowUnsandboxed: false` stays false). A cleared `default` under a new `max` no higher than
331
+ * the old default is no loosening: the default never exceeds the ceiling. The value is
332
+ * replaced whole, so the refusal names the fields the patch would clear;
333
+ * - `sandboxEgress`: the base list grows: from none to anything else, or to hosts (the
334
+ * deployment's when the org gives none) not all in the current list.
335
+ */
336
+ assertOnlyNarrows(before: OrgSettings, patch: OrgSettingsPatch): Promise<void>;
185
337
  private updateIn;
186
338
  }
339
+ /**
340
+ * The one {@link OrgSettingsService}: the orgs module re-exports it, and the catalog imports it
341
+ * directly (approving a network request writes `sandboxEgress`) without a cycle through OrgsModule.
342
+ */
343
+ export declare class OrgSettingsModule {
344
+ }