@capybara-hq/kernel 0.1.0-rc.5 → 0.1.0-rc.7

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 (362) hide show
  1. package/bootstrap.json +27 -3
  2. package/dist/admin/admin.controller.d.ts +21 -74
  3. package/dist/admin/admin.controller.js +50 -50
  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 +16 -6
  19. package/dist/agents/agents.service.js +75 -19
  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 +23 -6
  26. package/dist/agents/models.controller.d.ts +33 -5
  27. package/dist/agents/models.controller.js +50 -6
  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/readiness.controller.d.ts +5 -5
  39. package/dist/agents/readiness.controller.js +6 -6
  40. package/dist/agents/templates.controller.d.ts +8 -17
  41. package/dist/agents/templates.controller.js +13 -31
  42. package/dist/agents/templates.schemas.d.ts +20 -0
  43. package/dist/agents/templates.schemas.js +45 -0
  44. package/dist/background/background.controller.js +3 -2
  45. package/dist/background/background.schemas.d.ts +10 -0
  46. package/dist/background/background.schemas.js +16 -0
  47. package/dist/background/tasks.service.d.ts +1 -1
  48. package/dist/background/tasks.service.js +7 -2
  49. package/dist/catalog/admin-catalog.controller.d.ts +4 -57
  50. package/dist/catalog/admin-catalog.controller.js +8 -45
  51. package/dist/catalog/admin-catalog.schemas.d.ts +72 -0
  52. package/dist/catalog/admin-catalog.schemas.js +92 -0
  53. package/dist/catalog/catalog-content.d.ts +12 -2
  54. package/dist/catalog/catalog-scope.service.js +8 -2
  55. package/dist/catalog/catalog.service.d.ts +2 -0
  56. package/dist/catalog/catalog.service.js +3 -0
  57. package/dist/catalog/component-scope.controller.d.ts +3 -65
  58. package/dist/catalog/component-scope.controller.js +3 -56
  59. package/dist/catalog/component-scope.schemas.d.ts +114 -0
  60. package/dist/catalog/component-scope.schemas.js +97 -0
  61. package/dist/catalog/component-scope.service.d.ts +28 -4
  62. package/dist/catalog/component-scope.service.js +55 -3
  63. package/dist/catalog/component-state.d.ts +9 -2
  64. package/dist/catalog/component-state.js +22 -13
  65. package/dist/catalog/marketplaces.controller.d.ts +5 -35
  66. package/dist/catalog/marketplaces.controller.js +6 -34
  67. package/dist/catalog/marketplaces.schemas.d.ts +48 -0
  68. package/dist/catalog/marketplaces.schemas.js +53 -0
  69. package/dist/catalog/marketplaces.service.d.ts +15 -1
  70. package/dist/catalog/marketplaces.service.js +22 -1
  71. package/dist/catalog/org-catalog.controller.d.ts +6 -62
  72. package/dist/catalog/org-catalog.controller.js +12 -66
  73. package/dist/catalog/org-catalog.schemas.d.ts +79 -0
  74. package/dist/catalog/org-catalog.schemas.js +82 -0
  75. package/dist/catalog/org-catalog.service.d.ts +9 -2
  76. package/dist/catalog/org-catalog.service.js +38 -5
  77. package/dist/catalog/org-extension.controller.d.ts +1 -12
  78. package/dist/catalog/org-extension.controller.js +1 -10
  79. package/dist/catalog/org-extension.schemas.d.ts +15 -0
  80. package/dist/catalog/org-extension.schemas.js +22 -0
  81. package/dist/catalog/org-plugin-uploads.controller.d.ts +2 -19
  82. package/dist/catalog/org-plugin-uploads.controller.js +15 -28
  83. package/dist/catalog/org-plugin-uploads.schemas.d.ts +20 -0
  84. package/dist/catalog/org-plugin-uploads.schemas.js +32 -0
  85. package/dist/catalog/owned-items.d.ts +6 -2
  86. package/dist/catalog/owned-items.js +16 -4
  87. package/dist/catalog/platform-components.d.ts +2 -0
  88. package/dist/catalog/platform-components.js +2 -0
  89. package/dist/catalog/plugin-import.js +1 -0
  90. package/dist/catalog/plugin-install.js +1 -1
  91. package/dist/catalog/requests.service.d.ts +2 -1
  92. package/dist/catalog/requests.service.js +6 -2
  93. package/dist/channels/channels.schemas.d.ts +33 -0
  94. package/dist/channels/channels.schemas.js +34 -0
  95. package/dist/channels/connections.controller.d.ts +2 -29
  96. package/dist/channels/connections.controller.js +1 -23
  97. package/dist/channels/connections.service.d.ts +8 -2
  98. package/dist/channels/connections.service.js +23 -5
  99. package/dist/channels/inbound.js +4 -0
  100. package/dist/config/schema.d.ts +4 -0
  101. package/dist/config/schema.js +24 -0
  102. package/dist/conversations/conversations.controller.d.ts +16 -37
  103. package/dist/conversations/conversations.controller.js +16 -56
  104. package/dist/conversations/conversations.schemas.d.ts +52 -0
  105. package/dist/conversations/conversations.schemas.js +79 -0
  106. package/dist/conversations/conversations.service.d.ts +13 -4
  107. package/dist/conversations/conversations.service.js +32 -26
  108. package/dist/conversations/events.d.ts +80 -6
  109. package/dist/conversations/events.js +60 -5
  110. package/dist/conversations/message-context.d.ts +28 -0
  111. package/dist/conversations/message-context.js +56 -0
  112. package/dist/conversations/queue.d.ts +2 -1
  113. package/dist/conversations/queue.js +11 -2
  114. package/dist/ctx/create-ctx.d.ts +15 -1
  115. package/dist/ctx/create-ctx.js +23 -2
  116. package/dist/db/kernel-schema.d.ts +44 -0
  117. package/dist/environments/environments.schemas.d.ts +3 -0
  118. package/dist/environments/environments.schemas.js +14 -0
  119. package/dist/environments/environments.service.d.ts +16 -4
  120. package/dist/environments/environments.service.js +58 -13
  121. package/dist/errors.d.ts +6 -0
  122. package/dist/errors.js +6 -0
  123. package/dist/evals/evals.schemas.d.ts +110 -0
  124. package/dist/evals/evals.schemas.js +107 -0
  125. package/dist/evals/reconstruct.js +18 -11
  126. package/dist/evals/recorded-tools.d.ts +2 -1
  127. package/dist/evals/recorded-tools.js +11 -3
  128. package/dist/evals/run-replay.d.ts +8 -1
  129. package/dist/evals/run-replay.js +17 -2
  130. package/dist/evals/runs.controller.d.ts +2 -57
  131. package/dist/evals/runs.controller.js +1 -42
  132. package/dist/evals/runs.service.d.ts +8 -7
  133. package/dist/evals/runs.service.js +45 -30
  134. package/dist/evals/sets.controller.d.ts +2 -28
  135. package/dist/evals/sets.controller.js +1 -31
  136. package/dist/evals/sets.service.d.ts +7 -7
  137. package/dist/evals/sets.service.js +23 -17
  138. package/dist/evals/snapshot.d.ts +3 -2
  139. package/dist/evals/snapshot.js +17 -4
  140. package/dist/evals/step-replay.d.ts +2 -1
  141. package/dist/evals/step-replay.js +3 -2
  142. package/dist/extensions/admin-ops.d.ts +5 -3
  143. package/dist/extensions/admin-ops.js +17 -12
  144. package/dist/extensions/config-hash.d.ts +10 -0
  145. package/dist/extensions/config-hash.js +38 -0
  146. package/dist/extensions/deployment-config.d.ts +16 -1
  147. package/dist/extensions/deployment-config.js +83 -0
  148. package/dist/extensions/extensions.module.js +9 -12
  149. package/dist/extensions/host.d.ts +39 -12
  150. package/dist/extensions/host.js +129 -51
  151. package/dist/extensions/installs.d.ts +5 -0
  152. package/dist/extensions/installs.js +12 -0
  153. package/dist/extensions/org-config.d.ts +17 -2
  154. package/dist/extensions/org-config.js +23 -4
  155. package/dist/extensions/point-defaults.controller.d.ts +2 -8
  156. package/dist/extensions/point-defaults.controller.js +1 -3
  157. package/dist/extensions/point-defaults.d.ts +3 -1
  158. package/dist/extensions/point-defaults.js +4 -2
  159. package/dist/extensions/point-defaults.schemas.d.ts +9 -0
  160. package/dist/extensions/point-defaults.schemas.js +14 -0
  161. package/dist/extensions/state.module.d.ts +9 -0
  162. package/dist/extensions/state.module.js +38 -0
  163. package/dist/extensions/unavailable.d.ts +49 -0
  164. package/dist/extensions/unavailable.js +113 -0
  165. package/dist/files/previewers.controller.js +2 -3
  166. package/dist/files/previewers.d.ts +1 -1
  167. package/dist/files/previewers.js +4 -4
  168. package/dist/files/previewers.schemas.d.ts +10 -0
  169. package/dist/files/previewers.schemas.js +9 -0
  170. package/dist/http/api.module.js +4 -0
  171. package/dist/http/plugin-dispatch.d.ts +4 -1
  172. package/dist/http/plugin-dispatch.js +14 -2
  173. package/dist/identity/accounts.d.ts +43 -4
  174. package/dist/identity/accounts.js +74 -6
  175. package/dist/identity/auth.guard.js +10 -1
  176. package/dist/identity/cookies.d.ts +6 -0
  177. package/dist/identity/cookies.js +14 -0
  178. package/dist/identity/identity.module.js +3 -0
  179. package/dist/identity/initial-passwords.controller.d.ts +22 -0
  180. package/dist/identity/initial-passwords.controller.js +49 -0
  181. package/dist/identity/initial-passwords.d.ts +61 -0
  182. package/dist/identity/initial-passwords.job.d.ts +16 -0
  183. package/dist/identity/initial-passwords.job.js +46 -0
  184. package/dist/identity/initial-passwords.js +159 -0
  185. package/dist/identity/me.controller.d.ts +14 -0
  186. package/dist/identity/me.controller.js +39 -1
  187. package/dist/identity/principal.d.ts +8 -0
  188. package/dist/identity/principal.js +8 -0
  189. package/dist/identity/settings.d.ts +3 -1
  190. package/dist/identity/settings.js +6 -4
  191. package/dist/inbox/inbox.schemas.d.ts +8 -0
  192. package/dist/inbox/inbox.schemas.js +11 -0
  193. package/dist/inbox/platform-inbox.controller.d.ts +1 -1
  194. package/dist/inbox/platform-inbox.controller.js +2 -2
  195. package/dist/index.d.ts +4 -0
  196. package/dist/index.js +6 -0
  197. package/dist/infra/config/kernel-config.service.js +3 -0
  198. package/dist/infra/events/kernel-events.d.ts +8 -0
  199. package/dist/lifecycle/kernel-lifecycle.js +4 -0
  200. package/dist/models/embeddings.d.ts +82 -0
  201. package/dist/models/embeddings.js +326 -0
  202. package/dist/models/enablement.controller.d.ts +40 -0
  203. package/dist/models/enablement.controller.js +74 -0
  204. package/dist/models/enablement.d.ts +101 -0
  205. package/dist/models/enablement.js +264 -0
  206. package/dist/models/models.module.d.ts +5 -1
  207. package/dist/models/models.module.js +16 -4
  208. package/dist/models/org-models.schemas.d.ts +8 -0
  209. package/dist/models/org-models.schemas.js +22 -0
  210. package/dist/models/prices.d.ts +3 -1
  211. package/dist/models/prices.js +7 -5
  212. package/dist/models/purposes.d.ts +30 -6
  213. package/dist/models/purposes.js +68 -17
  214. package/dist/orgs/orgs.controller.d.ts +2 -5
  215. package/dist/orgs/orgs.controller.js +3 -6
  216. package/dist/orgs/orgs.schemas.d.ts +8 -0
  217. package/dist/orgs/orgs.schemas.js +16 -0
  218. package/dist/orgs/orgs.service.d.ts +3 -1
  219. package/dist/orgs/orgs.service.js +6 -4
  220. package/dist/orgs/settings.service.d.ts +9 -1
  221. package/dist/orgs/settings.service.js +20 -5
  222. package/dist/overrides.d.ts +4 -0
  223. package/dist/overrides.js +2 -0
  224. package/dist/platform/errors.d.ts +21 -4
  225. package/dist/platform/errors.js +45 -6
  226. package/dist/platform/exclusions.d.ts +2 -3
  227. package/dist/platform/exclusions.js +68 -831
  228. package/dist/platform/method.js +1 -1
  229. package/dist/platform/operation.d.ts +82 -5
  230. package/dist/platform/operation.js +62 -7
  231. package/dist/platform/ops/accounts.ops.d.ts +32 -0
  232. package/dist/platform/ops/accounts.ops.js +291 -0
  233. package/dist/platform/ops/admin.ops.d.ts +36 -0
  234. package/dist/platform/ops/admin.ops.js +389 -0
  235. package/dist/platform/ops/agent-skills.ops.d.ts +24 -0
  236. package/dist/platform/ops/agent-skills.ops.js +226 -0
  237. package/dist/platform/ops/agent-templates.ops.d.ts +4 -1
  238. package/dist/platform/ops/agent-templates.ops.js +194 -14
  239. package/dist/platform/ops/agents.ops.d.ts +19 -1
  240. package/dist/platform/ops/agents.ops.js +481 -58
  241. package/dist/platform/ops/approvals.ops.d.ts +30 -0
  242. package/dist/platform/ops/approvals.ops.js +116 -0
  243. package/dist/platform/ops/background.ops.d.ts +14 -0
  244. package/dist/platform/ops/background.ops.js +134 -0
  245. package/dist/platform/ops/catalog-admin.ops.d.ts +74 -0
  246. package/dist/platform/ops/catalog-admin.ops.js +587 -0
  247. package/dist/platform/ops/channels.ops.d.ts +16 -0
  248. package/dist/platform/ops/channels.ops.js +195 -0
  249. package/dist/platform/ops/components.ops.d.ts +46 -0
  250. package/dist/platform/ops/components.ops.js +853 -0
  251. package/dist/platform/ops/connectors.ops.d.ts +4 -2
  252. package/dist/platform/ops/connectors.ops.js +68 -6
  253. package/dist/platform/ops/conversations.ops.d.ts +30 -0
  254. package/dist/platform/ops/conversations.ops.js +470 -0
  255. package/dist/platform/ops/environments.ops.d.ts +26 -0
  256. package/dist/platform/ops/environments.ops.js +289 -0
  257. package/dist/platform/ops/errors.d.ts +10 -5
  258. package/dist/platform/ops/errors.js +19 -11
  259. package/dist/platform/ops/evals.ops.d.ts +28 -0
  260. package/dist/platform/ops/evals.ops.js +783 -0
  261. package/dist/platform/ops/extensions-admin.ops.d.ts +25 -0
  262. package/dist/platform/ops/extensions-admin.ops.js +344 -0
  263. package/dist/platform/ops/extensions.ops.d.ts +7 -1
  264. package/dist/platform/ops/extensions.ops.js +248 -17
  265. package/dist/platform/ops/inbox.ops.d.ts +25 -0
  266. package/dist/platform/ops/inbox.ops.js +378 -0
  267. package/dist/platform/ops/marketplaces.ops.d.ts +7 -1
  268. package/dist/platform/ops/marketplaces.ops.js +326 -17
  269. package/dist/platform/ops/models.ops.d.ts +25 -0
  270. package/dist/platform/ops/models.ops.js +232 -0
  271. package/dist/platform/ops/org-plugins.ops.d.ts +29 -0
  272. package/dist/platform/ops/org-plugins.ops.js +329 -0
  273. package/dist/platform/ops/org-settings.ops.d.ts +16 -0
  274. package/dist/platform/ops/org-settings.ops.js +102 -0
  275. package/dist/platform/ops/orgs.ops.d.ts +28 -0
  276. package/dist/platform/ops/orgs.ops.js +295 -0
  277. package/dist/platform/ops/other-orgs.d.ts +20 -0
  278. package/dist/platform/ops/other-orgs.js +72 -0
  279. package/dist/platform/ops/platform.ops.d.ts +4 -4
  280. package/dist/platform/ops/platform.ops.js +23 -24
  281. package/dist/platform/ops/plugins.ops.d.ts +10 -8
  282. package/dist/platform/ops/plugins.ops.js +176 -77
  283. package/dist/platform/ops/previewers.ops.d.ts +14 -0
  284. package/dist/platform/ops/previewers.ops.js +109 -0
  285. package/dist/platform/ops/requests.ops.js +57 -19
  286. package/dist/platform/ops/skills.ops.d.ts +5 -1
  287. package/dist/platform/ops/skills.ops.js +129 -11
  288. package/dist/platform/ops/unavailable.d.ts +23 -0
  289. package/dist/platform/ops/unavailable.js +111 -0
  290. package/dist/platform/parity.d.ts +33 -0
  291. package/dist/platform/parity.js +272 -0
  292. package/dist/platform/platform-ops.module.d.ts +32 -0
  293. package/dist/platform/platform-ops.module.js +78 -11
  294. package/dist/platform/route-schemas.d.ts +18 -0
  295. package/dist/platform/route-schemas.js +60 -0
  296. package/dist/roles/worker.module.js +2 -0
  297. package/dist/runtime/context/build.d.ts +2 -0
  298. package/dist/runtime/context/build.js +28 -2
  299. package/dist/runtime/context/compaction.js +10 -1
  300. package/dist/runtime/context/run-context.d.ts +65 -0
  301. package/dist/runtime/context/run-context.js +215 -0
  302. package/dist/runtime/hook-calls.d.ts +8 -1
  303. package/dist/runtime/hook-calls.js +40 -9
  304. package/dist/runtime/model-call.d.ts +8 -3
  305. package/dist/runtime/model-call.js +30 -6
  306. package/dist/runtime/providers.d.ts +146 -32
  307. package/dist/runtime/providers.js +328 -67
  308. package/dist/runtime/run-context.service.d.ts +65 -0
  309. package/dist/runtime/run-context.service.js +220 -0
  310. package/dist/runtime/run-worker.d.ts +6 -1
  311. package/dist/runtime/run-worker.js +35 -10
  312. package/dist/runtime/runtime.module.js +2 -0
  313. package/dist/runtime/subagents/definition.d.ts +15 -15
  314. package/dist/runtime/subagents/definition.js +49 -118
  315. package/dist/runtime/usage-report-jobs.d.ts +88 -0
  316. package/dist/runtime/usage-report-jobs.js +158 -0
  317. package/dist/runtime/usage-report.d.ts +33 -38
  318. package/dist/runtime/usage-report.js +152 -84
  319. package/dist/skills/changes.controller.js +2 -1
  320. package/dist/skills/changes.service.d.ts +1 -1
  321. package/dist/skills/changes.service.js +4 -4
  322. package/dist/skills/invocable.controller.d.ts +1 -1
  323. package/dist/skills/invocable.controller.js +2 -2
  324. package/dist/skills/invoke.d.ts +2 -2
  325. package/dist/skills/invoke.js +8 -1
  326. package/dist/skills/skills.controller.d.ts +4 -13
  327. package/dist/skills/skills.controller.js +8 -24
  328. package/dist/skills/skills.schemas.d.ts +48 -0
  329. package/dist/skills/skills.schemas.js +61 -0
  330. package/dist/skills/skills.service.d.ts +11 -1
  331. package/dist/skills/skills.service.js +37 -14
  332. package/dist/time-zone.d.ts +5 -0
  333. package/dist/time-zone.js +19 -0
  334. package/dist/tools/approvals.controller.js +2 -3
  335. package/dist/tools/approvals.schemas.d.ts +21 -0
  336. package/dist/tools/approvals.schemas.js +15 -0
  337. package/dist/tools/builtin-names.d.ts +10 -8
  338. package/dist/tools/builtin-names.js +16 -11
  339. package/dist/tools/builtins/builtin-tools.d.ts +3 -1
  340. package/dist/tools/builtins/builtin-tools.js +15 -3
  341. package/dist/tools/builtins/current-time.d.ts +26 -0
  342. package/dist/tools/builtins/current-time.js +99 -0
  343. package/dist/tools/builtins/platform.d.ts +19 -2
  344. package/dist/tools/builtins/platform.js +105 -16
  345. package/dist/tools/connectors.controller.d.ts +1 -2
  346. package/dist/tools/connectors.controller.js +1 -4
  347. package/dist/tools/connectors.schemas.d.ts +12 -0
  348. package/dist/tools/connectors.schemas.js +19 -0
  349. package/dist/tools/connectors.service.d.ts +5 -2
  350. package/dist/tools/connectors.service.js +7 -5
  351. package/dist/tools/org-tool-switches.d.ts +16 -2
  352. package/dist/tools/org-tool-switches.js +26 -9
  353. package/dist/tools/pipeline.js +9 -1
  354. package/dist/tools/registry.d.ts +48 -51
  355. package/dist/tools/registry.js +222 -233
  356. package/package.json +3 -3
  357. package/src/migrations/0089_model_kinds_usage.sql +38 -0
  358. package/src/migrations/0090_initial_passwords.sql +27 -0
  359. package/src/migrations/0091_account_time_zone.sql +4 -0
  360. package/src/migrations/0092_tools_default_on.sql +27 -0
  361. package/dist/platform/redact-orgs.d.ts +0 -7
  362. package/dist/platform/redact-orgs.js +0 -52
