@capybara-hq/kernel 0.1.0-rc.6 → 0.1.0-rc.8

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 (333) hide show
  1. package/bootstrap.json +27 -3
  2. package/dist/admin/admin.controller.d.ts +8 -72
  3. package/dist/admin/admin.controller.js +21 -46
  4. package/dist/admin/admin.schemas.d.ts +57 -0
  5. package/dist/admin/admin.schemas.js +50 -0
  6. package/dist/admin/extensions.controller.d.ts +10 -0
  7. package/dist/admin/extensions.controller.js +18 -0
  8. package/dist/admin/extensions.schemas.d.ts +7 -0
  9. package/dist/admin/extensions.schemas.js +10 -0
  10. package/dist/admin/limit-defaults.d.ts +20 -0
  11. package/dist/admin/limit-defaults.js +10 -0
  12. package/dist/agents/agent-profile.service.d.ts +7 -5
  13. package/dist/agents/agent-profile.service.js +14 -9
  14. package/dist/agents/agents.controller.d.ts +7 -287
  15. package/dist/agents/agents.controller.js +7 -67
  16. package/dist/agents/agents.schemas.d.ts +389 -0
  17. package/dist/agents/agents.schemas.js +126 -0
  18. package/dist/agents/agents.service.d.ts +13 -5
  19. package/dist/agents/agents.service.js +67 -13
  20. package/dist/agents/definition.d.ts +47 -19
  21. package/dist/agents/definition.js +119 -38
  22. package/dist/agents/from-template.d.ts +2 -2
  23. package/dist/agents/from-template.js +76 -45
  24. package/dist/agents/from-template.service.d.ts +12 -0
  25. package/dist/agents/from-template.service.js +20 -3
  26. package/dist/agents/models.controller.d.ts +1 -2
  27. package/dist/agents/models.controller.js +1 -1
  28. package/dist/agents/org-templates.d.ts +13 -3
  29. package/dist/agents/org-templates.js +69 -28
  30. package/dist/agents/pending-connector-requests.d.ts +2 -0
  31. package/dist/agents/pending-connector-requests.js +1 -1
  32. package/dist/agents/pending-connectors.controller.d.ts +1 -1
  33. package/dist/agents/pending-connectors.controller.js +2 -2
  34. package/dist/agents/pending-connectors.service.d.ts +2 -2
  35. package/dist/agents/pending-connectors.service.js +19 -19
  36. package/dist/agents/profile.d.ts +18 -0
  37. package/dist/agents/profile.js +5 -1
  38. package/dist/agents/templates.controller.d.ts +8 -17
  39. package/dist/agents/templates.controller.js +13 -31
  40. package/dist/agents/templates.schemas.d.ts +20 -0
  41. package/dist/agents/templates.schemas.js +45 -0
  42. package/dist/background/background.controller.js +3 -2
  43. package/dist/background/background.schemas.d.ts +10 -0
  44. package/dist/background/background.schemas.js +16 -0
  45. package/dist/background/tasks.service.d.ts +1 -1
  46. package/dist/background/tasks.service.js +7 -2
  47. package/dist/catalog/admin-catalog.controller.d.ts +4 -57
  48. package/dist/catalog/admin-catalog.controller.js +8 -45
  49. package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
  50. package/dist/catalog/admin-catalog.schemas.js +92 -0
  51. package/dist/catalog/catalog-content.d.ts +12 -2
  52. package/dist/catalog/catalog-scope.service.js +8 -2
  53. package/dist/catalog/catalog.service.d.ts +2 -0
  54. package/dist/catalog/catalog.service.js +3 -0
  55. package/dist/catalog/component-scope.controller.d.ts +3 -65
  56. package/dist/catalog/component-scope.controller.js +3 -56
  57. package/dist/catalog/component-scope.schemas.d.ts +114 -0
  58. package/dist/catalog/component-scope.schemas.js +97 -0
  59. package/dist/catalog/component-scope.service.d.ts +28 -4
  60. package/dist/catalog/component-scope.service.js +55 -3
  61. package/dist/catalog/component-state.d.ts +9 -2
  62. package/dist/catalog/component-state.js +22 -13
  63. package/dist/catalog/marketplaces.controller.d.ts +5 -35
  64. package/dist/catalog/marketplaces.controller.js +6 -34
  65. package/dist/catalog/marketplaces.schemas.d.ts +48 -0
  66. package/dist/catalog/marketplaces.schemas.js +53 -0
  67. package/dist/catalog/marketplaces.service.d.ts +15 -1
  68. package/dist/catalog/marketplaces.service.js +22 -1
  69. package/dist/catalog/org-catalog.controller.d.ts +6 -62
  70. package/dist/catalog/org-catalog.controller.js +12 -66
  71. package/dist/catalog/org-catalog.schemas.d.ts +79 -0
  72. package/dist/catalog/org-catalog.schemas.js +82 -0
  73. package/dist/catalog/org-catalog.service.d.ts +9 -2
  74. package/dist/catalog/org-catalog.service.js +38 -5
  75. package/dist/catalog/org-extension.controller.d.ts +1 -12
  76. package/dist/catalog/org-extension.controller.js +1 -10
  77. package/dist/catalog/org-extension.schemas.d.ts +15 -0
  78. package/dist/catalog/org-extension.schemas.js +22 -0
  79. package/dist/catalog/org-plugin-uploads.controller.d.ts +2 -19
  80. package/dist/catalog/org-plugin-uploads.controller.js +15 -28
  81. package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
  82. package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
  83. package/dist/catalog/owned-items.d.ts +6 -2
  84. package/dist/catalog/owned-items.js +16 -4
  85. package/dist/catalog/platform-components.d.ts +2 -0
  86. package/dist/catalog/platform-components.js +2 -0
  87. package/dist/catalog/plugin-import.js +1 -0
  88. package/dist/catalog/plugin-install.js +1 -1
  89. package/dist/catalog/requests.service.d.ts +2 -1
  90. package/dist/catalog/requests.service.js +6 -2
  91. package/dist/channels/channels.schemas.d.ts +33 -0
  92. package/dist/channels/channels.schemas.js +34 -0
  93. package/dist/channels/connections.controller.d.ts +2 -29
  94. package/dist/channels/connections.controller.js +1 -23
  95. package/dist/channels/connections.service.d.ts +8 -2
  96. package/dist/channels/connections.service.js +23 -5
  97. package/dist/channels/inbound.js +4 -0
  98. package/dist/conversations/conversations.controller.d.ts +16 -37
  99. package/dist/conversations/conversations.controller.js +16 -56
  100. package/dist/conversations/conversations.schemas.d.ts +52 -0
  101. package/dist/conversations/conversations.schemas.js +79 -0
  102. package/dist/conversations/conversations.service.d.ts +9 -1
  103. package/dist/conversations/conversations.service.js +23 -18
  104. package/dist/conversations/events.d.ts +80 -6
  105. package/dist/conversations/events.js +60 -5
  106. package/dist/conversations/message-context.d.ts +28 -0
  107. package/dist/conversations/message-context.js +56 -0
  108. package/dist/conversations/queue.d.ts +2 -1
  109. package/dist/conversations/queue.js +11 -2
  110. package/dist/db/kernel-schema.d.ts +20 -0
  111. package/dist/environments/environments.schemas.d.ts +3 -0
  112. package/dist/environments/environments.schemas.js +14 -0
  113. package/dist/environments/environments.service.d.ts +16 -4
  114. package/dist/environments/environments.service.js +58 -13
  115. package/dist/errors.d.ts +3 -0
  116. package/dist/errors.js +3 -0
  117. package/dist/evals/evals.schemas.d.ts +110 -0
  118. package/dist/evals/evals.schemas.js +107 -0
  119. package/dist/evals/reconstruct.js +18 -11
  120. package/dist/evals/recorded-tools.d.ts +2 -1
  121. package/dist/evals/recorded-tools.js +11 -3
  122. package/dist/evals/run-replay.d.ts +8 -1
  123. package/dist/evals/run-replay.js +13 -0
  124. package/dist/evals/runs.controller.d.ts +2 -57
  125. package/dist/evals/runs.controller.js +1 -42
  126. package/dist/evals/runs.service.d.ts +6 -6
  127. package/dist/evals/runs.service.js +32 -18
  128. package/dist/evals/sets.controller.d.ts +2 -28
  129. package/dist/evals/sets.controller.js +1 -31
  130. package/dist/evals/sets.service.d.ts +7 -7
  131. package/dist/evals/sets.service.js +23 -17
  132. package/dist/evals/snapshot.d.ts +3 -2
  133. package/dist/evals/snapshot.js +17 -4
  134. package/dist/extensions/admin-ops.d.ts +5 -3
  135. package/dist/extensions/admin-ops.js +17 -12
  136. package/dist/extensions/deployment-config.d.ts +16 -1
  137. package/dist/extensions/deployment-config.js +83 -0
  138. package/dist/extensions/extensions.module.js +3 -0
  139. package/dist/extensions/host.d.ts +33 -2
  140. package/dist/extensions/host.js +107 -1
  141. package/dist/extensions/installs.d.ts +5 -0
  142. package/dist/extensions/installs.js +12 -0
  143. package/dist/extensions/org-config.d.ts +17 -2
  144. package/dist/extensions/org-config.js +23 -4
  145. package/dist/extensions/point-defaults.controller.d.ts +2 -8
  146. package/dist/extensions/point-defaults.controller.js +1 -3
  147. package/dist/extensions/point-defaults.d.ts +3 -1
  148. package/dist/extensions/point-defaults.js +4 -2
  149. package/dist/extensions/point-defaults.schemas.d.ts +9 -0
  150. package/dist/extensions/point-defaults.schemas.js +14 -0
  151. package/dist/extensions/unavailable.d.ts +49 -0
  152. package/dist/extensions/unavailable.js +113 -0
  153. package/dist/files/previewers.controller.js +2 -3
  154. package/dist/files/previewers.d.ts +1 -1
  155. package/dist/files/previewers.js +4 -4
  156. package/dist/files/previewers.schemas.d.ts +10 -0
  157. package/dist/files/previewers.schemas.js +9 -0
  158. package/dist/http/api.module.js +2 -0
  159. package/dist/identity/accounts.d.ts +43 -4
  160. package/dist/identity/accounts.js +74 -6
  161. package/dist/identity/auth.guard.js +10 -1
  162. package/dist/identity/cookies.d.ts +6 -0
  163. package/dist/identity/cookies.js +14 -0
  164. package/dist/identity/identity.module.js +3 -0
  165. package/dist/identity/initial-passwords.controller.d.ts +22 -0
  166. package/dist/identity/initial-passwords.controller.js +49 -0
  167. package/dist/identity/initial-passwords.d.ts +61 -0
  168. package/dist/identity/initial-passwords.job.d.ts +16 -0
  169. package/dist/identity/initial-passwords.job.js +46 -0
  170. package/dist/identity/initial-passwords.js +159 -0
  171. package/dist/identity/me.controller.d.ts +12 -0
  172. package/dist/identity/me.controller.js +31 -1
  173. package/dist/identity/me.schemas.d.ts +14 -0
  174. package/dist/identity/me.schemas.js +17 -0
  175. package/dist/identity/principal.d.ts +8 -0
  176. package/dist/identity/principal.js +8 -0
  177. package/dist/identity/settings.d.ts +3 -1
  178. package/dist/identity/settings.js +6 -4
  179. package/dist/inbox/inbox.schemas.d.ts +8 -0
  180. package/dist/inbox/inbox.schemas.js +11 -0
  181. package/dist/inbox/platform-inbox.controller.d.ts +1 -1
  182. package/dist/inbox/platform-inbox.controller.js +2 -2
  183. package/dist/index.d.ts +4 -0
  184. package/dist/index.js +6 -0
  185. package/dist/lifecycle/kernel-lifecycle.js +4 -0
  186. package/dist/models/enablement.d.ts +2 -0
  187. package/dist/models/enablement.js +1 -0
  188. package/dist/models/org-models.schemas.d.ts +8 -0
  189. package/dist/models/org-models.schemas.js +22 -0
  190. package/dist/models/prices.d.ts +3 -1
  191. package/dist/models/prices.js +7 -5
  192. package/dist/models/purposes.d.ts +12 -2
  193. package/dist/models/purposes.js +22 -8
  194. package/dist/orgs/orgs.controller.d.ts +2 -5
  195. package/dist/orgs/orgs.controller.js +3 -6
  196. package/dist/orgs/orgs.schemas.d.ts +8 -0
  197. package/dist/orgs/orgs.schemas.js +16 -0
  198. package/dist/orgs/orgs.service.d.ts +3 -1
  199. package/dist/orgs/orgs.service.js +6 -4
  200. package/dist/orgs/settings.service.d.ts +9 -1
  201. package/dist/orgs/settings.service.js +20 -5
  202. package/dist/overrides.d.ts +4 -0
  203. package/dist/overrides.js +2 -0
  204. package/dist/platform/errors.d.ts +21 -4
  205. package/dist/platform/errors.js +45 -6
  206. package/dist/platform/exclusions.d.ts +2 -3
  207. package/dist/platform/exclusions.js +58 -849
  208. package/dist/platform/method.js +1 -1
  209. package/dist/platform/operation.d.ts +82 -5
  210. package/dist/platform/operation.js +63 -8
  211. package/dist/platform/ops/accounts.ops.d.ts +32 -0
  212. package/dist/platform/ops/accounts.ops.js +291 -0
  213. package/dist/platform/ops/admin.ops.d.ts +36 -0
  214. package/dist/platform/ops/admin.ops.js +389 -0
  215. package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
  216. package/dist/platform/ops/agent-skills.ops.js +226 -0
  217. package/dist/platform/ops/agent-templates.ops.d.ts +4 -1
  218. package/dist/platform/ops/agent-templates.ops.js +194 -14
  219. package/dist/platform/ops/agents.ops.d.ts +19 -1
  220. package/dist/platform/ops/agents.ops.js +481 -58
  221. package/dist/platform/ops/approvals.ops.d.ts +30 -0
  222. package/dist/platform/ops/approvals.ops.js +116 -0
  223. package/dist/platform/ops/background.ops.d.ts +14 -0
  224. package/dist/platform/ops/background.ops.js +134 -0
  225. package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
  226. package/dist/platform/ops/catalog-admin.ops.js +587 -0
  227. package/dist/platform/ops/channels.ops.d.ts +16 -0
  228. package/dist/platform/ops/channels.ops.js +195 -0
  229. package/dist/platform/ops/components.ops.d.ts +46 -0
  230. package/dist/platform/ops/components.ops.js +853 -0
  231. package/dist/platform/ops/connectors.ops.d.ts +4 -2
  232. package/dist/platform/ops/connectors.ops.js +68 -6
  233. package/dist/platform/ops/conversations.ops.d.ts +30 -0
  234. package/dist/platform/ops/conversations.ops.js +470 -0
  235. package/dist/platform/ops/environments.ops.d.ts +26 -0
  236. package/dist/platform/ops/environments.ops.js +289 -0
  237. package/dist/platform/ops/errors.d.ts +10 -5
  238. package/dist/platform/ops/errors.js +19 -11
  239. package/dist/platform/ops/evals.ops.d.ts +28 -0
  240. package/dist/platform/ops/evals.ops.js +783 -0
  241. package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
  242. package/dist/platform/ops/extensions-admin.ops.js +344 -0
  243. package/dist/platform/ops/extensions.ops.d.ts +7 -1
  244. package/dist/platform/ops/extensions.ops.js +248 -17
  245. package/dist/platform/ops/inbox.ops.d.ts +25 -0
  246. package/dist/platform/ops/inbox.ops.js +378 -0
  247. package/dist/platform/ops/marketplaces.ops.d.ts +7 -1
  248. package/dist/platform/ops/marketplaces.ops.js +326 -17
  249. package/dist/platform/ops/models.ops.d.ts +25 -0
  250. package/dist/platform/ops/models.ops.js +232 -0
  251. package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
  252. package/dist/platform/ops/org-plugins.ops.js +329 -0
  253. package/dist/platform/ops/org-settings.ops.d.ts +16 -0
  254. package/dist/platform/ops/org-settings.ops.js +102 -0
  255. package/dist/platform/ops/orgs.ops.d.ts +28 -0
  256. package/dist/platform/ops/orgs.ops.js +295 -0
  257. package/dist/platform/ops/other-orgs.d.ts +20 -0
  258. package/dist/platform/ops/other-orgs.js +72 -0
  259. package/dist/platform/ops/platform.ops.d.ts +11 -6
  260. package/dist/platform/ops/platform.ops.js +73 -27
  261. package/dist/platform/ops/plugins.ops.d.ts +10 -8
  262. package/dist/platform/ops/plugins.ops.js +176 -77
  263. package/dist/platform/ops/previewers.ops.d.ts +14 -0
  264. package/dist/platform/ops/previewers.ops.js +109 -0
  265. package/dist/platform/ops/requests.ops.js +57 -19
  266. package/dist/platform/ops/skills.ops.d.ts +5 -1
  267. package/dist/platform/ops/skills.ops.js +129 -11
  268. package/dist/platform/ops/unavailable.d.ts +23 -0
  269. package/dist/platform/ops/unavailable.js +111 -0
  270. package/dist/platform/parity.d.ts +33 -0
  271. package/dist/platform/parity.js +272 -0
  272. package/dist/platform/platform-ops.module.d.ts +32 -0
  273. package/dist/platform/platform-ops.module.js +78 -11
  274. package/dist/platform/route-schemas.d.ts +18 -0
  275. package/dist/platform/route-schemas.js +63 -0
  276. package/dist/roles/worker.module.js +2 -0
  277. package/dist/runtime/context/build.d.ts +2 -0
  278. package/dist/runtime/context/build.js +28 -2
  279. package/dist/runtime/context/compaction.js +10 -1
  280. package/dist/runtime/context/run-context.d.ts +65 -0
  281. package/dist/runtime/context/run-context.js +215 -0
  282. package/dist/runtime/model-call.js +2 -1
  283. package/dist/runtime/providers.js +8 -1
  284. package/dist/runtime/run-context.service.d.ts +65 -0
  285. package/dist/runtime/run-context.service.js +220 -0
  286. package/dist/runtime/run-worker.d.ts +5 -0
  287. package/dist/runtime/run-worker.js +31 -6
  288. package/dist/runtime/runtime.module.js +2 -0
  289. package/dist/runtime/subagents/definition.d.ts +15 -15
  290. package/dist/runtime/subagents/definition.js +46 -115
  291. package/dist/skills/changes.controller.js +2 -1
  292. package/dist/skills/changes.service.d.ts +1 -1
  293. package/dist/skills/changes.service.js +4 -4
  294. package/dist/skills/invocable.controller.d.ts +1 -1
  295. package/dist/skills/invocable.controller.js +2 -2
  296. package/dist/skills/invoke.d.ts +2 -2
  297. package/dist/skills/invoke.js +8 -1
  298. package/dist/skills/skills.controller.d.ts +4 -13
  299. package/dist/skills/skills.controller.js +8 -24
  300. package/dist/skills/skills.schemas.d.ts +48 -0
  301. package/dist/skills/skills.schemas.js +61 -0
  302. package/dist/skills/skills.service.d.ts +11 -1
  303. package/dist/skills/skills.service.js +37 -14
  304. package/dist/time-zone.d.ts +5 -0
  305. package/dist/time-zone.js +19 -0
  306. package/dist/tools/approvals.controller.js +2 -3
  307. package/dist/tools/approvals.schemas.d.ts +21 -0
  308. package/dist/tools/approvals.schemas.js +15 -0
  309. package/dist/tools/builtin-names.d.ts +10 -8
  310. package/dist/tools/builtin-names.js +16 -11
  311. package/dist/tools/builtins/builtin-tools.d.ts +3 -1
  312. package/dist/tools/builtins/builtin-tools.js +15 -3
  313. package/dist/tools/builtins/current-time.d.ts +26 -0
  314. package/dist/tools/builtins/current-time.js +99 -0
  315. package/dist/tools/builtins/platform.d.ts +19 -2
  316. package/dist/tools/builtins/platform.js +105 -16
  317. package/dist/tools/connectors.controller.d.ts +1 -2
  318. package/dist/tools/connectors.controller.js +1 -4
  319. package/dist/tools/connectors.schemas.d.ts +12 -0
  320. package/dist/tools/connectors.schemas.js +19 -0
  321. package/dist/tools/connectors.service.d.ts +5 -2
  322. package/dist/tools/connectors.service.js +7 -5
  323. package/dist/tools/org-tool-switches.d.ts +16 -2
  324. package/dist/tools/org-tool-switches.js +26 -9
  325. package/dist/tools/pipeline.js +3 -1
  326. package/dist/tools/registry.d.ts +48 -51
  327. package/dist/tools/registry.js +222 -233
  328. package/package.json +3 -3
  329. package/src/migrations/0090_initial_passwords.sql +27 -0
  330. package/src/migrations/0091_account_time_zone.sql +4 -0
  331. package/src/migrations/0092_tools_default_on.sql +27 -0
  332. package/dist/platform/redact-orgs.d.ts +0 -7
  333. package/dist/platform/redact-orgs.js +0 -52
