@capybara-hq/kernel 0.1.0-rc.2 → 0.1.0-rc.4

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 (312) hide show
  1. package/dist/admin/admin.controller.d.ts +9 -4
  2. package/dist/admin/admin.controller.js +13 -4
  3. package/dist/admin/extensions.controller.d.ts +8 -1
  4. package/dist/admin/extensions.controller.js +22 -2
  5. package/dist/agents/agent-lookup.d.ts +3 -0
  6. package/dist/agents/agent-lookup.js +20 -2
  7. package/dist/agents/agent-profile.service.d.ts +29 -0
  8. package/dist/agents/agent-profile.service.js +117 -0
  9. package/dist/agents/agents.controller.d.ts +93 -3
  10. package/dist/agents/agents.controller.js +114 -4
  11. package/dist/agents/agents.module.js +6 -2
  12. package/dist/agents/agents.service.d.ts +13 -5
  13. package/dist/agents/agents.service.js +49 -13
  14. package/dist/agents/definition.d.ts +35 -8
  15. package/dist/agents/definition.js +203 -17
  16. package/dist/agents/instruction-files.d.ts +60 -0
  17. package/dist/agents/instruction-files.js +111 -0
  18. package/dist/agents/models.controller.d.ts +9 -3
  19. package/dist/agents/models.controller.js +19 -4
  20. package/dist/agents/profile.d.ts +96 -0
  21. package/dist/agents/profile.js +51 -0
  22. package/dist/agents/readiness.controller.d.ts +26 -0
  23. package/dist/agents/readiness.controller.js +56 -0
  24. package/dist/agents/templates.js +20 -5
  25. package/dist/background/background.controller.d.ts +38 -0
  26. package/dist/background/background.controller.js +87 -0
  27. package/dist/background/background.module.d.ts +10 -0
  28. package/dist/background/background.module.js +32 -0
  29. package/dist/background/finish.d.ts +43 -0
  30. package/dist/background/finish.js +94 -0
  31. package/dist/background/launch-lock.d.ts +14 -0
  32. package/dist/background/launch-lock.js +39 -0
  33. package/dist/background/launch.d.ts +36 -0
  34. package/dist/background/launch.js +70 -0
  35. package/dist/background/poll.job.d.ts +53 -0
  36. package/dist/background/poll.job.js +182 -0
  37. package/dist/background/render.d.ts +23 -0
  38. package/dist/background/render.js +48 -0
  39. package/dist/background/session.d.ts +37 -0
  40. package/dist/background/session.js +66 -0
  41. package/dist/background/status.d.ts +35 -0
  42. package/dist/background/status.js +57 -0
  43. package/dist/background/stop.d.ts +62 -0
  44. package/dist/background/stop.js +225 -0
  45. package/dist/background/store.d.ts +150 -0
  46. package/dist/background/store.js +351 -0
  47. package/dist/background/store.module.d.ts +6 -0
  48. package/dist/background/store.module.js +22 -0
  49. package/dist/background/tasks.service.d.ts +67 -0
  50. package/dist/background/tasks.service.js +186 -0
  51. package/dist/background/wake-rules.d.ts +57 -0
  52. package/dist/background/wake-rules.js +83 -0
  53. package/dist/background/wake.d.ts +28 -0
  54. package/dist/background/wake.js +57 -0
  55. package/dist/catalog/catalog-content.js +4 -1
  56. package/dist/catalog/claude/agents.js +15 -10
  57. package/dist/catalog/marketplaces.service.d.ts +1 -1
  58. package/dist/catalog/plugin-import.js +1 -1
  59. package/dist/catalog/plugin-upgrade.js +1 -1
  60. package/dist/channels/cards.d.ts +8 -2
  61. package/dist/channels/cards.js +17 -9
  62. package/dist/channels/connections.service.d.ts +16 -1
  63. package/dist/channels/connections.service.js +38 -4
  64. package/dist/channels/threads.d.ts +5 -0
  65. package/dist/channels/threads.js +8 -0
  66. package/dist/config/schema.d.ts +18 -0
  67. package/dist/config/schema.js +104 -2
  68. package/dist/conversations/access.js +2 -0
  69. package/dist/conversations/artifacts.d.ts +1 -1
  70. package/dist/conversations/artifacts.js +1 -1
  71. package/dist/conversations/attachments.service.d.ts +30 -0
  72. package/dist/conversations/attachments.service.js +130 -5
  73. package/dist/conversations/conversations.controller.d.ts +36 -5
  74. package/dist/conversations/conversations.controller.js +62 -12
  75. package/dist/conversations/conversations.module.js +3 -0
  76. package/dist/conversations/conversations.service.d.ts +44 -2
  77. package/dist/conversations/conversations.service.js +140 -12
  78. package/dist/conversations/event-log.d.ts +12 -1
  79. package/dist/conversations/event-log.js +29 -1
  80. package/dist/conversations/events.d.ts +81 -3
  81. package/dist/conversations/events.js +83 -16
  82. package/dist/conversations/queue.d.ts +3 -1
  83. package/dist/conversations/queue.js +13 -2
  84. package/dist/conversations/queue.service.js +3 -1
  85. package/dist/conversations/titles.d.ts +7 -0
  86. package/dist/conversations/titles.js +15 -0
  87. package/dist/db/kernel-schema.d.ts +60 -4
  88. package/dist/db/pool.d.ts +5 -0
  89. package/dist/db/pool.js +3 -0
  90. package/dist/errors.d.ts +8 -0
  91. package/dist/errors.js +8 -0
  92. package/dist/evals/recorded-tools.d.ts +27 -1
  93. package/dist/evals/recorded-tools.js +85 -10
  94. package/dist/evals/run-replay.d.ts +10 -2
  95. package/dist/evals/run-replay.js +49 -12
  96. package/dist/evals/step-replay.js +12 -6
  97. package/dist/evals/trajectory.d.ts +2 -2
  98. package/dist/evals/trajectory.js +1 -1
  99. package/dist/extensions/admin-ops.js +2 -0
  100. package/dist/extensions/admin-view.d.ts +3 -1
  101. package/dist/extensions/admin-view.js +10 -2
  102. package/dist/extensions/blobs.js +1 -0
  103. package/dist/extensions/config-issues.d.ts +13 -1
  104. package/dist/extensions/config-issues.js +22 -5
  105. package/dist/extensions/config-json-schema.d.ts +43 -7
  106. package/dist/extensions/config-json-schema.js +124 -58
  107. package/dist/extensions/deployment-config-store.d.ts +6 -0
  108. package/dist/extensions/deployment-config.d.ts +50 -3
  109. package/dist/extensions/deployment-config.js +125 -28
  110. package/dist/extensions/display-name.d.ts +22 -0
  111. package/dist/extensions/display-name.js +77 -0
  112. package/dist/extensions/extensions.module.js +6 -0
  113. package/dist/extensions/host.d.ts +26 -1
  114. package/dist/extensions/host.js +82 -9
  115. package/dist/extensions/org-config.controller.d.ts +11 -3
  116. package/dist/extensions/org-config.controller.js +14 -6
  117. package/dist/extensions/org-config.d.ts +6 -0
  118. package/dist/extensions/org-config.js +12 -13
  119. package/dist/extensions/package.d.ts +14 -1
  120. package/dist/extensions/package.js +51 -2
  121. package/dist/extensions/permission-view.d.ts +3 -0
  122. package/dist/extensions/point-defaults.controller.d.ts +34 -0
  123. package/dist/extensions/point-defaults.controller.js +71 -0
  124. package/dist/extensions/point-defaults.d.ts +64 -0
  125. package/dist/extensions/point-defaults.js +206 -0
  126. package/dist/extensions/registry.d.ts +1 -1
  127. package/dist/extensions/registry.js +2 -0
  128. package/dist/http/api.module.js +8 -0
  129. package/dist/http/nest-logger.d.ts +6 -5
  130. package/dist/http/nest-logger.js +24 -10
  131. package/dist/identity/auth.controller.js +9 -5
  132. package/dist/identity/cookies.d.ts +20 -5
  133. package/dist/identity/cookies.js +44 -6
  134. package/dist/identity/me.controller.d.ts +5 -1
  135. package/dist/identity/me.controller.js +12 -3
  136. package/dist/identity/sessions.d.ts +12 -0
  137. package/dist/identity/sessions.js +45 -0
  138. package/dist/identity/settings.js +1 -1
  139. package/dist/index.d.ts +1 -1
  140. package/dist/infra/config/kernel-config.service.js +6 -0
  141. package/dist/infra/database/database.module.js +1 -0
  142. package/dist/infra/events/kernel-events.d.ts +8 -0
  143. package/dist/infra/lifecycle/process-guards.js +4 -0
  144. package/dist/infra/logging/logging.module.d.ts +4 -2
  145. package/dist/infra/logging/logging.module.js +24 -6
  146. package/dist/infra/queue/redis-connection.d.ts +6 -0
  147. package/dist/infra/queue/redis-connection.js +7 -0
  148. package/dist/infra/redis/redis.module.js +6 -2
  149. package/dist/infra/tokens.d.ts +6 -1
  150. package/dist/infra/tokens.js +6 -1
  151. package/dist/lifecycle/kernel-lifecycle.js +5 -0
  152. package/dist/log.d.ts +13 -1
  153. package/dist/log.js +93 -17
  154. package/dist/models/purposes.d.ts +23 -0
  155. package/dist/models/purposes.js +31 -10
  156. package/dist/orgs/offboarding.d.ts +3 -1
  157. package/dist/orgs/offboarding.js +26 -16
  158. package/dist/orgs/settings.service.d.ts +7 -2
  159. package/dist/orgs/settings.service.js +15 -4
  160. package/dist/roles/worker.module.js +6 -0
  161. package/dist/runtime/context/build.d.ts +15 -13
  162. package/dist/runtime/context/build.js +45 -27
  163. package/dist/runtime/context/claude-tools.d.ts +3 -1
  164. package/dist/runtime/context/claude-tools.js +12 -12
  165. package/dist/runtime/context/compaction.js +4 -0
  166. package/dist/runtime/context/legacy-text.d.ts +22 -0
  167. package/dist/runtime/context/legacy-text.js +37 -0
  168. package/dist/runtime/context/skills.d.ts +29 -11
  169. package/dist/runtime/context/skills.js +37 -30
  170. package/dist/runtime/langgraph-loop.js +3 -2
  171. package/dist/runtime/loop.d.ts +5 -4
  172. package/dist/runtime/maintenance.d.ts +4 -2
  173. package/dist/runtime/maintenance.js +17 -5
  174. package/dist/runtime/model-call.d.ts +17 -1
  175. package/dist/runtime/model-call.js +4 -3
  176. package/dist/runtime/providers.d.ts +6 -0
  177. package/dist/runtime/providers.js +8 -0
  178. package/dist/runtime/run-finish.d.ts +1 -1
  179. package/dist/runtime/run-queue.d.ts +28 -5
  180. package/dist/runtime/run-queue.js +131 -35
  181. package/dist/runtime/run-worker.d.ts +2 -2
  182. package/dist/runtime/run-worker.js +20 -7
  183. package/dist/runtime/runtime.module.js +8 -3
  184. package/dist/runtime/step-log.d.ts +6 -0
  185. package/dist/runtime/step-log.js +16 -2
  186. package/dist/runtime/subagents/definition.d.ts +1 -6
  187. package/dist/runtime/subagents/definition.js +14 -13
  188. package/dist/runtime/subagents/dispatch.d.ts +2 -2
  189. package/dist/runtime/subagents/dispatch.js +2 -2
  190. package/dist/runtime/subagents/org-agents.js +2 -1
  191. package/dist/runtime/subagents/roster.d.ts +1 -1
  192. package/dist/runtime/subagents/roster.js +1 -1
  193. package/dist/runtime/subagents/skill-fork.d.ts +2 -2
  194. package/dist/runtime/subagents/skill-fork.js +2 -2
  195. package/dist/runtime/subagents/subagents.service.d.ts +3 -3
  196. package/dist/runtime/subagents/subagents.service.js +3 -3
  197. package/dist/runtime/usage-report.d.ts +2 -1
  198. package/dist/runtime/usage-report.js +2 -1
  199. package/dist/runtime/waits.d.ts +13 -7
  200. package/dist/runtime/waits.js +42 -16
  201. package/dist/sandbox/sandbox.module.js +6 -1
  202. package/dist/sandbox/sandbox.service.d.ts +61 -3
  203. package/dist/sandbox/sandbox.service.js +141 -7
  204. package/dist/skills/catalog.d.ts +4 -4
  205. package/dist/skills/catalog.js +4 -4
  206. package/dist/skills/changes.service.d.ts +2 -2
  207. package/dist/skills/changes.service.js +5 -4
  208. package/dist/skills/invocation-keys.d.ts +1 -1
  209. package/dist/skills/invocation-keys.js +1 -1
  210. package/dist/skills/invoke.d.ts +1 -1
  211. package/dist/skills/invoke.js +5 -4
  212. package/dist/tools/approvals.service.d.ts +6 -0
  213. package/dist/tools/approvals.service.js +21 -1
  214. package/dist/tools/builtin-names.d.ts +91 -0
  215. package/dist/tools/builtin-names.js +143 -0
  216. package/dist/tools/builtins/agent.d.ts +7 -7
  217. package/dist/tools/builtins/agent.js +7 -11
  218. package/dist/tools/builtins/ask-user.d.ts +1 -1
  219. package/dist/tools/builtins/ask-user.js +2 -2
  220. package/dist/tools/builtins/builtin-tools.d.ts +17 -3
  221. package/dist/tools/builtins/builtin-tools.js +36 -4
  222. package/dist/tools/builtins/read-tool-output.d.ts +1 -1
  223. package/dist/tools/builtins/read-tool-output.js +2 -2
  224. package/dist/tools/builtins/sandbox/bash.d.ts +4 -4
  225. package/dist/tools/builtins/sandbox/bash.js +259 -29
  226. package/dist/tools/builtins/sandbox/common.d.ts +30 -7
  227. package/dist/tools/builtins/sandbox/common.js +9 -5
  228. package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
  229. package/dist/tools/builtins/sandbox/deliver.js +12 -12
  230. package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
  231. package/dist/tools/builtins/sandbox/edit.js +41 -30
  232. package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
  233. package/dist/tools/builtins/sandbox/file-state.js +34 -0
  234. package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
  235. package/dist/tools/builtins/sandbox/glob-match.js +1 -1
  236. package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
  237. package/dist/tools/builtins/sandbox/glob.js +4 -4
  238. package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
  239. package/dist/tools/builtins/sandbox/grep.js +147 -30
  240. package/dist/tools/builtins/sandbox/index.d.ts +3 -1
  241. package/dist/tools/builtins/sandbox/index.js +7 -1
  242. package/dist/tools/builtins/sandbox/read.d.ts +2 -2
  243. package/dist/tools/builtins/sandbox/read.js +21 -14
  244. package/dist/tools/builtins/sandbox/task-output.d.ts +63 -0
  245. package/dist/tools/builtins/sandbox/task-output.js +304 -0
  246. package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
  247. package/dist/tools/builtins/sandbox/task-stop.js +112 -0
  248. package/dist/tools/builtins/sandbox/write.d.ts +1 -1
  249. package/dist/tools/builtins/sandbox/write.js +37 -33
  250. package/dist/tools/builtins/skill-load.d.ts +3 -3
  251. package/dist/tools/builtins/skill-load.js +32 -16
  252. package/dist/tools/builtins/skill-write.d.ts +4 -4
  253. package/dist/tools/builtins/skill-write.js +10 -10
  254. package/dist/tools/builtins/tool-search.d.ts +13 -9
  255. package/dist/tools/builtins/tool-search.js +25 -14
  256. package/dist/tools/builtins/web/errors.d.ts +8 -0
  257. package/dist/tools/builtins/web/errors.js +53 -0
  258. package/dist/tools/builtins/web/extract.d.ts +62 -0
  259. package/dist/tools/builtins/web/extract.js +267 -0
  260. package/dist/tools/builtins/web/fetch.d.ts +55 -0
  261. package/dist/tools/builtins/web/fetch.js +174 -0
  262. package/dist/tools/builtins/web/index.d.ts +13 -0
  263. package/dist/tools/builtins/web/index.js +12 -0
  264. package/dist/tools/builtins/web/page-cache.d.ts +25 -0
  265. package/dist/tools/builtins/web/page-cache.js +77 -0
  266. package/dist/tools/builtins/web/search.d.ts +25 -0
  267. package/dist/tools/builtins/web/search.js +209 -0
  268. package/dist/tools/builtins/web/url.d.ts +17 -0
  269. package/dist/tools/builtins/web/url.js +43 -0
  270. package/dist/tools/connectors.service.js +4 -4
  271. package/dist/tools/display-names.d.ts +9 -0
  272. package/dist/tools/display-names.js +24 -0
  273. package/dist/tools/drift.js +5 -5
  274. package/dist/tools/elicitation.js +1 -1
  275. package/dist/tools/info.d.ts +20 -4
  276. package/dist/tools/info.js +55 -32
  277. package/dist/tools/legacy-data.d.ts +34 -0
  278. package/dist/tools/legacy-data.js +76 -0
  279. package/dist/tools/legacy-keys.d.ts +51 -0
  280. package/dist/tools/legacy-keys.js +115 -0
  281. package/dist/tools/naming.d.ts +1 -5
  282. package/dist/tools/naming.js +1 -7
  283. package/dist/tools/oauth/flow-paths.d.ts +1 -1
  284. package/dist/tools/oauth/flow-paths.js +1 -1
  285. package/dist/tools/outputs.js +1 -1
  286. package/dist/tools/pipeline.d.ts +13 -7
  287. package/dist/tools/pipeline.js +112 -39
  288. package/dist/tools/policy.d.ts +1 -14
  289. package/dist/tools/policy.js +13 -19
  290. package/dist/tools/questions.controller.d.ts +1 -1
  291. package/dist/tools/questions.controller.js +1 -1
  292. package/dist/tools/questions.service.d.ts +1 -1
  293. package/dist/tools/registry.d.ts +38 -24
  294. package/dist/tools/registry.js +54 -47
  295. package/dist/tools/resources.d.ts +1 -1
  296. package/dist/tools/resources.js +1 -1
  297. package/dist/tools/tools.module.js +13 -1
  298. package/dist/tools/validate.js +1 -1
  299. package/package.json +3 -3
  300. package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
  301. package/src/migrations/0064_account_last_org.sql +7 -0
  302. package/src/migrations/0065_conversation_archive.sql +8 -0
  303. package/src/migrations/0066_extension_display_name.sql +4 -0
  304. package/src/migrations/0067_agent_profiles.sql +20 -0
  305. package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
  306. package/src/migrations/0069_attachments_agent_idx.sql +3 -0
  307. package/src/migrations/0070_background_tasks.sql +37 -0
  308. package/src/migrations/0071_background_tasks_reserve.sql +6 -0
  309. package/src/migrations/0072_background_tasks_stopping.sql +5 -0
  310. package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
  311. package/dist/tools/builtins/sandbox/names.d.ts +0 -7
  312. package/dist/tools/builtins/sandbox/names.js +0 -20