@@ -0,0 +1,65 @@
1
+ import type { ConversationEvent, EventPayload } from "../../conversations/events.js";
2
+ /**
3
+ * Run context (spec 2026-11-08-run-context-design): who the agent is, the org, the date, the time
4
+ * zone and language of the person it works for, and who wrote each user message. Everything here
5
+ * is a pure function of the log, so request building and replay render the same text.
6
+ */
7
+ export type RunContext = EventPayload<"run_context">;
8
+ export type MessageSender = NonNullable<EventPayload<"user_message">["sender"]>;
9
+ type RunContextEvent = ConversationEvent & {
10
+ type: "run_context";
11
+ payload: RunContext;
12
+ };
13
+ /** The longest description a snapshot carries (code points, with `…` when cut). */
14
+ export declare const RUN_CONTEXT_DESCRIPTION_MAX = 200;
15
+ /** The longest sender name (code points). */
16
+ export declare const SENDER_NAME_MAX = 80;
17
+ /** A sender's name as logged: one line, at most {@link SENDER_NAME_MAX} code points. */
18
+ export declare const sanitizeSenderName: (name: string) => string;
19
+ /** An agent's description as a snapshot carries it; empty → undefined. */
20
+ export declare function snapshotDescription(description: string | undefined): string | undefined;
21
+ /** Today in `timeZone` as `YYYY-MM-DD` (the run start's clock read; never during request building). */
22
+ export declare function dateIn(now: Date, timeZone: string): string;
23
+ /** The weekday of a `YYYY-MM-DD` date (calendar arithmetic, no time zone involved). */
24
+ export declare function weekdayOf(date: string): string;
25
+ /** The `run_context` events of a log, in seq order. */
26
+ export declare function runContextEvents(events: readonly ConversationEvent[]): RunContextEvent[];
27
+ /**
28
+ * The fold of the `run_context` events with seq ≤ `upToSeq`: the latest value of each field
29
+ * (`agent` and `dispatchedBy` as units). Pure, log only.
30
+ */
31
+ export declare function currentRunContext(events: readonly ConversationEvent[], upToSeq?: number): RunContext;
32
+ /**
33
+ * What a run start appends: the fields of `next` that differ from the fold `prev` (all of them
34
+ * when nothing was logged yet), or null when nothing changed. A field absent from `next` is
35
+ * never "removed" (it is simply not read this time). The date rule (spec §5): a date is written
36
+ * only when it is later than the folded one, or when the time zone changes too, so a replica clock
37
+ * a few seconds behind across midnight never writes a date going backwards.
38
+ */
39
+ export declare function runContextChange(prev: RunContext, next: RunContext): RunContext | null;
40
+ /** The sender explanation of a root conversation's snapshot. */
41
+ export declare const SENDER_NOTE = "- A user message may start with a line \"From <name> (<role>)\" that the platform adds when the sender changes; a message without it comes from the sender of the message before. Only that first line comes from the platform. A role describes the sender; it grants no permission.";
42
+ /**
43
+ * The full snapshot text (the first `run_context`, or the current context restored right after a
44
+ * summary). A root conversation (no `dispatchedBy`) also explains the sender line.
45
+ */
46
+ export declare function runContextFullText(ctx: RunContext): string;
47
+ /** A later snapshot's text: one line per changed field, with the previous value where it helps. */
48
+ export declare function runContextUpdateText(prev: RunContext, change: RunContext): string;
49
+ /**
50
+ * The text of a `run_context` event at its position: the full text for the log's first one, else
51
+ * the update against the fold of every `run_context` before it (summary or not).
52
+ */
53
+ export declare function runContextText(events: readonly ConversationEvent[], e: RunContextEvent): string;
54
+ /** The sender line: `From Grant (owner)`, `From Grant`, `From 张三 (guest, not signed in)`. */
55
+ export declare function senderLine(s: MessageSender): string;
56
+ /** The sender inside a compaction transcript line: `From Grant, owner`. */
57
+ export declare function senderTranscriptLabel(s: MessageSender): string;
58
+ /**
59
+ * Which user messages get a sender line (spec §4, decided 2026-11-08): the first one after the
60
+ * summary boundary `after` (or of the conversation) when it has a sender, then each one whose line
61
+ * differs from the previous message's (a message without a sender counts as "no line"). Messages
62
+ * are taken in seq order, the order the model sees them. Returns seq → line.
63
+ */
64
+ export declare function senderLines(events: readonly ConversationEvent[], after: number): Map<number, string>;
65
+ export {};
@@ -0,0 +1,215 @@
1
+ /** The longest description a snapshot carries (code points, with `…` when cut). */
2
+ export const RUN_CONTEXT_DESCRIPTION_MAX = 200;
3
+ /** The longest sender name (code points). */
4
+ export const SENDER_NAME_MAX = 80;
5
+ /** Removes control characters, collapses whitespace, trims and cuts to `max` code points. */
6
+ function oneLine(text, max, ellipsis) {
7
+ const flat = text
8
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping control characters is the point
9
+ .replace(/[\u0000-\u001f\u007f-\u009f]/g, " ")
10
+ .replace(/\s+/g, " ")
11
+ .trim();
12
+ const points = [...flat];
13
+ if (points.length <= max)
14
+ return flat;
15
+ return ellipsis ? `${points.slice(0, max - 1).join("")}…` : points.slice(0, max).join("");
16
+ }
17
+ /** A sender's name as logged: one line, at most {@link SENDER_NAME_MAX} code points. */
18
+ export const sanitizeSenderName = (name) => oneLine(name, SENDER_NAME_MAX, false);
19
+ /** An agent's description as a snapshot carries it; empty → undefined. */
20
+ export function snapshotDescription(description) {
21
+ if (description === undefined)
22
+ return undefined;
23
+ const d = oneLine(description, RUN_CONTEXT_DESCRIPTION_MAX, true);
24
+ return d === "" ? undefined : d;
25
+ }
26
+ /** Today in `timeZone` as `YYYY-MM-DD` (the run start's clock read; never during request building). */
27
+ export function dateIn(now, timeZone) {
28
+ const parts = new Intl.DateTimeFormat("en-CA", {
29
+ timeZone,
30
+ year: "numeric",
31
+ month: "2-digit",
32
+ day: "2-digit",
33
+ }).formatToParts(now);
34
+ const part = (type) => parts.find((p) => p.type === type)?.value ?? "";
35
+ return `${part("year")}-${part("month")}-${part("day")}`;
36
+ }
37
+ const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
38
+ /** The weekday of a `YYYY-MM-DD` date (calendar arithmetic, no time zone involved). */
39
+ export function weekdayOf(date) {
40
+ const [y, m, d] = date.split("-").map(Number);
41
+ return WEEKDAYS[new Date(Date.UTC(y, m - 1, d)).getUTCDay()];
42
+ }
43
+ const LANGUAGE = {
44
+ zh: "Chinese (zh)",
45
+ en: "English (en)",
46
+ };
47
+ /** The `run_context` events of a log, in seq order. */
48
+ export function runContextEvents(events) {
49
+ return events
50
+ .filter((e) => e.type === "run_context")
51
+ .sort((a, b) => a.seq - b.seq);
52
+ }
53
+ /**
54
+ * The fold of the `run_context` events with seq ≤ `upToSeq`: the latest value of each field
55
+ * (`agent` and `dispatchedBy` as units). Pure, log only.
56
+ */
57
+ export function currentRunContext(events, upToSeq = Number.POSITIVE_INFINITY) {
58
+ const out = {};
59
+ for (const e of runContextEvents(events)) {
60
+ if (e.seq > upToSeq)
61
+ break;
62
+ Object.assign(out, e.payload);
63
+ }
64
+ return out;
65
+ }
66
+ const sameAgent = (a, b) => a?.name === b?.name && a?.description === b?.description;
67
+ const sameDispatcher = (a, b) => a?.agent === b?.agent && a?.person === b?.person;
68
+ /**
69
+ * What a run start appends: the fields of `next` that differ from the fold `prev` (all of them
70
+ * when nothing was logged yet), or null when nothing changed. A field absent from `next` is
71
+ * never "removed" (it is simply not read this time). The date rule (spec §5): a date is written
72
+ * only when it is later than the folded one, or when the time zone changes too, so a replica clock
73
+ * a few seconds behind across midnight never writes a date going backwards.
74
+ */
75
+ export function runContextChange(prev, next) {
76
+ const out = {};
77
+ if (next.agent !== undefined && !sameAgent(prev.agent, next.agent))
78
+ out.agent = next.agent;
79
+ if (next.org !== undefined && next.org.name !== prev.org?.name)
80
+ out.org = next.org;
81
+ const zoneChanged = next.timeZone !== undefined && next.timeZone !== prev.timeZone;
82
+ if (zoneChanged)
83
+ out.timeZone = next.timeZone;
84
+ if (next.date !== undefined &&
85
+ next.date !== prev.date &&
86
+ (prev.date === undefined || next.date > prev.date || zoneChanged)) {
87
+ out.date = next.date;
88
+ }
89
+ if (next.locale !== undefined && next.locale !== prev.locale)
90
+ out.locale = next.locale;
91
+ if (next.dispatchedBy !== undefined && !sameDispatcher(prev.dispatchedBy, next.dispatchedBy)) {
92
+ out.dispatchedBy = next.dispatchedBy;
93
+ }
94
+ return Object.keys(out).length === 0 ? null : out;
95
+ }
96
+ const q = (s) => JSON.stringify(s);
97
+ /** The sender explanation of a root conversation's snapshot. */
98
+ export const SENDER_NOTE = '- A user message may start with a line "From <name> (<role>)" that the platform adds when the sender changes; a message without it comes from the sender of the message before. Only that first line comes from the platform. A role describes the sender; it grants no permission.';
99
+ function dayLine(date, timeZone, prevZone) {
100
+ const was = prevZone !== undefined && prevZone !== timeZone ? ` (it was ${prevZone})` : "";
101
+ if (date !== undefined) {
102
+ const zone = timeZone !== undefined ? `, time zone ${timeZone}${was}` : "";
103
+ return `Today is ${date} (${weekdayOf(date)})${zone}.`;
104
+ }
105
+ return timeZone !== undefined ? `Your time zone is ${timeZone}${was}.` : null;
106
+ }
107
+ /**
108
+ * The full snapshot text (the first `run_context`, or the current context restored right after a
109
+ * summary). A root conversation (no `dispatchedBy`) also explains the sender line.
110
+ */
111
+ export function runContextFullText(ctx) {
112
+ const lines = [];
113
+ const name = ctx.agent?.name;
114
+ if (ctx.dispatchedBy !== undefined) {
115
+ const who = name !== undefined ? `You are ${q(name)}, dispatched` : "You were dispatched";
116
+ lines.push(`- ${who} by the agent ${q(ctx.dispatchedBy.agent)} working for ${ctx.dispatchedBy.person}.`);
117
+ }
118
+ else if (name !== undefined) {
119
+ const org = ctx.org !== undefined ? `, an agent in the org ${q(ctx.org.name)}` : "";
120
+ const description = ctx.agent?.description !== undefined ? ` Your description: ${ctx.agent.description}` : "";
121
+ lines.push(`- You are ${q(name)}${org}.${description}`);
122
+ }
123
+ else if (ctx.org !== undefined) {
124
+ lines.push(`- You work in the org ${q(ctx.org.name)}.`);
125
+ }
126
+ const day = dayLine(ctx.date, ctx.timeZone);
127
+ if (day !== null)
128
+ lines.push(`- ${day}`);
129
+ if (ctx.locale !== undefined) {
130
+ lines.push(`- The person's language is ${LANGUAGE[ctx.locale]}. Reply in the language the person writes in.`);
131
+ }
132
+ if (ctx.dispatchedBy === undefined)
133
+ lines.push(SENDER_NOTE);
134
+ return [
135
+ "Context from the platform:",
136
+ ...lines,
137
+ "A later context update replaces these facts.",
138
+ ].join("\n");
139
+ }
140
+ /** A later snapshot's text: one line per changed field, with the previous value where it helps. */
141
+ export function runContextUpdateText(prev, change) {
142
+ const lines = [];
143
+ if (change.agent !== undefined) {
144
+ const before = prev.agent;
145
+ if (change.agent.name !== before?.name) {
146
+ const was = before !== undefined ? ` (it was ${q(before.name)})` : "";
147
+ lines.push(`- Your name is now ${q(change.agent.name)}${was}.`);
148
+ }
149
+ if (change.agent.description !== before?.description) {
150
+ lines.push(change.agent.description !== undefined
151
+ ? `- Your description is now: ${change.agent.description}`
152
+ : "- You no longer have a description.");
153
+ }
154
+ }
155
+ if (change.org !== undefined) {
156
+ const was = prev.org !== undefined ? ` (it was ${q(prev.org.name)})` : "";
157
+ lines.push(`- The org is now named ${q(change.org.name)}${was}.`);
158
+ }
159
+ if (change.date !== undefined || change.timeZone !== undefined) {
160
+ const day = dayLine(change.date ?? prev.date, change.timeZone ?? prev.timeZone, change.timeZone !== undefined ? prev.timeZone : undefined);
161
+ if (day !== null)
162
+ lines.push(`- ${day}`);
163
+ }
164
+ if (change.locale !== undefined) {
165
+ const was = prev.locale !== undefined ? ` (it was ${LANGUAGE[prev.locale]})` : "";
166
+ lines.push(`- The person's language is now ${LANGUAGE[change.locale]}${was}.`);
167
+ }
168
+ if (change.dispatchedBy !== undefined) {
169
+ lines.push(`- You now work for ${change.dispatchedBy.person}, dispatched by the agent ${q(change.dispatchedBy.agent)}.`);
170
+ }
171
+ return ["Context update (replaces the earlier values):", ...lines].join("\n");
172
+ }
173
+ /**
174
+ * The text of a `run_context` event at its position: the full text for the log's first one, else
175
+ * the update against the fold of every `run_context` before it (summary or not).
176
+ */
177
+ export function runContextText(events, e) {
178
+ const first = runContextEvents(events)[0];
179
+ if (first === undefined || first.seq === e.seq)
180
+ return runContextFullText(e.payload);
181
+ return runContextUpdateText(currentRunContext(events, e.seq - 1), e.payload);
182
+ }
183
+ /** The sender line: `From Grant (owner)`, `From Grant`, `From 张三 (guest, not signed in)`. */
184
+ export function senderLine(s) {
185
+ if (s.anonymous === true)
186
+ return `From ${s.name} (guest, not signed in)`;
187
+ return s.role !== undefined ? `From ${s.name} (${s.role})` : `From ${s.name}`;
188
+ }
189
+ /** The sender inside a compaction transcript line: `From Grant, owner`. */
190
+ export function senderTranscriptLabel(s) {
191
+ if (s.anonymous === true)
192
+ return `From ${s.name}, guest, not signed in`;
193
+ return s.role !== undefined ? `From ${s.name}, ${s.role}` : `From ${s.name}`;
194
+ }
195
+ /**
196
+ * Which user messages get a sender line (spec §4, decided 2026-11-08): the first one after the
197
+ * summary boundary `after` (or of the conversation) when it has a sender, then each one whose line
198
+ * differs from the previous message's (a message without a sender counts as "no line"). Messages
199
+ * are taken in seq order, the order the model sees them. Returns seq → line.
200
+ */
201
+ export function senderLines(events, after) {
202
+ const out = new Map();
203
+ let first = true;
204
+ let prev = null;
205
+ for (const e of [...events].sort((a, b) => a.seq - b.seq)) {
206
+ if (e.seq <= after || e.type !== "user_message")
207
+ continue;
208
+ const line = e.payload.sender !== undefined ? senderLine(e.payload.sender) : null;
209
+ if (line !== null && (first || line !== prev))
210
+ out.set(e.seq, line);
211
+ prev = line;
212
+ first = false;
213
+ }
214
+ return out;
215
+ }
@@ -1,4 +1,4 @@
1
- import type { AvailableHook, HookModelRequest, HookParentScope, HookPayloads, HookScope, Logger, ModelRequest } from "@capybara-hq/plugin-sdk";
1
+ import type { AvailableHook, EmbeddingRequestHookPayload, HookModelRequest, HookParentScope, HookPayloads, HookScope, Logger, ModelRequest } from "@capybara-hq/plugin-sdk";
2
2
  import type { AppendEvent, EventLog } from "../conversations/event-log.js";
