@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
@@ -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
+ }
@@ -158,7 +158,8 @@ wrapUpReason) {
158
158
  // a skills catalog snapshot (Ruling M17; an empty one too) or a person's skill invocation in the
159
159
  // log → Skill is offered (see skillLoadOffered)
160
160
  const resolved = await deps.tools.forAgent(input.orgId, {
161
- tools: input.agent.tools ?? [],
161
+ disabledTools: input.agent.disabledTools,
162
+ subagentTools: input.agent.subagentTools,
162
163
  subagents: input.agent.subagents,
163
164
  child: input.parent !== undefined || input.parentRunId !== undefined || input.subagent === true,
164
165
  forkChild: input.parent?.forSkill === true,
@@ -38,6 +38,11 @@ export const LIST_FAILURE_TTL_SECONDS = 15;
38
38
  * config digest): the list is re-read every {@link MODELS_TTL_SECONDS}, the warn is not.
39
39
  */
40
40
  const DROPPED_WARN_TTL_SECONDS = 24 * 3600;
41
+ /**
42
+ * The shape of a cached model list. 2: every entry carries its normalised `kind` (model platform
43
+ * providers); a format-1 entry has none, and a kernel reading it found no chat model at all.
44
+ */
45
+ const MODELS_CACHE_FORMAT = 2;
41
46
  /**
42
47
  * The model list's cache key (`@Cacheable` stores it as `cache:<key>`). It carries the provider's
43
48
  * contract major: after a plugin moves from `@1` to `@2` it never reads the list written through
@@ -47,8 +52,10 @@ const DROPPED_WARN_TTL_SECONDS = 24 * 3600;
47
52
  * config change (models added or removed) every replica validates the new list at once instead of
48
53
  * waiting for the old entry's TTL. The digest is only a hash, never config text (no secret in the
49
54
  * key). Old keys expire by TTL. Entries without a version / digest (test doubles) use `-`.
55
+ * `f<n>` is the shape of the cached entry ({@link MODELS_CACHE_FORMAT}): a kernel that changes what
56
+ * it caches bumps it, so during a rolling upgrade it never reads a list an older kernel wrote.
50
57
  */
51
- const modelsKey = (p, hash) => `capk:models:${p.plugin}:v${p.major}:${p.version ?? "-"}:${hash ?? "-"}`;
58
+ const modelsKey = (p, hash) => `capk:models:${p.plugin}:v${p.major}:f${MODELS_CACHE_FORMAT}:${p.version ?? "-"}:${hash ?? "-"}`;
52
59
  /** 列表视图的失败标记({@link LIST_FAILURE_TTL_SECONDS}),与模型列表同样按版本与配置摘要区分。 */
53
60
  const listFailedKey = (p, hash) => `capk:models-failed:${p.plugin}:v${p.major}:${p.version ?? "-"}:${hash ?? "-"}`;
54
61
  const droppedKey = (plugin, hash, model) => `capk:models-dropped:${plugin}:${hash ?? "-"}:${model}`;
@@ -0,0 +1,65 @@
1
+ import type { AgentDefinition } from "../agents/definition.js";
2
+ import { EventLog } from "../conversations/event-log.js";
3
+ import type { KernelSchemaDb } from "../db/kernel-schema.js";
4
+ import { KernelDb } from "../infra/database/kernel-db.js";
5
+ import { TransactionHost } from "../infra/database/transaction-host.js";
6
+ /**
7
+ * Optional provider: the clock run start reads the date from and the `CurrentTime` builtin reads
8
+ * the time from (default `Date.now`; tests).
9
+ */
10
+ export declare const RUN_CONTEXT_CLOCK: unique symbol;
11
+ /** The idem key of a run's `run_context` (one per run at most). */
12
+ export declare const runContextIdemKey: (runId: string) => string;
13
+ /** What a run start tells {@link RunContextService.record}. */
14
+ export interface RunContextInput {
15
+ orgId: string;
16
+ conversationId: string;
17
+ runId: string;
18
+ /** The run's boundary: its trigger message (or the finish / delivery that woke it). */
19
+ triggerSeq: number;
20
+ /** The run's effective definition (a root run's agent version; a sub-agent's frozen one). */
21
+ agent: AgentDefinition;
22
+ /** A sub-agent run: the parent call that dispatched it and the child's roster name. */
23
+ subagent?: {
24
+ parentConversationId: string;
25
+ parentRunId: string;
26
+ /** The roster name (`subagent_started.agentType`), or the forked skill's name. */
27
+ name: string;
28
+ };
29
+ }
30
+ /**
31
+ * Run start's run context (spec 2026-11-08-run-context-design §5): compares the facts the run
32
+ * would show the model (its agent's name and description, the org's name, today's date, the time
33
+ * zone and language of the person whose message started it; for a sub-agent who dispatched it)
34
+ * with the fold of the conversation's `run_context` events, and appends only what differs (the
35
+ * first time: everything). Lazy: a rename writes nothing anywhere; the next run notices.
36
+ */
37
+ export declare class RunContextService {
38
+ private readonly db;
39
+ private readonly eventLog;
40
+ readonly txHost: TransactionHost;
41
+ private readonly now;
42
+ constructor(db: KernelDb, eventLog: Pick<EventLog, "appendIn" | "notify">, txHost: TransactionHost, now?: () => number);
43
+ private clock;
44
+ /** Records the run's context (see the class) and notifies after the commit. */
45
+ record(input: RunContextInput): Promise<void>;
46
+ /**
47
+ * One transaction under the conversation row lock (as `lockLatestCatalog`): fold, read the
48
+ * current values, append when something differs, with the idem key `run_context:<runId>` (a
49
+ * retried run start finds its event, or finds nothing changed). Returns the seq written.
50
+ */
51
+ private append;
52
+ /** A root run: agent, org, and the date, zone and language of the run's person (§3.4). */
53
+ private rootContext;
54
+ /**
55
+ * A sub-agent run (spec §6): its roster name, who dispatched it (the parent agent's name and
56
+ * the person the parent works for), and the parent's date and zone; no org, no language.
57
+ */
58
+ private childContext;
59
+ }
60
+ /**
61
+ * The time zone a conversation's run context holds now (the latest `run_context` with a
62
+ * `timeZone`, as the fold reads it), else the org default (§3.3), else UTC. The `CurrentTime`
63
+ * builtin's default zone.
64
+ */
65
+ export declare function conversationTimeZone(t: KernelSchemaDb, orgId: string, conversationId: string): Promise<string>;
@@ -0,0 +1,220 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
8
+ return function (target, key) { decorator(target, key, paramIndex); }
9
+ };
10
+ import { Inject, Injectable, Optional } from "@nestjs/common";
11
+ import { sql } from "kysely";
12
+ import { EventLog } from "../conversations/event-log.js";
13
+ import { KernelDb } from "../infra/database/kernel-db.js";
14
+ import { TransactionHost } from "../infra/database/transaction-host.js";
15
+ import { Transactional } from "../infra/database/transactional.decorator.js";
16
+ import { readOrgSettings } from "../orgs/settings.service.js";
17
+ import { isTimeZone } from "../time-zone.js";
18
+ import { currentRunContext, dateIn, runContextChange, sanitizeSenderName, snapshotDescription, } from "./context/run-context.js";
19
+ /**
20
+ * Optional provider: the clock run start reads the date from and the `CurrentTime` builtin reads
21
+ * the time from (default `Date.now`; tests).
22
+ */
23
+ export const RUN_CONTEXT_CLOCK = Symbol("RUN_CONTEXT_CLOCK");
24
+ /** The idem key of a run's `run_context` (one per run at most). */
25
+ export const runContextIdemKey = (runId) => `run_context:${runId}`;
26
+ const cut = (s, max) => [...s].slice(0, max).join("");
27
+ /**
28
+ * Run start's run context (spec 2026-11-08-run-context-design §5): compares the facts the run
29
+ * would show the model (its agent's name and description, the org's name, today's date, the time
30
+ * zone and language of the person whose message started it; for a sub-agent who dispatched it)
31
+ * with the fold of the conversation's `run_context` events, and appends only what differs (the
32
+ * first time: everything). Lazy: a rename writes nothing anywhere; the next run notices.
33
+ */
34
+ let RunContextService = class RunContextService {
35
+ db;
36
+ eventLog;
37
+ txHost;
38
+ now;
39
+ constructor(db, eventLog, txHost, now = Date.now) {
40
+ this.db = db;
41
+ this.eventLog = eventLog;
42
+ this.txHost = txHost;
43
+ this.now = now;
44
+ }
45
+ clock() {
46
+ return new Date(this.now());
47
+ }
48
+ /** Records the run's context (see the class) and notifies after the commit. */
49
+ async record(input) {
50
+ const seq = await this.append(input);
51
+ if (seq !== null)
52
+ await this.eventLog.notify(input.conversationId, seq);
53
+ }
54
+ /**
55
+ * One transaction under the conversation row lock (as `lockLatestCatalog`): fold, read the
56
+ * current values, append when something differs, with the idem key `run_context:<runId>` (a
57
+ * retried run start finds its event, or finds nothing changed). Returns the seq written.
58
+ */
59
+ async append(input) {
60
+ const t = this.db.db;
61
+ await t
62
+ .selectFrom("conversations")
63
+ .select("id")
64
+ .where("id", "=", input.conversationId)
65
+ .forUpdate()
66
+ .executeTakeFirst();
67
+ const prev = await foldOf(t, input.conversationId);
68
+ const next = input.subagent === undefined
69
+ ? await this.rootContext(t, input)
70
+ : await this.childContext(t, input, input.subagent);
71
+ const change = runContextChange(prev, next);
72
+ if (change === null)
73
+ return null;
74
+ const written = await this.eventLog.appendIn(input.conversationId, [
75
+ {
76
+ type: "run_context",
77
+ runId: input.runId,
78
+ idemKey: runContextIdemKey(input.runId),
79
+ payload: change,
80
+ },
81
+ ]);
82
+ return Math.max(...written.map((e) => e.seq));
83
+ }
84
+ /** A root run: agent, org, and the date, zone and language of the run's person (§3.4). */
85
+ async rootContext(t, input) {
86
+ const org = await t
87
+ .selectFrom("orgs")
88
+ .select("name")
89
+ .where("id", "=", input.orgId)
90
+ .executeTakeFirst();
91
+ const settings = await readOrgSettings(t, input.orgId);
92
+ // the person whose message started the run: the latest message at or before the trigger that
93
+ // recorded a zone (a wake run has no message of its own)
94
+ const person = await t
95
+ .selectFrom("conversation_events")
96
+ .select([
97
+ sql `payload->>'timeZone'`.as("timeZone"),
98
+ sql `payload->>'locale'`.as("locale"),
99
+ ])
100
+ .where("conversation_id", "=", input.conversationId)
101
+ .where("type", "=", "user_message")
102
+ .where("seq", "<=", String(input.triggerSeq))
103
+ .where(sql `payload ? 'timeZone'`)
104
+ .orderBy("seq", "desc")
105
+ .limit(1)
106
+ .executeTakeFirst();
107
+ const zone = person?.timeZone != null && isTimeZone(person.timeZone)
108
+ ? person.timeZone
109
+ : (settings.timeZone ?? "UTC");
110
+ const locale = person?.locale === "zh" || person?.locale === "en" ? person.locale : settings.locale;
111
+ const description = snapshotDescription(input.agent.description);
112
+ return {
113
+ agent: { name: input.agent.name, ...(description !== undefined && { description }) },
114
+ ...(org !== undefined && org.name.trim() !== "" && { org: { name: cut(org.name, 200) } }),
115
+ date: dateIn(this.clock(), zone),
116
+ timeZone: zone,
117
+ locale,
118
+ };
119
+ }
120
+ /**
121
+ * A sub-agent run (spec §6): its roster name, who dispatched it (the parent agent's name and
122
+ * the person the parent works for), and the parent's date and zone; no org, no language.
123
+ */
124
+ async childContext(t, input, child) {
125
+ const parent = await foldOf(t, child.parentConversationId);
126
+ const parentAgent = parent.agent?.name ?? (await parentDefinitionName(t, child.parentRunId)) ?? "agent";
127
+ const person = parent.dispatchedBy?.person ??
128
+ (await latestSenderName(t, child.parentConversationId)) ??
129
+ (await triggerName(t, child.parentRunId)) ??
130
+ "a person";
131
+ const zone = parent.timeZone ?? (await readOrgSettings(t, input.orgId)).timeZone ?? "UTC";
132
+ return {
133
+ agent: { name: cut(child.name, 130) },
134
+ dispatchedBy: { agent: cut(parentAgent, 130), person },
135
+ date: dateIn(this.clock(), zone),
136
+ timeZone: zone,
137
+ };
138
+ }
139
+ };
140
+ __decorate([
141
+ Transactional()
142
+ ], RunContextService.prototype, "append", null);
143
+ RunContextService = __decorate([
144
+ Injectable(),
145
+ __param(0, Inject(KernelDb)),
146
+ __param(1, Inject(EventLog)),
147
+ __param(2, Inject(TransactionHost)),
148
+ __param(3, Optional()),
149
+ __param(3, Inject(RUN_CONTEXT_CLOCK))
150
+ ], RunContextService);
151
+ export { RunContextService };
152
+ /**
153
+ * The time zone a conversation's run context holds now (the latest `run_context` with a
154
+ * `timeZone`, as the fold reads it), else the org default (§3.3), else UTC. The `CurrentTime`
155
+ * builtin's default zone.
156
+ */
157
+ export async function conversationTimeZone(t, orgId, conversationId) {
158
+ const row = await t
159
+ .selectFrom("conversation_events")
160
+ .select(sql `payload->>'timeZone'`.as("timeZone"))
161
+ .where("conversation_id", "=", conversationId)
162
+ .where("type", "=", "run_context")
163
+ .where(sql `payload ? 'timeZone'`)
164
+ .orderBy("seq", "desc")
165
+ .limit(1)
166
+ .executeTakeFirst();
167
+ if (row?.timeZone != null && isTimeZone(row.timeZone))
168
+ return row.timeZone;
169
+ const zone = (await readOrgSettings(t, orgId)).timeZone;
170
+ return zone !== undefined && isTimeZone(zone) ? zone : "UTC";
171
+ }
172
+ /** The fold of a conversation's `run_context` events (read inside the caller's transaction). */
173
+ async function foldOf(t, conversationId) {
174
+ const rows = await t
175
+ .selectFrom("conversation_events")
176
+ .select(["seq", "payload"])
177
+ .where("conversation_id", "=", conversationId)
178
+ .where("type", "=", "run_context")
179
+ .orderBy("seq", "asc")
180
+ .execute();
181
+ return currentRunContext(rows.map((r) => ({ type: "run_context", seq: Number(r.seq), payload: r.payload })));
182
+ }
183
+ /** The name in the parent run's agent version (a parent logged before run contexts existed). */
184
+ async function parentDefinitionName(t, runId) {
185
+ const row = await t
186
+ .selectFrom("runs")
187
+ .innerJoin("conversations", "conversations.id", "runs.conversation_id")
188
+ .innerJoin("agent_versions as v", (j) => j
189
+ .onRef("v.agent_id", "=", "conversations.agent_id")
190
+ .onRef("v.version", "=", "runs.agent_version"))
191
+ .select(sql `v.definition->>'name'`.as("name"))
192
+ .where("runs.id", "=", runId)
193
+ .executeTakeFirst();
194
+ return row?.name ?? undefined;
195
+ }
196
+ /** The latest sender name in a conversation's log (the person the conversation works for). */
197
+ async function latestSenderName(t, conversationId) {
198
+ const row = await t
199
+ .selectFrom("conversation_events")
200
+ .select(sql `payload->'sender'->>'name'`.as("name"))
201
+ .where("conversation_id", "=", conversationId)
202
+ .where("type", "=", "user_message")
203
+ .where(sql `payload ? 'sender'`)
204
+ .orderBy("seq", "desc")
205
+ .limit(1)
206
+ .executeTakeFirst();
207
+ const name = row?.name == null ? "" : sanitizeSenderName(row.name);
208
+ return name === "" ? undefined : name;
209
+ }
210
+ /** The display name of the account that triggered a run. */
211
+ async function triggerName(t, runId) {
212
+ const row = await t
213
+ .selectFrom("runs")
214
+ .innerJoin("accounts", "accounts.id", "runs.trigger_account_id")
215
+ .select("accounts.display_name")
216
+ .where("runs.id", "=", runId)
217
+ .executeTakeFirst();
218
+ const name = row === undefined ? "" : sanitizeSenderName(row.display_name);
219
+ return name === "" ? undefined : name;
220
+ }
@@ -14,6 +14,7 @@ import { KyselyCheckpointSaver } from "./checkpointer.js";
14
14
  import { ConversationLock } from "./conversation-lock.js";
15
15
  import { ProviderRegistry } from "./providers.js";
16
16
  import { type OrgQuota } from "./quota.js";
17
+ import { RunContextService } from "./run-context.service.js";
17
18
  import { RunDrafts } from "./run-drafts.js";
18
19
  import { RunFinish } from "./run-finish.js";
19
20
  import type { RunJobData } from "./run-jobs.js";
@@ -63,6 +64,8 @@ export declare class RunWorker {
63
64
  private readonly models;
64
65
  /** Run start's skills catalog snapshot (reads the pinned skills' bodies, phase B). */
65
66
  private readonly skillsCatalog;
67
+ /** Run start's run context (run context spec §5): who the agent is, the day, the person. */
68
+ private readonly runContext;
66
69
  /**
67
70
  * In the terminal transaction of every run: writes its open `Agent` call results
68
71
  * (`stopOpenAgentCalls`; a no-op without dispatches); `fire` runs their observe hooks after the
@@ -96,6 +99,8 @@ export declare class RunWorker {
96
99
  models: Pick<ProviderRegistry, "resolve">,
97
100
  /** Run start's skills catalog snapshot (reads the pinned skills' bodies, phase B). */
98
101
  skillsCatalog: Pick<SkillsCatalogService, "record">,
102
+ /** Run start's run context (run context spec §5): who the agent is, the day, the person. */
103
+ runContext: Pick<RunContextService, "record">,
99
104
  /**
100
105
  * In the terminal transaction of every run: writes its open `Agent` call results
101
106
  * (`stopOpenAgentCalls`; a no-op without dispatches); `fire` runs their observe hooks after the