@@ -1,13 +1,23 @@
1
- /** 加载技能的内置工具名。 */
2
- export const SKILL_LOAD = "skill_load";
1
+ import { SKILL_LOAD } from "../../tools/builtin-names.js";
2
+ export const SKILL_TEXTS = Object.freeze({
3
+ skillsCatalogHeader: "Skills are available in this conversation. A skill is a set of instructions, sometimes with " +
4
+ "scripts or other files, for a specific kind of task. When a task matches a skill's description, " +
5
+ `call ${SKILL_LOAD} with the skill's name to read its instructions before you start; do not guess ` +
6
+ "what a skill says. Available skills:",
7
+ newSkills: `New skills (call ${SKILL_LOAD} with the name to use one):`,
8
+ updatedSkills: `Updated skills (call ${SKILL_LOAD} again before relying on earlier instructions):`,
9
+ currentSkills: "Skills available in this conversation now (this replaces any earlier list of skills; call " +
10
+ `${SKILL_LOAD} with a name to read a skill's instructions):`,
11
+ invokedSkills: (names) => `Skills the user invoked earlier in this conversation: ${names.join(", ")}. Call ${SKILL_LOAD} with a name to read its instructions again.`,
12
+ pinnedSkillsHeader: "Pinned skills: the owner of this agent pinned these skills, so their instructions apply " +
13
+ `throughout this conversation. Follow them without calling ${SKILL_LOAD}; call ${SKILL_LOAD} ` +
14
+ "only to copy a pinned skill's files into the sandbox.",
15
+ });
3
16
  /** 目录开头的说明(system 缓存段里的第一份目录)。 */