@@ -1,6 +1,8 @@
1
+ import type { KernelLogger } from "../../log.js";
1
2
  import type { OrgSettings } from "../../orgs/settings.service.js";
2
3
  import type { ActorFacts } from "../../platform/actor.js";
3
4
  import type { AgentDocTopic } from "../../platform/agent-docs.js";
5
+ import { type PlatformOperation } from "../../platform/operation.js";
4
6
  import type { PlatformOperations } from "../../platform/registry.js";
5
7
  import type { BuiltinTool, CallPolicyContext } from "../registry.js";
6
8
  /**
@@ -9,8 +11,12 @@ import type { BuiltinTool, CallPolicyContext } from "../registry.js";
9
11
  * - `browse` / `search` / `describe` / `read` only read; their policy is the tool's `allow`.
10
12
  * - `call` gets a per-call policy key `Platform:<operation>` ({@link BuiltinTool.callPolicy}): a
11
13
  * read runs, a write asks (remembered only for `personal`), an operation that cannot run now is
12
- * denied with its reason. Right before `op.run` the availability is checked again on fresh facts
13
- * (the actor may have lost the role while the confirmation waited).
14
+ * denied with its reason, and so is a write whose `precheck` knows it would fail (spec §14.2
15
+ * item 2: no card). The policy is derived again when an approved call resumes, so a precheck
16
+ * that fails by then returns its error and nothing runs. Right before `op.run` the availability
17
+ * is checked again on fresh facts (the actor may have lost the role while the confirmation
18
+ * waited).
19
+ * - An `ApiError` gets the next step the operation declares for its code and the actor's role.
14
20
  * - The actor, the agent and the conversation come from the runtime context, never from input.
15
21
  * - Results are JSON text; a list an operation returns is capped at {@link LIST_MAX} entries.
16
22
  */