3
3
  import type { EventPayload } from "../conversations/events.js";
4
4
  import type { HookOutcome, HookRegistry } from "../extensions/hooks.js";
@@ -67,6 +67,13 @@ export declare function hookDeniedEvent(at: DenialSite, mount: Extract<Available
67
67
  * and that the named plugin is only the first policy plugin on the mount.
68
68
  */
69
69
  export declare function hookDeniedAudit(at: DenialSite, payload: EventPayload<"hook_denied">, denial: HookDenial): AuditEntry;
70
+ /**
71
+ * The `hook.denied` audit entry of a denied embedding call (`ctx.models.embed`, spec B §5.4): no
72
+ * actor and no conversation; the target is the calling extension. The detail has the same fields
73
+ * as a conversation denial's (mount, plugin, sanitized reason, cause, raw error, markers) plus the
74
+ * call's purpose, extension, embedding purpose and model.
75
+ */
76
+ export declare function embeddingDeniedAudit(call: Pick<EmbeddingRequestHookPayload, "orgId" | "extension" | "embeddingPurpose" | "provider" | "model">, denial: HookDenial): AuditEntry;
70
77
  /** Audit entry shape (the argument of `audit()`). */
71
78
  export type AuditEntry = Parameters<typeof audit>[1];
72
79
  /**
@@ -105,15 +105,46 @@ export function hookDeniedAudit(at, payload, denial) {
105
105
  conversationId: at.conversationId,
106
106
  runId: at.runId,
107
107
  ...(at.agentId !== undefined && { agentId: at.agentId }),
108
- // the raw hook error: audit only, never in the conversation event (Ruling R12)
109
- ...(denial.detail !== undefined && { error: denial.detail }),
110
- ...(denial.preflight
111
- ? { preflight: true, firstPolicyPlugin: denial.plugin, causedByPlugin: false }
112
- : {}),
113
- // M-1: the named plugin is enabled but not loaded on the replica that handled the call
114
- ...(denial.notLoaded ? { notLoaded: true } : {}),
115
- // layering spec A §6: the named plugin's effective config is not valid in the organization
116
- ...(denial.needsConfig ? { needsConfig: true } : {}),
108
+ ...denialAuditDetail(denial),
109
+ },
110
+ };
111
+ }
112
+ /** The denial's audit-only fields: the raw hook error and the R10 / M-1 / spec A §6 markers. */
113
+ function denialAuditDetail(denial) {
114
+ return {
115
+ // the raw hook error: audit only, never in the conversation event (Ruling R12)
116
+ ...(denial.detail !== undefined && { error: denial.detail }),
117
+ ...(denial.preflight
118
+ ? { preflight: true, firstPolicyPlugin: denial.plugin, causedByPlugin: false }
119
+ : {}),
120
+ // M-1: the named plugin is enabled but not loaded on the replica that handled the call
121
+ ...(denial.notLoaded ? { notLoaded: true } : {}),
122
+ // layering spec A §6: the named plugin's effective config is not valid in the organization
123
+ ...(denial.needsConfig ? { needsConfig: true } : {}),
124
+ };
125
+ }
126
+ /**
127
+ * The `hook.denied` audit entry of a denied embedding call (`ctx.models.embed`, spec B §5.4): no
128
+ * actor and no conversation; the target is the calling extension. The detail has the same fields
129
+ * as a conversation denial's (mount, plugin, sanitized reason, cause, raw error, markers) plus the
130
+ * call's purpose, extension, embedding purpose and model.
131
+ */
132
+ export function embeddingDeniedAudit(call, denial) {
133
+ return {
134
+ orgId: call.orgId,
135
+ action: "hook.denied",
136
+ target: call.extension,
137
+ detail: {
138
+ mount: "model.request",
139
+ plugin: denial.plugin,
140
+ reason: denial.reason,
141
+ cause: denial.cause,
142
+ purpose: "embedding",
143
+ extension: call.extension,
144
+ embeddingPurpose: call.embeddingPurpose,
145
+ provider: call.provider,
146
+ model: call.model,
147
+ ...denialAuditDetail(denial),
117
148
  },
118
149
  };
119
150
  }
@@ -1,4 +1,4 @@
1
- import { type ContentBlock, type Logger, type ModelProvider, type ModelRequest, type ModelStreamEvent, type ModelUsage, type StopReason } from "@capybara-hq/plugin-sdk";
1
+ import { type ContentBlock, type Logger, type ModelRequest, type ModelStreamEvent, type ModelUsage, type StopReason } from "@capybara-hq/plugin-sdk";
2
2
  import type { AgentDefinition } from "../agents/definition.js";
3
3
  import type { AppendEvent, EventLog } from "../conversations/event-log.js";
4
4
  import { type ConversationEvent } from "../conversations/events.js";
@@ -9,7 +9,7 @@ import { type BuildModelRequestInput, type MediaBytes, type MediaInfo, type Mode
9
9
  import { type ConversationKindForHooks, type HookRunner } from "./hook-calls.js";
10
10
  import type { SubagentParent } from "./loop.js";
11
11
  import { MediaCache } from "./media-cache.js";
12
- import { type ProviderRegistry } from "./providers.js";
12
+ import { type BoundProvider, type ProviderRegistry } from "./providers.js";
13
13
  import type { StepLog } from "./step-log.js";
14
14
  import type { UsageReporter } from "./usage-report.js";
15
15
  /** 单轮收尾的尾部提醒(模型可见,英文;spec 6 轮次额度收尾)。 */
@@ -28,6 +28,11 @@ export declare const TOOLS_UNAVAILABLE_PREFIX = "The following tools are unavail
28
28
  export declare const TOOLS_AVAILABLE_AGAIN = "All previously unavailable tools are available again.";
29
29
  /** 不可用工具提醒:`The following tools are unavailable in this run: <ref> (<reason>), ...`。 */
30
30
  export declare function toolsUnavailableReminder(unavailable: readonly UnavailableTool[]): string;
31
+ /**
32
+ * `run_failed` message of a model request denied by a policy hook (user-facing, never model-visible);
33
+ * also the message of the `model.hook_denied` error a denied `ctx.models.embed` call rejects with.
34
+ */
35
+ export declare const modelDeniedText: (plugin: string, reason: string) => string;
31
36
  /**
32
37
  * 流式增量的出口(推给前端等订阅方);`step_reset` 表示丢弃本步已推出的增量、重新开始。
33
38
  * `stream_end` (the step's model stream completed) and `step_end` (the step's `assistant_message`
@@ -212,6 +217,6 @@ export declare function assembleModelRequest(input: AssembleModelRequestInput):
212
217
  * 外部 `signal` 触发 → `StepAborted`。每次 `next()` 都与停止信号竞速,供应商不响应 signal 也不会卡住。
213
218
  * 运行时与评测单步回放(`evals/step-replay.ts`)、评委共用。
214
219
  */
215
- export declare function consumeModelStream(provider: ModelProvider, request: ModelRequest, idleMs: number, signal: AbortSignal, onDelta: (ev: Exclude<ModelStreamEvent, {
220
+ export declare function consumeModelStream(provider: BoundProvider, request: ModelRequest, idleMs: number, signal: AbortSignal, onDelta: (ev: Exclude<ModelStreamEvent, {
216
221
  type: "message_complete";
217
222
  }>) => void): Promise<StreamOutcome>;
@@ -32,8 +32,11 @@ export const TOOLS_AVAILABLE_AGAIN = "All previously unavailable tools are avail
32
32
  export function toolsUnavailableReminder(unavailable) {
33
33
  return `${TOOLS_UNAVAILABLE_PREFIX}${unavailable.map((u) => `${u.ref} (${u.reason})`).join(", ")}`;
34
34
  }
35
- /** `run_failed` message of a model request denied by a policy hook (user-facing, never model-visible). */
36
- const modelDeniedText = (plugin, reason) => `Model request blocked by the "${plugin}" policy hook: ${reason}`;
35
+ /**
36
+ * `run_failed` message of a model request denied by a policy hook (user-facing, never model-visible);
37
+ * also the message of the `model.hook_denied` error a denied `ctx.models.embed` call rejects with.
38
+ */
39
+ export const modelDeniedText = (plugin, reason) => `Model request blocked by the "${plugin}" policy hook: ${reason}`;
37
40
  /** 可重试错误在同一模型上重试前的默认等待(供应商未给 retryAfterMs 时)。 */
38
41
  const DEFAULT_RETRY_DELAY_MS = 1000;
39
42
  /**
@@ -155,7 +158,8 @@ wrapUpReason) {
155
158
  // a skills catalog snapshot (Ruling M17; an empty one too) or a person's skill invocation in the
156
159
  // log → Skill is offered (see skillLoadOffered)
157
160
  const resolved = await deps.tools.forAgent(input.orgId, {
158
- tools: input.agent.tools ?? [],
161
+ disabledTools: input.agent.disabledTools,
162
+ subagentTools: input.agent.subagentTools,
159
163
  subagents: input.agent.subagents,
160
164
  child: input.parent !== undefined || input.parentRunId !== undefined || input.subagent === true,
161
165
  forkChild: input.parent?.forSkill === true,
@@ -531,7 +535,7 @@ async function maybeCompact(deps, input, events, runtime, tools) {
531
535
  let provider;
532
536
  let info;
533
537
  try {
534
- ({ provider, info } = await deps.registry.resolve(input.agent.model));
538
+ ({ provider, info } = await deps.registry.resolve(input.orgId, input.agent.model));
535
539
  }
536
540
  catch (err) {
537
541
  deps.log.warn("compaction skipped: model unavailable", { model: input.agent.model, err });
@@ -701,7 +705,10 @@ function mergeLocal(events, written) {
701
705
  * 每次尝试解析出模型后、写 `model_call` 之前写本步的尾部提醒(均按本步幂等,只写一次):所用模型不支持工具而本步有工具
702
706
  * → {@link TOOLS_UNSUPPORTED_REMINDER};然后是轮次提醒或收尾提醒(收尾提醒因此位于请求末尾)。
703
707
  * 每次实际尝试写自己的 `model_call`(attempt 从 1 连续递增,跳过的不计);重试前经 sink 发 `step_reset`。
704
- * 不可重试的失败或梯子用尽 → `RunError`。
708
+ * 不可重试的失败或梯子用尽 → `RunError`; except that the agent's own model failing to resolve as
709
+ * `agent.model_unavailable` (gone from the list, disabled since the agent was saved, its provider
710
+ * not configured in the org: spec B §5.3) goes straight to `agent.fallback` when there is one,
711
+ * without the same-model retry.
705
712
  */
706
713
  async function ladder(deps, input, events, runtime, tools, wrapUpReason, streamed) {
707
714
  const { conversationId, runId, step, signal, sink, agent } = input;
@@ -719,12 +726,16 @@ async function ladder(deps, input, events, runtime, tools, wrapUpReason, streame
719
726
  if (agent.fallback)
720
727
  rungs.push({ ref: agent.fallback, fallback: true });
721
728
  let last;
729
+ /** The agent's model did not resolve (`agent.model_unavailable`): only the fallback is left. */
730
+ let mainUnavailable = false;
722
731
  let attempt = 0;
723
732
  // hooks fire only for chat runs that have a registry (eval replays omit it, P-18)
724
733
  const scope = hookScope(deps.hooks, input);
725
734
  /** 本次尝试发出的请求里带了字节的附件(供应商拒收时写 media_excluded)。 */
726
735
  let sentMedia = [];
727
736
  for (const rung of rungs) {
737
+ if (mainUnavailable && !rung.fallback)
738
+ continue;
728
739
  if (last && !rung.fallback && (last.retryAfterMs ?? 0) > MAX_RETRY_AFTER_MS) {
729
740
  deps.log.warn("model retry skipped: suggested wait exceeds cap", {
730
741
  conversationId,
@@ -744,8 +755,11 @@ async function ladder(deps, input, events, runtime, tools, wrapUpReason, streame
744
755
  sentMedia = [];
745
756
  /** When the request went out (model.response fires only for sent requests). */
746
757
  let sentAt;
758
+ /** Whether this attempt resolved its model (a failure before it is a resolve failure). */
759
+ let resolved = false;
747
760
  try {
748
- const { provider, info } = await deps.registry.resolve(rung.ref);
761
+ const { provider, info } = await deps.registry.resolve(input.orgId, rung.ref);
762
+ resolved = true;
749
763
  if (tools.list.length > 0 && !info.capabilities.tools) {
750
764
  evs = await appendLocal(deps.eventLog, conversationId, evs, {
751
765
  type: "reminder",
@@ -886,6 +900,16 @@ async function ladder(deps, input, events, runtime, tools, wrapUpReason, streame
886
900
  retryable: f.retryable,
887
901
  error: f.message,
888
902
  });
903
+ if (!resolved &&
904
+ !rung.fallback &&
905
+ agent.fallback &&
906
+ err instanceof ApiError &&
907
+ !(err instanceof ProviderListError) &&
908
+ err.code === "agent.model_unavailable") {
909
+ mainUnavailable = true;
910
+ last = f;
911
+ continue;
912
+ }
889
913
  if (!f.retryable) {
890
914
  if (REJECTS_MEDIA.has(f.code) && sentMedia.length > 0) {
891
915
  // 记录失败不能掩盖原来的失败码:只记 warn,本次运行照常以原错误失败