4
- export const SKILLS_CATALOG_HEADER = "Skills are available in this conversation. A skill is a set of instructions, sometimes with " +
5
- "scripts or other files, for a specific kind of task. When a task matches a skill's description, " +
6
- `call ${SKILL_LOAD} with the skill's name to read its instructions before you start; do not guess ` +
7
- "what a skill says. Available skills:";
17
+ export const SKILLS_CATALOG_HEADER = SKILL_TEXTS.skillsCatalogHeader;
8
18
  /** 按码点比较名字(与区域设置无关,结果确定)。 */
9
19
  const byName = (a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
10
- /** 目录里每个技能描述最多的码点数(超出确定地截断;`skill_load` 仍返回完整正文)。 */
20
+ /** 目录里每个技能描述最多的码点数(超出确定地截断;`Skill` 仍返回完整正文)。 */
11
21
  export const CATALOG_DESCRIPTION_MAX_CHARS = 300;
12
22
  /** 折叠成一行,按码点截到 {@link CATALOG_DESCRIPTION_MAX_CHARS}。 */
13
23
  function shortDescription(d) {
@@ -21,8 +31,8 @@ function shortDescription(d) {
21
31
  const line = (s) => `- ${s.name}: ${shortDescription(s.description)}`;
22
32
  const lines = (skills) => [...skills].sort(byName).map(line).join("\n");
23
33
  /** 第一份目录(进 system 缓存段),按名字排序。 */
24
- export function skillsCatalogText(skills) {
25
- return `${SKILLS_CATALOG_HEADER}\n${lines(skills)}`;
34
+ export function skillsCatalogText(skills, texts = SKILL_TEXTS) {
35
+ return `${texts.skillsCatalogHeader}\n${lines(skills)}`;
26
36
  }
27
37
  /** 两份快照是否相同(按 id、版本、名字、描述与来源)。顺序无关。 */
28
38
  export function sameSkills(a, b) {
@@ -66,7 +76,7 @@ export function sameSnapshot(a, b) {
66
76
  /**
67
77
  * The catalog differences between two snapshots. `pinnedIds` (the next snapshot's pinned ids, phase
68
78
  * B) are left out of `updated`: a pinned skill's new body is rendered by {@link pinnedChangeText},
69
- * and the pinned header says not to call `skill_load` for it.
79
+ * and the pinned header says not to call `Skill` for it.
70
80
  */
71
81
  function catalogChanges(prev, next, pinnedIds) {
72
82
  const before = new Map(prev.map((s) => [s.id, s]));
@@ -86,14 +96,14 @@ function catalogChanges(prev, next, pinnedIds) {
86
96
  * 试用草稿被拒绝 / 批准了别人的同号版本时,内容变了而版本号可能不变)。
87
97
  * `prev` 为上一份快照(没有为空)。
88
98
  */
89
- export function skillsChangeText(prev, next, pinnedIds) {
99
+ export function skillsChangeText(prev, next, pinnedIds, texts = SKILL_TEXTS) {
90
100
  const { added, updated, removed } = catalogChanges(prev, next, pinnedIds);
91
101
  const parts = ["The skills available in this conversation have changed."];
92
102
  if (added.length > 0) {
93
- parts.push(`New skills (call ${SKILL_LOAD} with the name to use one):\n${lines(added)}`);
103
+ parts.push(`${texts.newSkills}\n${lines(added)}`);
94
104
  }
95
105
  if (updated.length > 0) {
96
- parts.push(`Updated skills (call ${SKILL_LOAD} again before relying on earlier instructions):\n${lines(updated)}`);
106
+ parts.push(`${texts.updatedSkills}\n${lines(updated)}`);
97
107
  }
98
108
  if (removed.length > 0) {
99
109
  parts.push(`Removed skills (no longer available; do not use them): ${[...removed]
@@ -106,22 +116,21 @@ export function skillsChangeText(prev, next, pinnedIds) {
106
116
  return parts.join("\n\n");
107
117
  }
108
118
  /** 压缩摘要之后补上的「当前目录」(与 system 里的第一份不同时):完整列出,替代之前的目录与提醒。 */
109
- export function skillsCurrentText(skills) {
119
+ export function skillsCurrentText(skills, texts = SKILL_TEXTS) {
110
120
  if (skills.length === 0) {
111
121
  return "No skills are available in this conversation now (this replaces any earlier list of skills).";
112
122
  }
113
- return ("Skills available in this conversation now (this replaces any earlier list of skills; call " +
114
- `${SKILL_LOAD} with a name to read a skill's instructions):\n${lines(skills)}`);
123
+ return `${texts.currentSkills}\n${lines(skills)}`;
115
124
  }
116
125
  // ---- Skills a person invoked (phase D spec §4.4; model-visible, English) ----
117
126
  /**
118
127
  * The line restored after a compaction summary whose range holds inline skill invocations
119
128
  * (`names`: distinct, code point order); empty for none. Bodies are not re-injected.
120
129
  */
121
- export function invokedSkillsText(names) {
130
+ export function invokedSkillsText(names, texts = SKILL_TEXTS) {
122
131
  if (names.length === 0)
123
132
  return "";
124
- return `Skills the user invoked earlier in this conversation: ${names.join(", ")}. Call ${SKILL_LOAD} with a name to read its instructions again.`;
133
+ return texts.invokedSkills(names);
125
134
  }
126
135
  /** The distinct names (code point order) of the inline invocations in `events` up to `upToSeq`. */
127
136
  export function invokedSkillNames(events, upToSeq) {
@@ -180,16 +189,14 @@ export function systemSkillsCatalog(events) {
180
189
  }
181
190
  // ---- Pinned skills and the tool-name map (phase B, spec §9.1, §9.4; model-visible, English) ----
182
191
  /** The header of the pinned skills in the system cache segment. */
183
- export const PINNED_SKILLS_HEADER = "Pinned skills: the owner of this agent pinned these skills, so their instructions apply " +
184
- `throughout this conversation. Follow them without calling ${SKILL_LOAD}; call ${SKILL_LOAD} ` +
185
- "only to copy a pinned skill's files into the sandbox.";
192
+ export const PINNED_SKILLS_HEADER = SKILL_TEXTS.pinnedSkillsHeader;
186
193
  /** One pinned skill with its body. */
187
194
  export function pinnedBlock(p) {
188
195
  return `<pinned_skill name="${p.name}" version="${p.version}">\n${p.body.trim()}\n</pinned_skill>`;
189
196
  }
190
197
  /** The pinned skills of the system snapshot (non-empty), after the catalog. */
191
- export function pinnedSystemText(pinned) {
192
- return `${PINNED_SKILLS_HEADER}\n\n${pinned.map(pinnedBlock).join("\n\n")}`;
198
+ export function pinnedSystemText(pinned, texts = SKILL_TEXTS) {
199
+ return `${texts.pinnedSkillsHeader}\n\n${pinned.map(pinnedBlock).join("\n\n")}`;
193
200
  }
194
201
  /**
195
202
  * The pinned change notice between two snapshots ({@link samePinned} false): each entry that is new
@@ -233,7 +240,7 @@ export function toolMapChangeText(next) {
233
240
  * nothing else differs: logs before phase B render exactly as before), the pinned change, the
234
241
  * tool-name map change; joined by blank lines.
235
242
  */
236
- export function snapshotChangeText(prev, next) {
243
+ export function snapshotChangeText(prev, next, texts = SKILL_TEXTS) {
237
244
  const prevSkills = prev?.skills ?? [];
238
245
  const pinnedDiff = !samePinned(prev?.pinned, next.pinned);
239
246
  const mapDiff = prev?.toolMap !== next.toolMap;
@@ -247,7 +254,7 @@ export function snapshotChangeText(prev, next) {
247
254
  : !sameSkills(prevSkills, next.skills);
248
255
  const parts = [];
249
256
  if (catalogDiff || (!pinnedDiff && !mapDiff)) {
250
- parts.push(skillsChangeText(prevSkills, next.skills, pinnedIds));
257
+ parts.push(skillsChangeText(prevSkills, next.skills, pinnedIds, texts));
251
258
  }
252
259
  if (pinnedDiff)
253
260
  parts.push(pinnedChangeText(prev?.pinned, next.pinned));
@@ -260,10 +267,10 @@ export function snapshotChangeText(prev, next) {
260
267
  * current catalog (when the skills differ from the system snapshot's), the current pinned skills
261
268
  * (when they differ), the tool-name map (when it differs); joined by blank lines, "" for nothing.
262
269
  */
263
- export function snapshotCurrentText(system, covered) {
270
+ export function snapshotCurrentText(system, covered, texts = SKILL_TEXTS) {
264
271
  const parts = [];
265
272
  if (!sameSkills(system?.skills ?? [], covered.skills)) {
266
- parts.push(skillsCurrentText(covered.skills));
273
+ parts.push(skillsCurrentText(covered.skills, texts));
267
274
  }
268
275
  if (!samePinned(system?.pinned, covered.pinned))
269
276
  parts.push(pinnedCurrentText(covered.pinned));
@@ -273,10 +280,10 @@ export function snapshotCurrentText(system, covered) {
273
280
  return parts.join("\n\n");
274
281
  }
275
282
  /** The system snapshot's text after the agent's instructions: catalog, pinned skills, tool map. */
276
- export function snapshotSystemText(s) {
277
- let text = skillsCatalogText(s.skills);
283
+ export function snapshotSystemText(s, texts = SKILL_TEXTS) {
284
+ let text = skillsCatalogText(s.skills, texts);
278
285
  if (s.pinned && s.pinned.length > 0)
279
- text += `\n\n${pinnedSystemText(s.pinned)}`;
286
+ text += `\n\n${pinnedSystemText(s.pinned, texts)}`;
280
287
  if (s.toolMap !== undefined)
281
288
  text += `\n\n${s.toolMap}`;
282
289
  return text;
@@ -6,7 +6,8 @@ import { isForkInvocation } from "./subagents/skill-fork.js";
6
6
  /**
7
7
  * 图状态:只记录进度,消息每步从事件日志重建(runModelStep 自己读日志),checkpoint 很小。
8
8
  * - `step`:当前(最近一次进入的)步骤编号,prepare 节点 +1;
9
- * - `consumedUpToSeq`:已吸收的最大 user_message seq;
9
+ * - `consumedUpToSeq`:已吸收的最大可吸收事件 seq(user_message / background_task_finished; a
10
+ * finish TaskOutput or TaskStop already reported is absorbed like any other, rendered short);
10
11
  * - `lastStopReason`:最近一步模型调用的停止原因;
11
12
  * - `outcome`:图的结束方式(在决定结束的节点里写入,续跑已结束的图时直接读出,不依赖当前时间)。
12
13
  *
@@ -148,7 +149,7 @@ export class LangGraphLoop {
148
149
  let consumed = s.consumedUpToSeq;
149
150
  // the run's first prepare (also when it runs again after a suspend on its fork's sub-agent)
150
151
  const firstStep = s.step === 0;
151
- const absorbed = await ctx.pendingUserMessages(consumed);
152
+ const absorbed = await ctx.pendingAbsorbable(consumed);
152
153
  for (const m of absorbed)
153
154
  consumed = Math.max(consumed, m.seq);
154
155
  // phase D: a run's own fork invocation is absorbed at step 1 (the run boundary,
@@ -1,6 +1,6 @@
1
1
  import type { AgentDefinition } from "../agents/definition.js";
2
2
  import type { KernelConfig } from "../config/schema.js";
3
- import type { ConversationEvent } from "../conversations/events.js";
3
+ import type { AbsorbableEvent } from "../conversations/events.js";
4
4
  import type { StreamSink } from "./model-call.js";
5
5
  /** 一次运行交给 loop 的上下文(spec 4.4)。 */
6
6
  export interface LoopContext {
@@ -22,10 +22,11 @@ export interface LoopContext {
22
22
  shutdown: AbortSignal;
23
23
  sink: StreamSink;
24
24
  /**
25
- * 下一个步骤间隙要吸收的插话:返回 seq > afterSeq 的 user_message(且只含本轮开始时尚未被消费的,
25
+ * 下一个步骤间隙要吸收的事件:返回 seq > afterSeq 的可吸收事件(`user_message` 与
26
+ * `background_task_finished`, `isAbsorbable`;且只含本轮开始时尚未被消费的,
26
27
  * 即 seq 也大于会话的 `consumed_seq`),按 seq 升序。loop 记录吸收到的最大 seq 作为 `consumedUpToSeq`。
27
28
  */
28
- pendingUserMessages(afterSeq: number): Promise<ConversationEvent[]>;
29
+ pendingAbsorbable(afterSeq: number): Promise<AbsorbableEvent[]>;
29
30
  limits: {
30
31
  maxSteps: number;
31
32
  deadline: number;
@@ -53,7 +54,7 @@ export interface SubagentParent {
53
54
  otherAgent?: boolean;
54
55
  }
55
56
  /**
56
- * 运行在等什么人处理:审批(`approvals` 行)或输入请求(`questions` 行,统一承载 `ask_user`、
57
+ * 运行在等什么人处理:审批(`approvals` 行)或输入请求(`questions` 行,统一承载 `AskUserQuestion`、
57
58
  * 插件工具的 `input_required` 与 MCP elicitation)。`expiresAt` 为 ISO 时间。
58
59
  * `subagents` (phase C, spec §7.2): sub-agents dispatched in a step are still running; the id is
59
60
  * `sa-<runId>-<step>` (no `:`, it is part of BullMQ job ids).
@@ -5,6 +5,7 @@ import type { KernelLogger } from "../log.js";
5
5
  import { DirectorySync } from "../orgs/directory-sync.js";
6
6
  import { SandboxService } from "../sandbox/sandbox.service.js";
7
7
  import { ToolDrift } from "../tools/drift.js";
8
+ import { RunQueue } from "./run-queue.js";
8
9
  import { Waits } from "./waits.js";
9
10
  export { MAINTENANCE_QUEUE_NAME } from "./maintenance-queue.js";
10
11
  /** The maintenance worker's concurrency (as the hand-made worker had). */
@@ -13,7 +14,7 @@ export declare const MAINTENANCE_CONCURRENCY = 5;
13
14
  * The one consumer of `cap-kernel-maintenance` (decision R11 of the Nest kernel spec): dispatches
14
15
  * each one-off job by name to its domain (`wait-timeout` → {@link Waits}, `sandbox-destroy-for` →
15
16
  * {@link SandboxService}, `drift-connector` → {@link ToolDrift}, `directory-sync` →
16
- * {@link DirectorySync}). The name of a periodic job (a `@LockedCron` / `@LockedInterval` job,
17
+ * {@link DirectorySync}, `bg-wake` → {@link RunQueue.ensureRun}). The name of a periodic job (a `@LockedCron` / `@LockedInterval` job,
17
18
  * such as `sandbox-suspend-idle`) runs that job's body once ({@link ScheduledRuns.runNow}), as the
18
19
  * maintenance handlers did when those jobs were schedulers on this queue: an operator's or a
19
20
  * test's one-off run, not a second schedule (decision R23 of the Nest kernel spec). Any other
@@ -24,10 +25,11 @@ export declare class MaintenanceProcessor extends WorkerHost<Worker> {
24
25
  private readonly sandbox;
25
26
  private readonly drift;
26
27
  private readonly directory;
28
+ private readonly runs;
27
29
  private readonly scheduled;
28
30
  private readonly log;
29
31
  private readonly queue;
30
- constructor(waits: Pick<Waits, "processTimeout">, sandbox: Pick<SandboxService, "destroyFor">, drift: Pick<ToolDrift, "check">, directory: Pick<DirectorySync, "runSyncJob">, scheduled: Pick<ScheduledRuns, "runNow">, log: Pick<KernelLogger, "error" | "warn">, queue: Pick<Queue, "removeJobScheduler">);
32
+ constructor(waits: Pick<Waits, "processTimeout">, sandbox: Pick<SandboxService, "destroyFor">, drift: Pick<ToolDrift, "check">, directory: Pick<DirectorySync, "runSyncJob">, runs: Pick<RunQueue, "ensureRun">, scheduled: Pick<ScheduledRuns, "runNow">, log: Pick<KernelLogger, "error" | "warn">, queue: Pick<Queue, "removeJobScheduler">);
31
33
  /**
32
34
  * Removes the retired job schedulers (`RETIRED_SCHEDULER_IDS`, runtime/retired-schedulers.ts): every fixed-period
33
35
  * maintenance job is a `@LockedCron` / `@LockedInterval` now. Idempotent; called once when a
@@ -9,6 +9,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
9
9
  };
10
10
  import { getQueueToken, OnWorkerEvent, WorkerHost } from "@nestjs/bullmq";
11
11
  import { Inject, Injectable, Module } from "@nestjs/common";
12
+ import { BG_WAKE_JOB } from "../background/wake-rules.js";
12
13
  import { configuredProcessor } from "../infra/queue/configured-processor.js";
13
14
  import { QueueModule } from "../infra/queue/queue.module.js";
14
15
  import { removeRetiredSchedulers } from "../infra/queue/retired-schedulers.js";
@@ -26,6 +27,7 @@ import { DRIFT_CONNECTOR_JOB } from "../tools/job-ids.js";
26
27
  import { ToolsModule } from "../tools/tools.module.js";
27
28
  import { MAINTENANCE_QUEUE_NAME } from "./maintenance-queue.js";
28
29
  import { RETIRED_SCHEDULER_IDS } from "./retired-schedulers.js";
30
+ import { RunQueue } from "./run-queue.js";
29
31
  import { RuntimeModule } from "./runtime.module.js";
30
32
  import { WAIT_TIMEOUT_JOB, Waits } from "./waits.js";
31
33
  export { MAINTENANCE_QUEUE_NAME } from "./maintenance-queue.js";
@@ -35,7 +37,7 @@ export const MAINTENANCE_CONCURRENCY = 5;
35
37
  * The one consumer of `cap-kernel-maintenance` (decision R11 of the Nest kernel spec): dispatches
36
38
  * each one-off job by name to its domain (`wait-timeout` → {@link Waits}, `sandbox-destroy-for` →
37
39
  * {@link SandboxService}, `drift-connector` → {@link ToolDrift}, `directory-sync` →
38
- * {@link DirectorySync}). The name of a periodic job (a `@LockedCron` / `@LockedInterval` job,
40
+ * {@link DirectorySync}, `bg-wake` → {@link RunQueue.ensureRun}). The name of a periodic job (a `@LockedCron` / `@LockedInterval` job,
39
41
  * such as `sandbox-suspend-idle`) runs that job's body once ({@link ScheduledRuns.runNow}), as the
40
42
  * maintenance handlers did when those jobs were schedulers on this queue: an operator's or a
41
43
  * test's one-off run, not a second schedule (decision R23 of the Nest kernel spec). Any other
@@ -46,15 +48,17 @@ let MaintenanceProcessor = class MaintenanceProcessor extends WorkerHost {
46
48
  sandbox;
47
49
  drift;
48
50
  directory;
51
+ runs;
49
52
  scheduled;
50
53
  log;
51
54
  queue;
52
- constructor(waits, sandbox, drift, directory, scheduled, log, queue) {
55
+ constructor(waits, sandbox, drift, directory, runs, scheduled, log, queue) {
53
56
  super();
54
57
  this.waits = waits;
55
58
  this.sandbox = sandbox;
56
59
  this.drift = drift;
57
60
  this.directory = directory;
61
+ this.runs = runs;
58
62
  this.scheduled = scheduled;
59
63
  this.log = log;
60
64
  this.queue = queue;
@@ -90,6 +94,13 @@ let MaintenanceProcessor = class MaintenanceProcessor extends WorkerHost {
90
94
  case DIRECTORY_SYNC_JOB:
91
95
  await this.directory.runSyncJob(job.data);
92
96
  return;
97
+ // the end of a conversation's wake window (background Bash spec §3)
98
+ case BG_WAKE_JOB: {
99
+ // fired before the window ended (clock skew): it reschedules under its next retry id
100
+ const { conversationId, retry } = job.data;
101
+ await this.runs.ensureRun(conversationId, { wakeRetry: (retry ?? 0) + 1 });
102
+ return;
103
+ }
93
104
  default:
94
105
  if (await this.scheduled.runNow(job.name))
95
106
  return;
@@ -115,9 +126,10 @@ MaintenanceProcessor = __decorate([
115
126
  __param(1, Inject(SandboxService)),
116
127
  __param(2, Inject(ToolDrift)),
117
128
  __param(3, Inject(DirectorySync)),
118
- __param(4, Inject(ScheduledRuns)),
119
- __param(5, Inject(KERNEL_LOGGER)),
120
- __param(6, Inject(getQueueToken(MAINTENANCE_QUEUE_NAME)))
129
+ __param(4, Inject(RunQueue)),
130
+ __param(5, Inject(ScheduledRuns)),
131
+ __param(6, Inject(KERNEL_LOGGER)),
132
+ __param(7, Inject(getQueueToken(MAINTENANCE_QUEUE_NAME)))
121
133
  ], MaintenanceProcessor);
122
134
  export { MaintenanceProcessor };
123
135
  /**
@@ -1,6 +1,7 @@
1
1
  import { type ContentBlock, type Logger, type ModelProvider, type ModelRequest, type ModelStreamEvent, type ModelUsage, type StopReason } from "@capybara-hq/plugin-sdk";
2
2
  import type { AgentDefinition } from "../agents/definition.js";
3
- import type { EventLog } from "../conversations/event-log.js";
3
+ import type { AppendEvent, EventLog } from "../conversations/event-log.js";
4
+ import { type ConversationEvent } from "../conversations/events.js";
4
5
  import type { KernelSchemaDb } from "../db/kernel-schema.js";
5
6
  import type { KernelConfigService } from "../infra/config/kernel-config.service.js";
6
7
  import type { ToolRegistry, UnavailableTool } from "../tools/registry.js";
@@ -151,6 +152,21 @@ export declare function runModelStep(deps: ModelStepDeps, input: ModelStepInput)
151
152
  * 其余与 `runModelStep` 相同(幂等、降级、中止)。
152
153
  */
153
154
  export declare function runFinalWrapUp(deps: ModelStepDeps, input: ModelStepInput): Promise<ModelStepResult>;
155
+ /**
156
+ * Appends a model call's events (its reply or compaction outcome with its `usage`; also the usage
157
+ * of a `WebFetch` extraction call, `tools/builtins/web/extract.ts`). For a
158
+ * sub-agent's run (`input.parentRunId`) in one transaction that also adds the tokens of the usage
159
+ * events it newly wrote to the parent run's `subagent_tokens_used` (sub-agents spec §8.3): a usage
160
+ * event already in the log (an idempotent hit after a crash) adds nothing, so each call counts
161
+ * exactly once.
162
+ */
163
+ export declare function appendCounted(deps: {
164
+ eventLog: Pick<EventLog, "append" | "notify">;
165
+ stepLog: Pick<StepLog, "appendCounted">;
166
+ }, input: {
167
+ conversationId: string;
168
+ parentRunId?: string | undefined;
169
+ }, events: AppendEvent[]): Promise<ConversationEvent[]>;
154
170
  /** {@link assembleModelRequest} 的输入。 */
155
171
  export interface AssembleModelRequestInput extends Omit<BuildModelRequestInput, "tools"> {
156
172
  /** 本步解析出的工具;模型不支持工具(`capabilities.tools` 为 false)时不带。 */
@@ -128,7 +128,7 @@ async function runStep(deps, input, wrapUp) {
128
128
  }
129
129
  // 每步实时解析(连接器 / 插件状态可能在步骤之间变化),解析结果记在 model_call;收尾调用同样带工具
130
130
  // a skills catalog snapshot (Ruling M17; an empty one too) or a person's skill invocation in the
131
- // log → skill_load is offered (see skillLoadOffered)
131
+ // log → Skill is offered (see skillLoadOffered)
132
132
  const resolved = await deps.tools.forAgent(input.orgId, {
133
133
  tools: input.agent.tools ?? [],
134
134
  subagents: input.agent.subagents,
@@ -226,13 +226,14 @@ async function runStep(deps, input, wrapUp) {
226
226
  }
227
227
  }
228
228
  /**
229
- * Appends a model call's events (its reply or compaction outcome with its `usage`). For a
229
+ * Appends a model call's events (its reply or compaction outcome with its `usage`; also the usage
230
+ * of a `WebFetch` extraction call, `tools/builtins/web/extract.ts`). For a
230
231
  * sub-agent's run (`input.parentRunId`) in one transaction that also adds the tokens of the usage
231
232
  * events it newly wrote to the parent run's `subagent_tokens_used` (sub-agents spec §8.3): a usage
232
233
  * event already in the log (an idempotent hit after a crash) adds nothing, so each call counts
233
234
  * exactly once.
234
235
  */
235
- async function appendCounted(deps, input, events) {
236
+ export async function appendCounted(deps, input, events) {
236
237
  const { conversationId, parentRunId } = input;
237
238
  if (parentRunId === undefined)
238
239
  return deps.eventLog.append(conversationId, events);
@@ -67,6 +67,12 @@ export declare class ProviderRegistry {
67
67
  listTimeoutMs?: number);
68
68
  /** `listModels()` 加时限(到时按失败处理,供应商的调用留在后台、结果丢弃)。 */
69
69
  private listModelsWithTimeout;
70
+ /**
71
+ * Whether at least one model-provider extension is loaded on this replica (enabled, configured,
72
+ * set up). Read from the extension host only: never calls a vendor, so a provider whose vendor
73
+ * is down still counts (org readiness, web-order spec §3.8).
74
+ */
75
+ hasProvider(): boolean;
70
76
  /** 每个插件取一个实现(`@2` 优先),按插件首次出现的顺序;不支持的主版本记 warn 后忽略。 */
71
77
  private providers;
72
78
  private models;
@@ -132,6 +132,14 @@ let ProviderRegistry = class ProviderRegistry {
132
132
  clearTimeout(timer);
133
133
  }
134
134
  }
135
+ /**
136
+ * Whether at least one model-provider extension is loaded on this replica (enabled, configured,
137
+ * set up). Read from the extension host only: never calls a vendor, so a provider whose vendor
138
+ * is down still counts (org readiness, web-order spec §3.8).
139
+ */
140
+ hasProvider() {
141
+ return this.providers().length > 0;
142
+ }
135
143
  /** 每个插件取一个实现(`@2` 优先),按插件首次出现的顺序;不支持的主版本记 warn 后忽略。 */
136
144
  providers() {
137
145
  const chosen = new Map();
@@ -19,7 +19,7 @@ export interface FinishRunArgs {
19
19
  floorToTrigger?: boolean;
20
20
  /**
21
21
  * Runs in the transaction once the run is known not to be terminal, before the terminal event:
22
- * a parent's open `agent` calls get their results here (sub-agents spec §12, review m1).
22
+ * a parent's open `Agent` calls get their results here (sub-agents spec §12, review m1).
23
23
  */
24
24
  beforeTerminal?: () => Promise<void>;
25
25
  }
@@ -1,6 +1,8 @@
1
1
  import type { Logger } from "@capybara-hq/plugin-sdk";
2
+ import type { Queue } from "bullmq";
2
3
  import { EventLog } from "../conversations/event-log.js";
3
4
  import type { ConversationKind } from "../db/kernel-schema.js";
5
+ import { KernelConfigService } from "../infra/config/kernel-config.service.js";
4
6
  import { KernelDb } from "../infra/database/kernel-db.js";
5
7
  import { TransactionHost } from "../infra/database/transaction-host.js";
6
8
  import { KernelEvents } from "../infra/events/kernel-events.js";
@@ -24,19 +26,24 @@ export declare class RunQueue {
24
26
  private readonly finisher;
25
27
  /** 运行以孤儿结束(标记失败 / 直接中止)后删除它的 checkpoint thread(thread_id = runId)。 */
26
28
  private readonly checkpoints;
27
- /** The run's open `agent` call results, in the orphan repair's transaction (sub-agents spec §12). */
29
+ /** The run's open `Agent` call results, in the orphan repair's transaction (sub-agents spec §12). */
28
30
  private readonly pipeline;
29
31
  private readonly events;
30
32
  private readonly log;
31
33
  readonly txHost: TransactionHost;
34
+ private readonly config;
35
+ /** The producer side of the delayed `bg-wake` job (`MaintenanceProcessor` consumes it). */
36
+ private readonly maintenance;
32
37
  constructor(kdb: KernelDb, eventLog: EventLog, lock: Pick<ConversationLock, "holder">, jobs: RunJobs, finisher: Pick<RunFinish, "finishIn">,
33
38
  /** 运行以孤儿结束(标记失败 / 直接中止)后删除它的 checkpoint thread(thread_id = runId)。 */
34
39
  checkpoints: Pick<KyselyCheckpointSaver, "deleteThread">,
35
- /** The run's open `agent` call results, in the orphan repair's transaction (sub-agents spec §12). */
36
- pipeline: Pick<ToolPipeline, "stopOpenAgentCalls">, events: KernelEvents, log: Pick<Logger, "error" | "warn">, txHost: TransactionHost);
40
+ /** The run's open `Agent` call results, in the orphan repair's transaction (sub-agents spec §12). */
41
+ pipeline: Pick<ToolPipeline, "stopOpenAgentCalls">, events: KernelEvents, log: Pick<Logger, "error" | "warn">, txHost: TransactionHost, config: KernelConfigService,
42
+ /** The producer side of the delayed `bg-wake` job (`MaintenanceProcessor` consumes it). */
43
+ maintenance: Pick<Queue, "add">);
37
44
  private get db();
38
45
  /**
39
- * The `beforeTerminal` of an orphan repair: writes the run's open `agent` call results in the
46
+ * The `beforeTerminal` of an orphan repair: writes the run's open `Agent` call results in the
40
47
  * repair's transaction; `fire()` runs their observe hooks after the commit (review m1).
41
48
  */
42
49
  private stopOpenCalls;
@@ -44,6 +51,11 @@ export declare class RunQueue {
44
51
  * 有未消费的用户消息(最新 user_message 的 seq > `consumed_seq`)、会话锁无人持有、
45
52
  * 且没有 queued / running / waiting 的运行时:插入 `runs`(queued)并投递任务,返回 runId;否则返回 null。
46
53
  *
54
+ * The boundary (`trigger_seq`) is that newest message; with none unconsumed, the queue's head
55
+ * once it is sent; with no head either, a wake-eligible finished background task (background
56
+ * Bash spec §3, {@link wakeDecisionIn}): the run is then attributed to the task's trigger
57
+ * account, and a finish inside the wake window schedules the delayed `bg-wake` job instead.
58
+ *
47
59
  * 孤儿清理(R29,按需进行,没有定时器):已有的 queued / running 运行若 BullMQ 任务已不存在、
48
60
  * 会话锁也无人持有(queued 的还要超过宽限期),说明没有任何 worker 会再执行它——写
49
61
  * `run_failed { code: "run.orphaned" }` 把它标记为失败(consumed_seq 推进到它的触发消息),
@@ -52,9 +64,20 @@ export declare class RunQueue {
52
64
  *
53
65
  * agent 已软删除的会话不起新运行(孤儿清理照常进行)。
54
66
  */
55
- ensureRun(conversationId: string): Promise<string | null>;
67
+ ensureRun(conversationId: string,
68
+ /** From the `bg-wake` job: it fired `wakeRetry - 1` times before its window ended. */
69
+ opts?: {
70
+ wakeRetry?: number;
71
+ }): Promise<string | null>;
56
72
  /** {@link ensureRun}'s transaction: what it decided goes back through `st`. */
57
73
  private ensureRunIn;
74
+ /**
75
+ * Schedules the delayed `bg-wake` job at the end of the conversation's wake window (after the
76
+ * commit): one job per conversation and window end, so finishes inside one window share it. It
77
+ * calls {@link ensureRun}, which wakes the conversation if a finish is still unconsumed. A failed
78
+ * enqueue is logged: the next message, run end or page opening re-derives the wake.
79
+ */
80
+ private scheduleWake;
58
81
  /**
59
82
  * Enqueues a run job under the caller's job id (resumes, dispatches, repairs), with the same
60
83
  * options as {@link ensureRun} (see {@link RunJobs.enqueue}).