@@ -30,5 +36,16 @@ export interface PlatformToolDeps {
30
36
  };
31
37
  /** The org setting `platformTool`. */
32
38
  setting(orgId: string): Promise<OrgSettings["platformTool"]>;
39
+ /** How long a precheck may take; default {@link PRECHECK_TIMEOUT_MS} (a test seam). */
40
+ precheckTimeoutMs?: number;
41
+ /** A precheck that throws is logged (warn) and one that times out (debug), with the op id. */
42
+ log?: Pick<KernelLogger, "warn"> & Partial<Pick<KernelLogger, "debug">>;
33
43
  }
44
+ /**
45
+ * An operation's input keys as `browse` and `search` show them, so a call needs no guess:
46
+ * `"itemId"`, `"agentId, updatedAt, avatar?, quickActions?"` (`?` = optional), `""` when it takes
47
+ * none. A union input lists the keys of every branch; a key is required when every branch requires
48
+ * it. Types, bounds and an example stay in `describe`.
49
+ */
50
+ export declare function paramsLine(op: PlatformOperation): string;
34
51
  export declare function platformTool(deps: PlatformToolDeps): BuiltinTool;
@@ -1,9 +1,9 @@
1
1
  import { ToolError } from "@capybara-hq/plugin-sdk";
2
2
  import { z } from "zod";
3
3
  import { availability } from "../../platform/availability.js";
4
- import { toToolError } from "../../platform/errors.js";
4
+ import { errorRoleOf, errorsFor, nextStepFor, OPERATION_ERROR_NEXT, resolveNext, sentence, toToolError, } from "../../platform/errors.js";
5
5
  import { PLATFORM_METHOD } from "../../platform/method.js";
6
- import { OPERATION_ID, operationDomain, } from "../../platform/operation.js";
6
+ import { OPERATION_ID, operationDomain, PRECHECK_TIMEOUT_MS, } from "../../platform/operation.js";
7
7
  import { BUILTIN } from "../builtin-names.js";
8
8
  /**
9
9
  * The `Platform` builtin (Platform tool spec §3–§6): one tool through which an agent discovers and
@@ -11,8 +11,12 @@ import { BUILTIN } from "../builtin-names.js";
11
11
  * - `browse` / `search` / `describe` / `read` only read; their policy is the tool's `allow`.
12
12
  * - `call` gets a per-call policy key `Platform:<operation>` ({@link BuiltinTool.callPolicy}): a
13
13
  * read runs, a write asks (remembered only for `personal`), an operation that cannot run now is
14
- * denied with its reason. Right before `op.run` the availability is checked again on fresh facts
15
- * (the actor may have lost the role while the confirmation waited).
14
+ * denied with its reason, and so is a write whose `precheck` knows it would fail (spec §14.2
15
+ * item 2: no card). The policy is derived again when an approved call resumes, so a precheck
16
+ * that fails by then returns its error and nothing runs. Right before `op.run` the availability
17
+ * is checked again on fresh facts (the actor may have lost the role while the confirmation
18
+ * waited).
19
+ * - An `ApiError` gets the next step the operation declares for its code and the actor's role.
16
20
  * - The actor, the agent and the conversation come from the runtime context, never from input.
17
21
  * - Results are JSON text; a list an operation returns is capped at {@link LIST_MAX} entries.
18
22
  */
@@ -25,11 +29,13 @@ export const PLATFORM_UNAVAILABLE_OFF = "The org turned the Platform tool off; a
25
29
  const ACTIONS = ["browse", "search", "describe", "call", "read"];
26
30
  const SPEC = {
27
31
  name: BUILTIN.Platform,
28
- description: "Discover and use the platform's own operations (skills, agents, templates, plugins, " +
29
- "marketplaces, requests, connectors, extensions) and its documentation, as the person you are " +
30
- 'working for. Start with action "browse", then "describe" an operation before you "call" it; ' +
31
- 'never guess parameters. Writes ask the person to confirm. Use "read" for how-to documentation ' +
32
- "(plugin format, skills, extension points).",
32
+ description: "Discover and use the platform's own operations (agents, skills, templates, plugins, " +
33
+ "connectors, extensions, conversations, environments, models, evals, channels, requests, " +
34
+ "approvals and the inbox, org settings, and for admins accounts, orgs and the admin console) " +
35
+ 'and its documentation, as the person you are working for. Start with action "browse", which ' +
36
+ 'lists every domain, then "describe" an operation before you "call" it; never guess ' +
37
+ 'parameters. Writes ask the person to confirm. Use "read" for how-to documentation (plugin ' +
38
+ "format, skills, extension points).",
33
39
  inputSchema: {
34
40
  type: "object",
35
41
  properties: {
@@ -86,11 +92,43 @@ const firstSentence = (text) => {
86
92
  };
87
93
  const kindOf = (op) => op.confirm === "read" ? "read" : "write";
88
94
  const availabilityFields = (a) => a.ok ? { available: true } : { available: false, reason: a.reason };
95
+ /** The most input keys a `params` line names before it ends in `…`. */
96
+ const PARAMS_MAX = 8;
97
+ const paramsCache = new WeakMap();
98
+ /**
99
+ * An operation's input keys as `browse` and `search` show them, so a call needs no guess:
100
+ * `"itemId"`, `"agentId, updatedAt, avatar?, quickActions?"` (`?` = optional), `""` when it takes
101
+ * none. A union input lists the keys of every branch; a key is required when every branch requires
102
+ * it. Types, bounds and an example stay in `describe`.
103
+ */
104
+ export function paramsLine(op) {
105
+ const cached = paramsCache.get(op);
106
+ if (cached !== undefined)
107
+ return cached;
108
+ const schema = z.toJSONSchema(op.input, {
109
+ io: "input",
110
+ unrepresentable: "any",
111
+ });
112
+ const branches = schema.anyOf ?? schema.oneOf ?? [schema];
113
+ const keys = [];
114
+ for (const b of branches) {
115
+ for (const k of Object.keys(b.properties ?? {}))
116
+ if (!keys.includes(k))
117
+ keys.push(k);
118
+ }
119
+ const required = (k) => branches.every((b) => b.required?.includes(k) ?? false);
120
+ const ordered = [...keys.filter(required), ...keys.filter((k) => !required(k))];
121
+ const names = ordered.map((k) => (required(k) ? k : `${k}?`));
122
+ const text = names.length > PARAMS_MAX ? `${names.slice(0, PARAMS_MAX).join(", ")}, …` : names.join(", ");
123
+ paramsCache.set(op, text);
124
+ return text;
125
+ }
89
126
  /** One operation as `browse` and `search` list it. */
90
127
  const line = (op, facts) => ({
91
128
  id: op.id,
92
129
  description: firstSentence(op.description),
93
130
  kind: kindOf(op),
131
+ params: paramsLine(op),
94
132
  ...availabilityFields(availability(op, facts)),
95
133
  });
96
134
  const capped = (items) => ({
@@ -115,6 +153,7 @@ const unknownOperationText = (id) => `Unknown operation "${id}". Use browse or s
115
153
  const missingText = (action, field, what) => `Action ${action} needs "${field}": pass ${what}.`;
116
154
  const invalidParamsText = (id, problems) => `Invalid params for ${id}: ${problems}. Call describe with operation "${id}" for its input schema and an example, then call again.`;
117
155
  const unavailableOpText = (id, reason) => `Operation ${id} is unavailable, so do not call it again as is: ${reason}`;
156
+ const precheckText = (id, code, message, next) => `Operation ${id} cannot run now: ${code}: ${sentence(message)} ${next ?? OPERATION_ERROR_NEXT}`;
118
157
  const outputRefText = (id) => `Operation ${id} writes, and its params hold a {"$output": ...} reference, which the person confirming would see instead of the content. Pass the content inline in params and call again.`;
119
158
  /** Whether a value holds a `{"$output": …}` reference anywhere (the pipeline's form). */
120
159
  function hasOutputRef(v) {
@@ -157,13 +196,14 @@ function paramsOf(op, params) {
157
196
  * The operation context of a confirmation (`confirmFor`, `summary`): the runtime's ids, never
158
197
  * input. Nothing aborts it; it only reads.
159
198
  */
160
- const confirmCtx = (ctx) => ({
199
+ const confirmCtx = (ctx, errorRole) => ({
161
200
  orgId: ctx.orgId,
162
201
  actorAccountId: ctx.accountId,
163
202
  agentId: ctx.agentId,
164
203
  conversationId: ctx.conversationId,
165
204
  runId: ctx.runId,
166
205
  signal: new AbortController().signal,
206
+ errorRole,
167
207
  });
168
208
  const factsCtx = (ctx) => ({
169
209
  orgId: ctx.orgId,
@@ -198,7 +238,8 @@ export function platformTool(deps) {
198
238
  return deny(e.message);
199
239
  throw e;
200
240
  }
201
- const verdict = availability(op, await facts(ctx));
241
+ const f = await facts(ctx);
242
+ const verdict = availability(op, f);
202
243
  if (!verdict.ok)
203
244
  return deny(unavailableOpText(op.id, verdict.reason));
204
245
  if (op.confirm === "read")
@@ -207,7 +248,13 @@ export function platformTool(deps) {
207
248
  if (hasOutputRef(ctx.rawInput?.params)) {
208
249
  return deny(outputRefText(op.id));
209
250
  }
210
- const octx = confirmCtx(ctx);
251
+ const role = errorRoleOf(f);
252
+ const failed = await precheckOf(op, params, ctx, role, deps.precheckTimeoutMs ?? PRECHECK_TIMEOUT_MS, deps.log);
253
+ if (failed !== null) {
254
+ const next = resolveNext(failed.next, role) ?? nextStepFor(op.errors, failed.code, role);
255
+ return deny(precheckText(op.id, failed.code, failed.message, next));
256
+ }
257
+ const octx = confirmCtx(ctx, role);
211
258
  const [cls, summary] = await Promise.all([
212
259
  classOf(op, params, octx),
213
260
  summaryOf(op, params, octx),
@@ -216,7 +263,7 @@ export function platformTool(deps) {
216
263
  key,
217
264
  policy: "ask",
218
265
  // org / platform writes are confirmed every time (spec §6.2)
219
- remember: cls === "personal",
266
+ remember: cls === "personal" && op.rememberable !== false,
220
267
  summary,
221
268
  };
222
269
  }
@@ -280,7 +327,8 @@ export function platformTool(deps) {
280
327
  confirm: op.confirm,
281
328
  inputSchema: z.toJSONSchema(op.input, { io: "input", unrepresentable: "any" }),
282
329
  example: op.example,
283
- ...(op.errors !== undefined && op.errors.length > 0 && { errors: op.errors }),
330
+ ...(op.errors !== undefined &&
331
+ op.errors.length > 0 && { errors: errorsFor(op.errors, errorRoleOf(f)) }),
284
332
  ...availabilityFields(availability(op, f)),
285
333
  related: deps.ops
286
334
  .inDomain(operationDomain(op.id))
@@ -292,9 +340,11 @@ export function platformTool(deps) {
292
340
  const op = operationOf(deps, "call", input.operation);
293
341
  const params = paramsOf(op, input.params);
294
342
  // fresh facts right before running: the role may be gone since the confirmation (Review Focus 3)
295
- const verdict = availability(op, await facts(factsCtx(ctx)));
343
+ const f = await facts(factsCtx(ctx));
344
+ const verdict = availability(op, f);
296
345
  if (!verdict.ok)
297
346
  throw new ToolError(unavailableOpText(op.id, verdict.reason));
347
+ const role = errorRoleOf(f);
298
348
  let result;
299
349
  try {
300
350
  result = await op.run(params, {
@@ -303,11 +353,15 @@ export function platformTool(deps) {
303
353
  agentId: ctx.agentId,
304
354
  conversationId: ctx.conversationId,
305
355
  runId: ctx.runId ?? null,
356
+ callId: ctx.callId,
306
357
  signal: ctx.signal,
358
+ errorRole: role,
307
359
  });
308
360
  }
309
361
  catch (e) {
310
- throw toToolError(e);
362
+ // a service refusal after the approval (a race the precheck could not see) still names the
363
+ // next step for this actor (Review Focus 2)
364
+ throw toToolError(e, (code) => nextStepFor(op.errors, code, role));
311
365
  }
312
366
  return json(asResult(result), { zh: `调用平台操作 ${op.id}`, en: `Called ${op.id}` });
313
367
  }
@@ -348,6 +402,41 @@ async function classOf(op, params, ctx) {
348
402
  return "org";
349
403
  }
350
404
  }
405
+ /**
406
+ * The operation's precheck, bounded by `ms`: the failure it found, or null (none, passed, timed
407
+ * out, or threw: the write's own errors speak then; a throw is logged as a warning, a timeout at
408
+ * debug). Its signal aborts at the timeout or when the run's signal aborts.
409
+ */
410
+ async function precheckOf(op, params, ctx, role, ms, log) {
411
+ if (op.precheck === undefined)
412
+ return null;
413
+ const ac = new AbortController();
414
+ const signal = ctx.signal === undefined ? ac.signal : AbortSignal.any([ac.signal, ctx.signal]);
415
+ let timer;
416
+ const timeout = new Promise((resolve) => {
417
+ timer = setTimeout(() => {
418
+ ac.abort();
419
+ log?.debug?.("platform precheck timed out; the card is shown", { operation: op.id, ms });
420
+ resolve(null);
421
+ }, ms);
422
+ });
423
+ try {
424
+ const r = await Promise.race([
425
+ op.precheck(params, { ...confirmCtx(ctx, role), signal }),
426
+ timeout,
427
+ ]);
428
+ if (r === null || r.ok)
429
+ return null;
430
+ return { code: r.code, message: r.message, ...(r.next !== undefined && { next: r.next }) };
431
+ }
432
+ catch (err) {
433
+ log?.warn("platform precheck failed; the card is shown", { operation: op.id, err });
434
+ return null;
435
+ }
436
+ finally {
437
+ clearTimeout(timer);
438
+ }
439
+ }
351
440
  /** The card summary of a write, rendered from the validated params and kernel reads. */
352
441
  async function summaryOf(op, params, ctx) {
353
442
  try {
@@ -1,9 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { type Principal } from "../identity/principal.js";
3
3
  import { type OrgContext } from "../orgs/org.guard.js";
4
+ import { CredentialValue } from "./connectors.schemas.js";
4
5
  import { type ConnectorDetail, type ConnectorPreview, type ConnectorSummary, ConnectorsService, type ToolIssue } from "./connectors.service.js";
5
- /** 凭据值:形状由 `Credentials.validate` 按认证方式校验(不回显值);这里只限大小。 */
6
- export declare const CredentialValue: z.ZodRecord<z.ZodString, z.ZodUnknown>;
7
6
  declare const CreateBody: z.ZodObject<{
8
7
  name: z.ZodString;
9
8
  slug: z.ZodOptional<z.ZodString>;
@@ -15,6 +15,7 @@ import { createZodDto } from "../infra/validation/create-zod-dto.js";
15
15
  import { ZBody } from "../infra/validation/zod-params.js";
16
16
  import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
17
17
  import { can } from "../orgs/roles.js";
18
+ import { CredentialValue } from "./connectors.schemas.js";
18
19
  import { ConnectorsService, } from "./connectors.service.js";
19
20
  import { publicEndpoint } from "./endpoint.js";
20
21
  /**
@@ -34,10 +35,6 @@ function forViewer(org, c) {
34
35
  }
35
36
  return view;
36
37
  }
37
- /** 凭据值:形状由 `Credentials.validate` 按认证方式校验(不回显值);这里只限大小。 */
38
- export const CredentialValue = z
39
- .record(z.string().max(100), z.unknown())
40
- .refine((v) => JSON.stringify(v).length <= 16_384, { message: "Credential is too large" });
41
38
  const CreateBody = z
42
39
  .object({
43
40
  name: z.string().trim().min(1).max(80),
@@ -0,0 +1,12 @@
1
+ import { z } from "zod";
2
+ import type { RouteSchemas } from "../platform/route-schemas.js";
3
+ /**
4
+ * A credential value: `Credentials.validate` checks its shape by auth method (values are never
5
+ * echoed); this only bounds its size.
6
+ */
7
+ export declare const CredentialValue: z.ZodRecord<z.ZodString, z.ZodUnknown>;
8
+ /** `:connectorId` as the routes take it (`@Param`). */
9
+ export declare const ConnectorPathParams: z.ZodObject<{
10
+ connectorId: z.ZodString;
11
+ }, z.core.$strip>;
12
+ export declare const CONNECTOR_ROUTES: readonly RouteSchemas[];
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * A credential value: `Credentials.validate` checks its shape by auth method (values are never
4
+ * echoed); this only bounds its size.
5
+ */
6
+ export const CredentialValue = z
7
+ .record(z.string().max(100), z.unknown())
8
+ .refine((v) => JSON.stringify(v).length <= 16_384, { message: "Credential is too large" });
9
+ /** `:connectorId` as the routes take it (`@Param`). */
10
+ export const ConnectorPathParams = z.object({ connectorId: z.string().min(1) });
11
+ export const CONNECTOR_ROUTES = [
12
+ { route: "GET /api/v1/orgs/:orgId/connectors" },
13
+ { route: "GET /api/v1/orgs/:orgId/connectors/:connectorId", params: ConnectorPathParams },
14
+ { route: "DELETE /api/v1/orgs/:orgId/connectors/:connectorId", params: ConnectorPathParams },
15
+ {
16
+ route: "POST /api/v1/orgs/:orgId/connectors/:connectorId/refresh",
17
+ params: ConnectorPathParams,
18
+ },
19
+ ];
@@ -309,14 +309,16 @@ export declare class ConnectorsService {
309
309
  /** 改名、启停连接器、工具启停与默认策略、批量把无注解工具改为 allow(`connectors.manage`)。 */
310
310
  update(orgId: string, connectorId: string, actorAccountId: string, patch: UpdateConnectorInput, actorTokenId?: string): Promise<ConnectorDetail>;
311
311
  /** 软删除,并删除该连接器的全部凭据(`connectors.manage`)。 */
312
- remove(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string): Promise<void>;
312
+ remove(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<void>;
313
313
  /**
314
314
  * 在调用方事务里软删除连接器(调用方已锁组织行并按需复核角色;应用安装的回滚与卸载用):删全部凭据与授权,
315
315
  * 审计 `connector.deleted`(`reason` 并进 detail)。已删除 / 不存在 → `connector.not_found`。
316
316
  */
317
317
  removeIn(orgId: string, connectorId: string,
318
318
  /** null: the kernel itself (the plugin scope sync uninstalling a plugin). */
319
- actorAccountId: string | null, actorTokenId?: string, reason?: string): Promise<void>;
319
+ actorAccountId: string | null, actorTokenId?: string, reason?: string,
320
+ /** Merged into the audit detail (a write made through the Platform tool). */
321
+ auditDetail?: Record<string, unknown>): Promise<void>;
320
322
  /**
321
323
  * 重新 listTools 并按漂移检测的规则比对写入(见 drift.ts):新增 / 定义变化的工具待复核(旧定义保留供对比),
322
324
  * 消失的工具停用;连接器从未拍过快照时首个快照直接启用。
@@ -326,6 +328,7 @@ export declare class ConnectorsService {
326
328
  */
327
329
  refresh(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string, opts?: {
328
330
  trigger?: "first_connect";
331
+ auditDetail?: Record<string, unknown>;
329
332
  }): Promise<{
330
333
  connector: ConnectorDetail;
331
334
  issues: ToolIssue[];
@@ -960,9 +960,9 @@ let ConnectorsService = class ConnectorsService {
960
960
  return this.detail(t, orgId, connectorId, actorAccountId);
961
961
  }
962
962
  /** 软删除,并删除该连接器的全部凭据(`connectors.manage`)。 */
963
- async remove(orgId, connectorId, actorAccountId, actorTokenId) {
963
+ async remove(orgId, connectorId, actorAccountId, actorTokenId, auditDetail) {
964
964
  await this.orgLock.lockAndAuthorize(orgId, actorAccountId, "connectors.manage");
965
- await this.removeIn(orgId, connectorId, actorAccountId, actorTokenId);
965
+ await this.removeIn(orgId, connectorId, actorAccountId, actorTokenId, undefined, auditDetail);
966
966
  }
967
967
  /**
968
968
  * 在调用方事务里软删除连接器(调用方已锁组织行并按需复核角色;应用安装的回滚与卸载用):删全部凭据与授权,
@@ -970,7 +970,9 @@ let ConnectorsService = class ConnectorsService {
970
970
  */
971
971
  async removeIn(orgId, connectorId,
972
972
  /** null: the kernel itself (the plugin scope sync uninstalling a plugin). */
973
- actorAccountId, actorTokenId, reason) {
973
+ actorAccountId, actorTokenId, reason,
974
+ /** Merged into the audit detail (a write made through the Platform tool). */
975
+ auditDetail) {
974
976
  const t = this.db;
975
977
  const app = await this.row(t, orgId, connectorId, true);
976
978
  await t
@@ -991,7 +993,7 @@ let ConnectorsService = class ConnectorsService {
991
993
  orgId,
992
994
  action: "connector.deleted",
993
995
  target: connectorId,
994
- detail: { slug: app.slug, ...(reason !== undefined && { reason }) },
996
+ detail: { slug: app.slug, ...(reason !== undefined && { reason }), ...auditDetail },
995
997
  });
996
998
  }
997
999
  /**
@@ -1033,7 +1035,7 @@ let ConnectorsService = class ConnectorsService {
1033
1035
  orgId,
1034
1036
  action: "connector.tools_refreshed",
1035
1037
  target: connectorId,
1036
- detail: { ...changes, ...(opts.trigger && { trigger: opts.trigger }) },
1038
+ detail: { ...changes, ...(opts.trigger && { trigger: opts.trigger }), ...opts.auditDetail },
1037
1039
  });
1038
1040
  return {
1039
1041
  connector: await this.detail(t, orgId, connectorId, actorAccountId),
@@ -54,13 +54,22 @@ export declare class OrgToolSwitches {
54
54
  private offRows;
55
55
  /** Every tool the extension registers on this replica with its switch (default on). */
56
56
  list(orgId: string, plugin: string): Promise<OrgToolSwitch[]>;
57
+ /**
58
+ * What turning one tool off would affect (nothing written): the agents selecting it and the
59
+ * confirm hash {@link set} takes, or null when it is off already. Unknown tool -> 404
60
+ * `extension.tool_not_found`.
61
+ */
62
+ previewOff(orgId: string, plugin: string, tool: string): Promise<{
63
+ affectedAgents: AffectedAgent[];
64
+ confirm: string;
65
+ } | null>;
57
66
  /** The model-visible keys (`plugin__<extension>__<tool>`) of the tools turned off in the org. */
58
67
  offKeys(orgId: string): Promise<Set<string>>;
59
68
  /** Whether the org turned off this tool. */
60
69
  isToolOff(orgId: string, plugin: string, tool: string): Promise<boolean>;
61
70
  /**
62
71
  * Switches one tool in the org. On applies at once. Off, while the tool is on: without
63
- * `confirm` the preview (the org's agents whose current version selects the tool) and its hash,
72
+ * `confirm` the preview (the org's agents whose current version does not turn it off) and its hash,
64
73
  * with the current hash the switch is written (a changed preview -> 409 `plugin.switch_stale`).
65
74
  * A tool the extension does not register -> 404 `extension.tool_not_found`. A change writes the
66
75
  * audit row `extension.tool_switched`.
@@ -68,7 +77,12 @@ export declare class OrgToolSwitches {
68
77
  set(orgId: string, plugin: string, tool: string, enabled: boolean, actor: {
69
78
  accountId: string;
70
79
  tokenId?: string | undefined;
80
+ /** Merged into the audit detail (a write made through the Platform tool). */
81
+ auditDetail?: Record<string, unknown>;
71
82
  }, confirm?: string): Promise<OrgToolSwitchResult>;
72
- /** The org's live agents whose current version selects `{kind:"plugin", plugin, name: tool}`. */
83
+ /**
84
+ * The org's live agents whose current version has extension tool `tool` of `plugin` on: tools
85
+ * are on by default (tools default-on spec §4), so every agent that does not turn it off.
86
+ */
73
87
  private agentsSelecting;
74
88
  }
@@ -11,6 +11,7 @@ import { createHash } from "node:crypto";
11
11
  import { extensionToolKey } from "@capybara-hq/plugin-sdk";
12
12
  import { Inject, Injectable } from "@nestjs/common";
13
13
  import { sql } from "kysely";
14
+ import { extensionToolDisabled } from "../agents/definition.js";
14
15
  import { ApiError } from "../errors.js";
15
16
  import { ExtensionHost } from "../extensions/host.js";
16
17
  import { extensionVisibleTo } from "../extensions/org-config.js";
@@ -88,6 +89,21 @@ let OrgToolSwitches = class OrgToolSwitches {
88
89
  const off = new Set((await this.offRows(orgId, plugin)).map((r) => r.tool));
89
90
  return tools.map((tool) => ({ tool, enabled: !off.has(tool) }));
90
91
  }
92
+ /**
93
+ * What turning one tool off would affect (nothing written): the agents selecting it and the
94
+ * confirm hash {@link set} takes, or null when it is off already. Unknown tool -> 404
95
+ * `extension.tool_not_found`.
96
+ */
97
+ async previewOff(orgId, plugin, tool) {
98
+ const tools = await this.toolsFor(orgId, plugin);
99
+ if (!tools.includes(tool)) {
100
+ throw new ApiError("extension.tool_not_found", `Extension ${plugin} does not register a tool named ${tool}`);
101
+ }
102
+ if (await this.isToolOff(orgId, plugin, tool))
103
+ return null;
104
+ const affectedAgents = await this.agentsSelecting(orgId, plugin, tool);
105
+ return { affectedAgents, confirm: switchOffHash(orgId, plugin, tool, affectedAgents) };
106
+ }
91
107
  /** The model-visible keys (`plugin__<extension>__<tool>`) of the tools turned off in the org. */
92
108
  async offKeys(orgId) {
93
109
  return new Set((await this.offRows(orgId)).map((r) => extensionToolKey(r.plugin, r.tool)));
@@ -105,7 +121,7 @@ let OrgToolSwitches = class OrgToolSwitches {
105
121
  }
106
122
  /**
107
123
  * Switches one tool in the org. On applies at once. Off, while the tool is on: without
108
- * `confirm` the preview (the org's agents whose current version selects the tool) and its hash,
124
+ * `confirm` the preview (the org's agents whose current version does not turn it off) and its hash,
109
125
  * with the current hash the switch is written (a changed preview -> 409 `plugin.switch_stale`).
110
126
  * A tool the extension does not register -> 404 `extension.tool_not_found`. A change writes the
111
127
  * audit row `extension.tool_switched`.
@@ -143,11 +159,14 @@ let OrgToolSwitches = class OrgToolSwitches {
143
159
  orgId,
144
160
  action: "extension.tool_switched",
145
161
  target: extensionToolKey(plugin, tool),
146
- detail: { plugin, tool, from, to: enabled },
162
+ detail: { plugin, tool, from, to: enabled, ...actor.auditDetail },
147
163
  });
148
164
  return { applied: true };
149
165
  }
150
- /** The org's live agents whose current version selects `{kind:"plugin", plugin, name: tool}`. */
166
+ /**
167
+ * The org's live agents whose current version has extension tool `tool` of `plugin` on: tools
168
+ * are on by default (tools default-on spec §4), so every agent that does not turn it off.
169
+ */
151
170
  async agentsSelecting(orgId, plugin, tool) {
152
171
  const rows = await this.db
153
172
  .selectFrom("agents as a")
@@ -160,12 +179,10 @@ let OrgToolSwitches = class OrgToolSwitches {
160
179
  const out = [];
161
180
  for (const r of rows) {
162
181
  const def = r.definition;
163
- const refs = Array.isArray(def?.tools) ? def.tools : [];
164
- const selects = refs.some((x) => {
165
- const ref = x;
166
- return ref?.kind === "plugin" && ref.plugin === plugin && ref.name === tool;
167
- });
168
- if (selects)
182
+ const off = Array.isArray(def?.disabledTools)
183
+ ? extensionToolDisabled(def.disabledTools, plugin, tool)
184
+ : false;
185
+ if (!off)
169
186
  out.push({ id: r.id, name: typeof def?.name === "string" ? def.name : r.id });
170
187
  }
171
188
  return out;
@@ -243,7 +243,8 @@ let ToolPipeline = class ToolPipeline {
243
243
  // skill invocation in the log → Skill is offered (see skillLoadOffered)
244
244
  const skillLoad = await skillLoadOfferedIn(this.deps.db, this.deps.eventLog, ctx.conversationId);
245
245
  resolved = await this.deps.registry.forAgent(ctx.orgId, {
246
- tools: ctx.agent.tools ?? [],
246
+ disabledTools: ctx.agent.disabledTools,
247
+ subagentTools: ctx.agent.subagentTools,
247
248
  skillLoad,
248
249
  subagents: ctx.agent.subagents,
249
250
  child: ctx.parent !== undefined,
@@ -384,6 +385,7 @@ let ToolPipeline = class ToolPipeline {
384
385
  conversationId: ctx.conversationId,
385
386
  runId: ctx.runId,
386
387
  rawInput,
388
+ signal: ctx.signal,
387
389
  })) ?? null;
388
390
  // a deny with a reason (e.g. an unavailable operation): the reason is the tool error
389
391
  if (callPolicy?.policy === "deny" && callPolicy.denyReason !== undefined) {