@xingular/harness 0.1.7 → 1.0.0

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 (683) hide show
  1. package/CHANGELOG.md +97 -1
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +22 -0
  4. package/README.md +187 -85
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +13701 -13498
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +808 -151
  373. package/docs/README.md +22 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  403. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  404. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  405. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  406. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  407. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  408. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  409. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  410. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  411. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  412. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  413. package/docs/decisions/ADR-0013-doctor.md +27 -0
  414. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  415. package/docs/doctor.md +74 -0
  416. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  418. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  420. package/docs/features/README.md +20 -0
  421. package/docs/features/automations/README.md +41 -0
  422. package/docs/features/cores/README.md +39 -0
  423. package/docs/features/google-harness2/README.md +52 -0
  424. package/docs/features/integrations/README.md +40 -0
  425. package/docs/features/interfaces/README.md +29 -0
  426. package/docs/features/memory/README.md +28 -0
  427. package/docs/releases/1.0.0.md +40 -0
  428. package/docs/releases/README.md +36 -0
  429. package/docs/study/00-index.md +78 -0
  430. package/docs/study/arms/00-matrix.md +20 -0
  431. package/docs/study/arms/01-system-prompt.md +211 -0
  432. package/docs/study/arms/02-tools.md +79 -0
  433. package/docs/study/arms/03-subagents.md +90 -0
  434. package/docs/study/arms/04-skills.md +75 -0
  435. package/docs/study/arms/05-context-management.md +90 -0
  436. package/docs/study/arms/06-memory.md +90 -0
  437. package/docs/study/arms/07-governance.md +71 -0
  438. package/docs/study/arms/08-execution.md +69 -0
  439. package/docs/study/arms/09-observability.md +60 -0
  440. package/docs/study/arms/10-refinement.md +110 -0
  441. package/docs/study/btw-comparison.md +37 -0
  442. package/docs/study/feature-gap-review.md +42 -0
  443. package/docs/study/insights.md +123 -0
  444. package/docs/study/roadmap.md +72 -0
  445. package/docs/study/sources/claude-code.md +44 -0
  446. package/docs/study/sources/deepseek-harness.md +102 -0
  447. package/docs/study/sources/harness2.md +50 -0
  448. package/docs/study/sources/kimi-cli.md +42 -0
  449. package/docs/study/sources/omp.md +93 -0
  450. package/docs/study/sources/opencode.md +43 -0
  451. package/docs/study/sources/openhands.md +46 -0
  452. package/docs/study/sources/smolagents.md +40 -0
  453. package/docs/study/sources/swe-agent.md +34 -0
  454. package/docs/system-prompt-design.md +196 -0
  455. package/docs/terminal-tui.md +473 -56
  456. package/package.json +43 -13
  457. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  458. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  459. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  460. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  461. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  462. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  463. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  464. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  465. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  466. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  467. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  468. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  469. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  470. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  471. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  472. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  473. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  474. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  475. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  476. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  477. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  478. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  479. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  480. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  481. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  482. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  483. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  484. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  485. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  486. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  487. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  488. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  489. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  490. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  491. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  492. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  493. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  494. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  495. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  496. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  497. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  498. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  499. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
  500. package/src/accounts/accounts.test.ts +0 -333
  501. package/src/accounts/accounts.ts +0 -658
  502. package/src/accounts/env.test.ts +0 -95
  503. package/src/accounts/env.ts +0 -338
  504. package/src/accounts/secrets.ts +0 -50
  505. package/src/accounts/store.ts +0 -338
  506. package/src/capabilities/api.ts +0 -75
  507. package/src/capabilities/runSnapshot.ts +0 -59
  508. package/src/capabilities/types.ts +0 -34
  509. package/src/cli.ts +0 -118
  510. package/src/core/bus.ts +0 -34
  511. package/src/core/changes.ts +0 -33
  512. package/src/core/env.ts +0 -27
  513. package/src/core/errors.ts +0 -32
  514. package/src/core/frontmatter.ts +0 -47
  515. package/src/core/fs.test.ts +0 -38
  516. package/src/core/fs.ts +0 -92
  517. package/src/core/index.ts +0 -193
  518. package/src/core/path.test.ts +0 -14
  519. package/src/core/path.ts +0 -79
  520. package/src/core/projects.ts +0 -90
  521. package/src/core/text.ts +0 -39
  522. package/src/harness.ts +0 -312
  523. package/src/hub/catalog.json +0 -123
  524. package/src/hub/cli.ts +0 -59
  525. package/src/hub/hub.test.ts +0 -205
  526. package/src/hub/hub.ts +0 -256
  527. package/src/hub/schema.ts +0 -81
  528. package/src/index.ts +0 -75
  529. package/src/mcp/connections.ts +0 -614
  530. package/src/mcp/manager.ts +0 -130
  531. package/src/mcp/oauth.ts +0 -195
  532. package/src/mcp/scopeMigration.test.ts +0 -79
  533. package/src/mcp/scopeMigration.ts +0 -204
  534. package/src/mcp/service.test.ts +0 -376
  535. package/src/mcp/service.ts +0 -549
  536. package/src/mcp/types.ts +0 -108
  537. package/src/memory/api.test.ts +0 -82
  538. package/src/memory/api.ts +0 -303
  539. package/src/memory/blocks.test.ts +0 -78
  540. package/src/memory/blocks.ts +0 -408
  541. package/src/memory/caller.ts +0 -69
  542. package/src/memory/curation.test.ts +0 -163
  543. package/src/memory/curation.ts +0 -64
  544. package/src/memory/dispatch.ts +0 -59
  545. package/src/memory/facts.test.ts +0 -41
  546. package/src/memory/facts.ts +0 -248
  547. package/src/memory/graph.ts +0 -103
  548. package/src/memory/health.test.ts +0 -130
  549. package/src/memory/health.ts +0 -74
  550. package/src/memory/maintainer.ts +0 -272
  551. package/src/memory/maintenance.test.ts +0 -176
  552. package/src/memory/maintenance.ts +0 -518
  553. package/src/memory/migrate.ts +0 -79
  554. package/src/memory/operations.ts +0 -150
  555. package/src/memory/proposals.test.ts +0 -168
  556. package/src/memory/proposals.ts +0 -584
  557. package/src/memory/recall.test.ts +0 -115
  558. package/src/memory/recall.ts +0 -278
  559. package/src/memory/references.ts +0 -77
  560. package/src/memory/runContext.ts +0 -93
  561. package/src/memory/secrets.ts +0 -6
  562. package/src/memory/store.test.ts +0 -66
  563. package/src/memory/store.ts +0 -385
  564. package/src/memory/wiki.test.ts +0 -47
  565. package/src/memory/wiki.ts +0 -422
  566. package/src/memory/wikiIndex.test.ts +0 -88
  567. package/src/memory/wikiIndex.ts +0 -116
  568. package/src/plugins/api.ts +0 -181
  569. package/src/plugins/attachments.test.ts +0 -84
  570. package/src/plugins/attachments.ts +0 -141
  571. package/src/plugins/builtin.ts +0 -82
  572. package/src/plugins/catalogue.test.ts +0 -254
  573. package/src/plugins/catalogue.ts +0 -251
  574. package/src/plugins/cli.ts +0 -184
  575. package/src/plugins/discover.ts +0 -151
  576. package/src/plugins/firstParty.test.ts +0 -143
  577. package/src/plugins/firstParty.ts +0 -129
  578. package/src/plugins/hooks.test.ts +0 -250
  579. package/src/plugins/hooks.ts +0 -239
  580. package/src/plugins/identity.ts +0 -37
  581. package/src/plugins/install.test.ts +0 -107
  582. package/src/plugins/install.ts +0 -106
  583. package/src/plugins/inventory.ts +0 -123
  584. package/src/plugins/manifest.ts +0 -76
  585. package/src/plugins/plugins.test.ts +0 -205
  586. package/src/plugins/plugins.ts +0 -189
  587. package/src/plugins/proposal.ts +0 -121
  588. package/src/plugins/runtime.test.ts +0 -40
  589. package/src/plugins/runtime.ts +0 -82
  590. package/src/plugins/trust.ts +0 -142
  591. package/src/plugins/types.ts +0 -149
  592. package/src/prompt/compile.test.ts +0 -261
  593. package/src/prompt/compile.ts +0 -732
  594. package/src/server/methods.ts +0 -349
  595. package/src/server/remote.ts +0 -77
  596. package/src/server/rpc.ts +0 -116
  597. package/src/server/serve.ts +0 -28
  598. package/src/server/server.test.ts +0 -174
  599. package/src/sessions/approvals.ts +0 -118
  600. package/src/sessions/contracts.ts +0 -336
  601. package/src/sessions/conversation.test.ts +0 -177
  602. package/src/sessions/extensionSession.test.ts +0 -74
  603. package/src/sessions/extensionUi.test.ts +0 -65
  604. package/src/sessions/extensionUi.ts +0 -102
  605. package/src/sessions/history.ts +0 -51
  606. package/src/sessions/lineageJoin.ts +0 -75
  607. package/src/sessions/policy.ts +0 -36
  608. package/src/sessions/pricing.ts +0 -60
  609. package/src/sessions/questionBatches.test.ts +0 -110
  610. package/src/sessions/reasoningSummaries.ts +0 -59
  611. package/src/sessions/registry.ts +0 -381
  612. package/src/sessions/runIndex.ts +0 -99
  613. package/src/sessions/runStore.test.ts +0 -152
  614. package/src/sessions/runStore.ts +0 -332
  615. package/src/sessions/runner.ts +0 -604
  616. package/src/sessions/runtimeResources.test.ts +0 -61
  617. package/src/sessions/sessions.test.ts +0 -549
  618. package/src/sessions/sessions.ts +0 -339
  619. package/src/skills/registry.test.ts +0 -104
  620. package/src/skills/registry.ts +0 -413
  621. package/src/terminal/accountsMenu.test.ts +0 -225
  622. package/src/terminal/accountsMenu.ts +0 -382
  623. package/src/terminal/cli.ts +0 -149
  624. package/src/terminal/client.ts +0 -74
  625. package/src/terminal/control.test.ts +0 -23
  626. package/src/terminal/control.ts +0 -23
  627. package/src/terminal/controller.ts +0 -291
  628. package/src/terminal/hubMenu.ts +0 -24
  629. package/src/terminal/launch.test.ts +0 -25
  630. package/src/terminal/launch.ts +0 -48
  631. package/src/terminal/piExtension.lifecycle.test.ts +0 -55
  632. package/src/terminal/piExtension.ts +0 -259
  633. package/src/terminal/pluginControl.test.ts +0 -146
  634. package/src/terminal/pluginMenu.ts +0 -112
  635. package/src/terminal/socket.test.ts +0 -71
  636. package/src/terminal/socket.ts +0 -232
  637. package/src/terminal/standalone.test.ts +0 -167
  638. package/src/terminal/standalone.ts +0 -153
  639. package/src/terminal/terminal.test.ts +0 -399
  640. package/src/terminal/terminals.ts +0 -553
  641. package/src/terminal/tui/application.test.ts +0 -114
  642. package/src/terminal/tui/application.ts +0 -491
  643. package/src/terminal/tui/commands.test.ts +0 -218
  644. package/src/terminal/tui/commands.ts +0 -361
  645. package/src/terminal/tui/dialogs.ts +0 -301
  646. package/src/terminal/tui/editor.test.ts +0 -84
  647. package/src/terminal/tui/editor.ts +0 -79
  648. package/src/terminal/tui/keybindings.test.ts +0 -22
  649. package/src/terminal/tui/keybindings.ts +0 -50
  650. package/src/terminal/tui/piAdapter.ts +0 -62
  651. package/src/terminal/tui/presentation.test.ts +0 -79
  652. package/src/terminal/tui/questions.test.ts +0 -41
  653. package/src/terminal/tui/questions.ts +0 -47
  654. package/src/terminal/tui/runtime.socket.test.ts +0 -104
  655. package/src/terminal/tui/runtime.test.ts +0 -215
  656. package/src/terminal/tui/runtime.ts +0 -388
  657. package/src/terminal/tui/sessionUi.ts +0 -24
  658. package/src/terminal/tui/settings.test.ts +0 -150
  659. package/src/terminal/tui/settings.ts +0 -188
  660. package/src/terminal/tui/status.test.ts +0 -70
  661. package/src/terminal/tui/status.ts +0 -109
  662. package/src/terminal/tui/theme.ts +0 -174
  663. package/src/terminal/tui/tools.test.ts +0 -145
  664. package/src/terminal/tui/tools.ts +0 -142
  665. package/src/terminal/tui/transcript.test.ts +0 -25
  666. package/src/terminal/tui/transcript.ts +0 -124
  667. package/src/terminal/tui/ui.test.ts +0 -313
  668. package/src/terminal/tui/ui.ts +0 -166
  669. package/src/terminal/tui/welcome.ts +0 -102
  670. package/src/tools/askUser.test.ts +0 -69
  671. package/src/tools/askUser.ts +0 -59
  672. package/src/tools/definitions.ts +0 -187
  673. package/src/tools/maintenance.ts +0 -24
  674. package/src/tools/memoryTools.ts +0 -22
  675. package/src/tools/pluginPropose.ts +0 -41
  676. package/src/tools/registryWrite.test.ts +0 -101
  677. package/src/tools/registryWrite.ts +0 -182
  678. package/src/tools/spawnSubagent.ts +0 -92
  679. package/src/tools/types.ts +0 -39
  680. package/src/web/safeRequest.ts +0 -171
  681. package/src/web/text.ts +0 -53
  682. package/src/web/tools.ts +0 -134
  683. package/src/web/web.test.ts +0 -141
@@ -1,110 +0,0 @@
1
- import { mkdtempSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { afterEach, expect, test } from 'vitest'
5
-
6
- import { closeIndex } from '../core/index'
7
- import { runEventPayloadSchemas, runRecordSchema, type RunEvent } from './contracts'
8
- import { RunRegistry } from './registry'
9
- import { readEvents, saveRun } from './runStore'
10
-
11
- const roots: string[] = []
12
- afterEach(() => {
13
- for (const root of roots.splice(0)) closeIndex(root)
14
- })
15
-
16
- function fixture() {
17
- const root = mkdtempSync(join(tmpdir(), 'harness-question-batch-'))
18
- roots.push(root)
19
- saveRun(root, runRecordSchema.parse({
20
- id: 'run-1',
21
- sessionId: 'session-1',
22
- projectId: null,
23
- mode: 'chat',
24
- harness: 'pi',
25
- sessionType: 'structured',
26
- nativeSessionId: null,
27
- workingDirectory: null,
28
- worktreeId: null,
29
- goal: null,
30
- status: 'running',
31
- startedAt: 'start',
32
- endedAt: null
33
- }))
34
- const registry = new RunRegistry({ root: () => root })
35
- const run = registry.start('session-1', 'run-1')
36
- return { root, registry, run }
37
- }
38
-
39
- test('question batches validate all answers before resolving and retain choice notes', async () => {
40
- const { root, registry, run } = fixture()
41
- expect(() => run.requestAnswers([])).toThrow(/between one and five/)
42
- expect(() => run.requestAnswers(Array.from({ length: 6 }, () => ({ question: 'Q', options: [], multiSelect: false, allowText: true })))).toThrow(/between one and five/)
43
-
44
- const result = run.requestAnswers([
45
- { summary: 'Project scope', question: 'What should change?', options: [{ label: 'UI' }, { label: 'API' }], multiSelect: true, allowText: true },
46
- { summary: 'Target date', question: 'When should it ship?', options: [{ label: 'Soon' }, { label: 'Later' }], multiSelect: false, allowText: false }
47
- ])
48
- let settled = false
49
- void result.then(() => { settled = true })
50
-
51
- const requested = readEvents(root, 'run-1').filter((event) => event.type === 'question.requested')
52
- expect(requested).toHaveLength(2)
53
- const [first, second] = requested.map((event) => event.payload as { questionId: string; summary: string; batchId: string; batchIndex: number; batchCount: number })
54
- expect(first).toMatchObject({ summary: 'Project scope', batchIndex: 1, batchCount: 2 })
55
- expect(second).toMatchObject({ summary: 'Target date', batchId: first.batchId, batchIndex: 2, batchCount: 2 })
56
- expect(() => registry.answerQuestion('run-1', first.questionId, { selected: ['UI'] })).toThrow(/together/)
57
-
58
- expect(() => registry.answerQuestions('run-1', first.batchId, [
59
- { questionId: first.questionId, answer: { selected: ['UI'] } },
60
- { questionId: second.questionId, answer: { selected: ['Later'], notes: { Soon: 'wrong choice' } } }
61
- ])).toThrow(/selected choices/)
62
- await Promise.resolve()
63
- expect(settled).toBe(false)
64
-
65
- registry.answerQuestions('run-1', first.batchId, [
66
- { questionId: second.questionId, answer: { selected: ['Soon'] } },
67
- { questionId: first.questionId, answer: { selected: ['UI'], notes: { UI: 'Keep keyboard navigation.' } } }
68
- ])
69
- await expect(result).resolves.toEqual([
70
- { selected: ['UI'], notes: { UI: 'Keep keyboard navigation.' } },
71
- { selected: ['Soon'] }
72
- ])
73
-
74
- const answered = readEvents(root, 'run-1').filter((event) => event.type === 'question.answered')
75
- expect(answered).toHaveLength(2)
76
- expect(answered.find((event) => (event.payload as { questionId: string }).questionId === first.questionId)?.payload).toMatchObject({
77
- batchId: first.batchId,
78
- batchIndex: 1,
79
- batchCount: 2,
80
- notes: { UI: 'Keep keyboard navigation.' }
81
- })
82
- })
83
-
84
- test('legacy single questions remain valid alongside batch event metadata', () => {
85
- const { root, registry, run } = fixture()
86
- const answer = run.requestAnswer({ question: 'Continue?', options: [{ label: 'Yes' }], multiSelect: false, allowText: false })
87
- const request = readEvents(root, 'run-1').find((event) => event.type === 'question.requested')!
88
- expect(runEventPayloadSchemas['question.requested'].safeParse(request.payload).success).toBe(true)
89
- expect(runEventPayloadSchemas['question.requested'].safeParse({ ...(request.payload as object), batchId: 'partial' }).success).toBe(false)
90
- registry.answerQuestion('run-1', (request.payload as { questionId: string }).questionId, { selected: ['Yes'] })
91
- return expect(answer).resolves.toEqual({ selected: ['Yes'] })
92
- })
93
-
94
- test('answer batch method rejects duplicate and foreign question ids without settling the batch', async () => {
95
- const { root, registry, run } = fixture()
96
- const result = run.requestAnswers([
97
- { summary: 'First', question: 'First?', options: [], multiSelect: false, allowText: true },
98
- { summary: 'Second', question: 'Second?', options: [], multiSelect: false, allowText: true }
99
- ])
100
- const requested = readEvents(root, 'run-1').filter((event) => event.type === 'question.requested')
101
- const [first, second] = requested.map((event) => event.payload as { questionId: string; batchId: string })
102
- const answers = [{ questionId: first.questionId, answer: { selected: [], text: 'a' } }, { questionId: second.questionId, answer: { selected: [], text: 'b' } }]
103
- expect(() => registry.answerQuestions('run-1', 'other-batch', answers)).toThrow(/batch/)
104
- expect(() => registry.answerQuestions('run-1', first.batchId, [answers[0], answers[0]])).toThrow(/batch/)
105
- expect(() => registry.answerQuestions('another-run', first.batchId, answers)).toThrow(/batch/)
106
- const events: RunEvent[] = readEvents(root, 'run-1')
107
- expect(events.filter((event) => event.type === 'question.answered')).toHaveLength(0)
108
- registry.answerQuestions('run-1', first.batchId, answers)
109
- await expect(result).resolves.toHaveLength(2)
110
- })
@@ -1,59 +0,0 @@
1
- export const MAX_REASONING_SUMMARY_CHARS = 4_000
2
-
3
- export const REASONING_SUMMARY_APIS = new Set([
4
- 'openai-responses',
5
- 'azure-openai-responses',
6
- 'openai-codex-responses'
7
- ])
8
-
9
- type RecordValue = Record<string, unknown>
10
-
11
- function isRecord(value: unknown): value is RecordValue {
12
- return Boolean(value && typeof value === 'object' && !Array.isArray(value))
13
- }
14
-
15
- function cleanSummary(value: string): string | undefined {
16
- let text = ''
17
- for (const character of value.trim()) {
18
- if (text.length + character.length > MAX_REASONING_SUMMARY_CHARS) break
19
- text += character
20
- }
21
- return text.trim() || undefined
22
- }
23
-
24
- /** Add the Responses API summary request while preserving the provider-selected effort. */
25
- export function requestConciseReasoningSummary(payload: unknown): { payload: unknown; requested: boolean } {
26
- if (!isRecord(payload) || !isRecord(payload.reasoning)) return { payload, requested: false }
27
- const effort = payload.reasoning.effort
28
- if (typeof effort !== 'string' || ['none', 'off'].includes(effort.toLowerCase())) return { payload, requested: false }
29
- return {
30
- payload: { ...payload, reasoning: { ...payload.reasoning, summary: 'concise' } },
31
- requested: true
32
- }
33
- }
34
-
35
- /** Pi preserves the provider reasoning item for both WebSocket and SSE replay.
36
- * Read only its explicit summary: Pi's generic thinking field can also contain raw reasoning.
37
- */
38
- export function completedReasoningSummary(message: unknown): string | undefined {
39
- if (!isRecord(message) || message.role !== 'assistant' || typeof message.api !== 'string' || !REASONING_SUMMARY_APIS.has(message.api) || !Array.isArray(message.content)) return undefined
40
- const parts: string[] = []
41
- const seen = new Set<string>()
42
- for (const block of message.content) {
43
- if (!isRecord(block) || block.type !== 'thinking' || typeof block.thinkingSignature !== 'string') continue
44
- try {
45
- const item: unknown = JSON.parse(block.thinkingSignature)
46
- if (!isRecord(item) || item.type !== 'reasoning' || !Array.isArray(item.summary)) continue
47
- if (typeof item.id === 'string') {
48
- if (seen.has(item.id)) continue
49
- seen.add(item.id)
50
- }
51
- for (const part of item.summary) {
52
- if (isRecord(part) && part.type === 'summary_text' && typeof part.text === 'string') parts.push(part.text)
53
- }
54
- } catch {
55
- // Signatures of other formats, or incomplete items, are not summary evidence.
56
- }
57
- }
58
- return cleanSummary(parts.join('\n\n'))
59
- }
@@ -1,381 +0,0 @@
1
- // Live runs. Assigns per-run sequence numbers, validates every event against the contract,
2
- // persists it, hands it to listeners, and tracks interrupt, approval, and question handlers.
3
- import { randomUUID } from 'node:crypto'
4
-
5
- import { log } from '../core/bus'
6
- import { HarnessError } from '../core/errors'
7
- import type { AutomaticReason } from './approvals'
8
- import { isActiveStatus, runEventSchema, type QuestionOption, type RunEvent, type RunEventType, type RunRecord } from './contracts'
9
- import { findRun, persistEvent, readEvents, runFamily } from './runStore'
10
-
11
- export type ApprovalDecision = 'approved' | 'denied' | 'native'
12
-
13
- export interface ApprovalInput {
14
- requestId?: string
15
- operation?: { tool: string; args: Record<string, unknown> }
16
- target: string
17
- action: string
18
- screenshotRef?: string
19
- /** A tool the user may choose to always allow for this session. */
20
- rememberable?: boolean
21
- /** `switch`: only the "always approve" switch may grant it. `none`: a person always decides. */
22
- standing?: 'full' | 'switch' | 'none'
23
- /** How long to wait for a decision before the request counts as denied. */
24
- timeoutMs?: number
25
- }
26
-
27
- export interface QuestionInput {
28
- requestId?: string
29
- userOnly?: boolean
30
- summary?: string
31
- question: string
32
- options: QuestionOption[]
33
- multiSelect: boolean
34
- allowText: boolean
35
- }
36
-
37
- export interface QuestionAnswer {
38
- selected: string[]
39
- text?: string
40
- /** Optional notes keyed by the selected choice label. */
41
- notes?: Record<string, string>
42
- }
43
-
44
- interface QuestionBatchMetadata {
45
- batchId: string
46
- batchIndex: number
47
- batchCount: number
48
- }
49
-
50
- interface PendingQuestion {
51
- runId: string
52
- input: QuestionInput
53
- batch?: QuestionBatchMetadata
54
- resolve: (answer: QuestionAnswer) => void
55
- }
56
-
57
- export interface ActiveRun {
58
- runId: string
59
- sessionId: string
60
- emit(type: RunEventType, payload: unknown, native?: unknown): void
61
- onInterrupt(handler: () => Promise<void> | void): void
62
- /** Hands a message to the model after its current step; the session registers how. */
63
- onSteer(handler: (text: string) => Promise<void> | void): void
64
- /** Resolves when the user decides; only the approval with this exact id can be resolved by it. */
65
- requestApproval(input: ApprovalInput): Promise<ApprovalDecision>
66
- /** Asks the user a question and resolves with their answer. */
67
- requestAnswer(input: QuestionInput): Promise<QuestionAnswer>
68
- /** Asks one to five related questions and resolves only after the whole batch is answered. */
69
- requestAnswers(inputs: QuestionInput[]): Promise<QuestionAnswer[]>
70
- finish(outcome: 'completed' | 'failed' | 'interrupted', failure?: { code: string; message: string }): void
71
- readonly finished: boolean
72
- }
73
-
74
- /** Called with every persisted event, and the run's record as it is after that event. */
75
- export type RunListener = (event: RunEvent, run: RunRecord | null) => void
76
-
77
- export interface RegistryOptions {
78
- root: () => string
79
- /** Why this approval can be granted without asking, if it can. */
80
- automatic?: (run: RunRecord, target: string, operation: ApprovalInput['operation'], standing: 'full' | 'switch') => Promise<AutomaticReason | null>
81
- /** Called when a run stops being live, whatever its outcome. */
82
- ended?: (runId: string, sessionId: string) => void
83
- /** Removes secrets from an event before it is stored or shown. */
84
- redact?: (event: RunEvent) => void
85
- }
86
-
87
- type LiveRun = ActiveRun & { interrupt: () => Promise<void>; steer: (text: string) => Promise<void> }
88
-
89
- export class RunRegistry {
90
- private readonly runs = new Map<string, LiveRun>()
91
- private readonly approvals = new Map<string, { runId: string; resolve: (decision: ApprovalDecision) => void }>()
92
- private readonly questions = new Map<string, PendingQuestion>()
93
- private readonly nativeCleared = new Map<string, string>()
94
- private readonly stopping = new Set<string>()
95
- private readonly listeners: RunListener[] = []
96
-
97
- constructor(private readonly options: RegistryOptions) {}
98
-
99
- /** Observers see events after they are persisted, in order. */
100
- listen(listener: RunListener): void {
101
- this.listeners.push(listener)
102
- }
103
-
104
- private deliver(event: RunEvent): boolean {
105
- const root = this.options.root()
106
- try {
107
- this.options.redact?.(event)
108
- if (!persistEvent(root, event)) return false
109
- } catch (error) {
110
- log(`could not persist event for ${event.runId}: ${error instanceof Error ? error.message : String(error)}`)
111
- return false
112
- }
113
- const run = findRun(root, event.runId)
114
- for (const listener of this.listeners) {
115
- try {
116
- listener(event, run)
117
- } catch (error) {
118
- log('a run listener failed', error instanceof Error ? error.message : String(error))
119
- }
120
- }
121
- return true
122
- }
123
-
124
- /** Starts tracking a run whose record is already saved. */
125
- start(sessionId: string, runId: string = randomUUID()): ActiveRun {
126
- let sequence = 0
127
- try {
128
- sequence = readEvents(this.options.root(), runId).reduce((highest, event) => Math.max(highest, event.sequence + 1), 0)
129
- } catch {
130
- sequence = 0
131
- }
132
- let finished = false
133
- const interruptHandlers: Array<() => Promise<void> | void> = []
134
- let steerHandler: ((text: string) => Promise<void> | void) | null = null
135
- const waitingStatus = (): string =>
136
- [...this.approvals.values()].some((request) => request.runId === runId) ? 'waiting_for_approval' : [...this.questions.values()].some((request) => request.runId === runId) ? 'waiting_for_input' : 'running'
137
-
138
- const requestQuestion = (input: QuestionInput, batch?: QuestionBatchMetadata, statusEvent = true): Promise<QuestionAnswer> => {
139
- const { requestId, ...payload } = input
140
- const questionId = requestId ?? randomUUID()
141
- if (finished || this.nativeCleared.delete(questionId)) return Promise.resolve({ selected: [] })
142
- if (this.questions.has(questionId)) throw new HarnessError('invalid_request', 'This question id is already pending.')
143
- return new Promise<QuestionAnswer>((resolve) => {
144
- this.questions.set(questionId, {
145
- runId,
146
- input,
147
- ...(batch ? { batch } : {}),
148
- resolve: (answer) => {
149
- this.questions.delete(questionId)
150
- emit('question.answered', { questionId, ...answer, ...(batch ?? {}) })
151
- emit('status.changed', { status: waitingStatus() })
152
- resolve(answer)
153
- }
154
- })
155
- emit('question.requested', { questionId, ...payload, ...(batch ?? {}) })
156
- if (statusEvent) emit('status.changed', { status: 'waiting_for_input' })
157
- })
158
- }
159
-
160
- const emit = (type: RunEventType, payload: unknown, native?: unknown): void => {
161
- if (finished) return
162
- const parsed = runEventSchema.safeParse({ id: randomUUID(), runId, sessionId, sequence, timestamp: new Date().toISOString(), type, payload, ...(native === undefined ? {} : { native }) })
163
- if (!parsed.success) {
164
- log(`dropped invalid ${type} event for run ${runId}`)
165
- return
166
- }
167
- sequence += 1
168
- this.deliver(parsed.data)
169
- }
170
-
171
- const run: LiveRun = {
172
- runId,
173
- sessionId,
174
- emit,
175
- onInterrupt: (handler) => void interruptHandlers.push(handler),
176
- onSteer: (handler) => {
177
- steerHandler = handler
178
- },
179
- steer: async (text) => {
180
- if (finished || !steerHandler) throw new HarnessError('run_not_active', 'This run is not accepting messages.')
181
- await steerHandler(text)
182
- },
183
- requestApproval: async (input) => {
184
- const { requestId, standing = 'full', timeoutMs, ...payload } = input
185
- const approvalId = requestId ?? randomUUID()
186
- // What the user already allowed is known here; if it cannot be read, ask as usual.
187
- const record = findRun(this.options.root(), runId)
188
- const automatic = record && this.options.automatic && standing !== 'none' ? await this.options.automatic(record, input.target, input.operation, standing).catch(() => null) : null
189
- if (finished) return 'denied'
190
- if (this.nativeCleared.delete(approvalId)) return 'native'
191
- if (automatic) {
192
- // Marked on the request too, so nothing treats it as waiting on someone.
193
- emit('approval.requested', { approvalId, ...payload, automatic })
194
- emit('approval.resolved', { approvalId, decision: 'approved', automatic })
195
- return 'approved'
196
- }
197
- emit('approval.requested', { approvalId, ...payload })
198
- emit('status.changed', { status: 'waiting_for_approval' })
199
- return new Promise<ApprovalDecision>((resolve) => {
200
- const timer = timeoutMs ? setTimeout(() => this.approvals.get(approvalId)?.resolve('denied'), timeoutMs) : null
201
- this.approvals.set(approvalId, {
202
- runId,
203
- resolve: (decision) => {
204
- if (timer) clearTimeout(timer)
205
- this.approvals.delete(approvalId)
206
- emit('approval.resolved', { approvalId, decision })
207
- emit('status.changed', { status: waitingStatus() })
208
- resolve(decision)
209
- }
210
- })
211
- })
212
- },
213
- requestAnswer: (input) => requestQuestion(input),
214
- requestAnswers: (inputs) => {
215
- if (!Array.isArray(inputs) || inputs.length < 1 || inputs.length > 5) {
216
- throw new HarnessError('invalid_request', 'A question batch must contain between one and five questions.')
217
- }
218
- const requestedIds = inputs.flatMap((input) => input.requestId ? [input.requestId] : [])
219
- if (new Set(requestedIds).size !== requestedIds.length || requestedIds.some((id) => this.questions.has(id))) {
220
- throw new HarnessError('invalid_request', 'Question ids in a batch must be unique and not already pending.')
221
- }
222
- if (finished) return Promise.resolve(inputs.map(() => ({ selected: [] })))
223
- const batchId = randomUUID()
224
- const answers = inputs.map((input, index) => requestQuestion(input, { batchId, batchIndex: index + 1, batchCount: inputs.length }, false))
225
- emit('status.changed', { status: 'waiting_for_input' })
226
- return Promise.all(answers)
227
- },
228
- finish: (outcome, failure) => {
229
- if (finished) return
230
- if (outcome === 'failed') emit('failed', failure ?? { code: 'failed', message: 'The run failed.' })
231
- else if (outcome === 'interrupted') emit('status.changed', { status: 'interrupted' })
232
- else emit('completed', {})
233
- finished = true
234
- this.runs.delete(runId)
235
- for (const [id, owner] of this.nativeCleared) if (owner === runId) this.nativeCleared.delete(id)
236
- for (const [, approval] of [...this.approvals]) if (approval.runId === runId) approval.resolve('denied')
237
- for (const [, question] of [...this.questions]) if (question.runId === runId) question.resolve({ selected: [] })
238
- try {
239
- this.options.ended?.(runId, sessionId)
240
- } catch (error) {
241
- log('a run could not be closed cleanly', error instanceof Error ? error.message : String(error))
242
- }
243
- },
244
- get finished() {
245
- return finished
246
- },
247
- interrupt: async () => {
248
- for (const handler of interruptHandlers) {
249
- try {
250
- await handler()
251
- } catch (error) {
252
- log(`an interrupt handler failed for run ${runId}`, error instanceof Error ? error.message : String(error))
253
- }
254
- }
255
- run.finish('interrupted')
256
- }
257
- }
258
-
259
- this.runs.set(runId, run)
260
- emit('started', {})
261
- emit('status.changed', { status: 'running' })
262
- const record = findRun(this.options.root(), runId)
263
- if (record?.parentRunId && this.hasStoppedAncestor(record.parentRunId)) run.finish('interrupted')
264
- return run
265
- }
266
-
267
- private hasStoppedAncestor(runId: string): boolean {
268
- const visited = new Set<string>()
269
- let currentId: string | null = runId
270
- while (currentId && !visited.has(currentId)) {
271
- if (this.stopping.has(currentId)) return true
272
- visited.add(currentId)
273
- const record = findRun(this.options.root(), currentId)
274
- if (!record) return false
275
- if (!isActiveStatus(record.status)) return true
276
- currentId = record.parentRunId
277
- }
278
- return false
279
- }
280
-
281
- /** The live run with this id, for a tool or broker that reports into it. */
282
- active(runId: string): ActiveRun | null {
283
- return this.runs.get(runId) ?? null
284
- }
285
-
286
- /** The live run of a session, when it has one. */
287
- activeForSession(sessionId: string): ActiveRun | null {
288
- for (const run of this.runs.values()) if (run.sessionId === sessionId) return run
289
- return null
290
- }
291
-
292
- /** Hands a message to a live run's model after its current step. Throws `run_not_active` when the run cannot take it. */
293
- async steer(runId: string, text: string): Promise<void> {
294
- const run = this.runs.get(runId)
295
- if (!run) throw new HarnessError('run_not_active', 'This run is not active.')
296
- await run.steer(text)
297
- }
298
-
299
- async interrupt(runId: string): Promise<void> {
300
- const run = this.runs.get(runId)
301
- if (!run) throw new HarnessError('run_not_active', 'This run is not active.')
302
- if (this.stopping.has(runId)) return
303
- const family = runFamily(this.options.root(), runId)
304
- const active = family.runs.map(({ run: member }) => member.id).filter((id) => this.runs.has(id))
305
- for (const id of active) this.stopping.add(id)
306
- try {
307
- await Promise.allSettled(active.map((id) => this.runs.get(id)?.interrupt()))
308
- } finally {
309
- for (const id of active) this.stopping.delete(id)
310
- }
311
- }
312
-
313
- /** Interrupts every live run, giving each a moment to stop cleanly. */
314
- async interruptAll(timeoutMs = 3000): Promise<void> {
315
- await Promise.race([Promise.allSettled(this.activeRunIds().map((id) => this.interrupt(id))), new Promise((resolve) => setTimeout(resolve, timeoutMs))])
316
- }
317
-
318
- resolveApproval(runId: string, approvalId: string, decision: ApprovalDecision): void {
319
- if (decision !== 'approved' && decision !== 'denied' && decision !== 'native') throw new HarnessError('invalid_request', 'Unknown decision.')
320
- const approval = this.approvals.get(approvalId)
321
- if (!approval || approval.runId !== runId) throw new HarnessError('approval_not_pending', 'This approval is not pending for this run.')
322
- approval.resolve(decision)
323
- }
324
-
325
- answerQuestion(runId: string, questionId: string, answer: QuestionAnswer): void {
326
- const question = this.questions.get(questionId)
327
- if (!question || question.runId !== runId) throw new HarnessError('question_not_pending', 'This question is not waiting for an answer.')
328
- if (question.batch) throw new HarnessError('question_batch_required', 'Answer every question in this batch together.')
329
- question.resolve(this.validateAnswer(question.input, answer))
330
- }
331
-
332
- answerQuestions(runId: string, batchId: string, answers: Array<{ questionId: string; answer: QuestionAnswer }>): void {
333
- const questions = [...this.questions.entries()].filter(([, pending]) => pending.runId === runId && pending.batch?.batchId === batchId)
334
- if (!questions.length || answers.length !== questions.length || new Set(answers.map(({ questionId }) => questionId)).size !== answers.length) {
335
- throw new HarnessError('question_not_pending', 'This question batch is not waiting for an answer.')
336
- }
337
- const pendingById = new Map(questions)
338
- const validated = answers.map(({ questionId, answer }) => {
339
- const pending = pendingById.get(questionId)
340
- if (!pending) throw new HarnessError('question_not_pending', 'Every question in the batch must be answered together.')
341
- return { pending, answer: this.validateAnswer(pending.input, answer) }
342
- })
343
- for (const { pending, answer } of validated) pending.resolve(answer)
344
- }
345
-
346
- private validateAnswer(input: QuestionInput, answer: QuestionAnswer): QuestionAnswer {
347
- const selected = answer.selected
348
- const selectedLabels = new Set(selected)
349
- const notes: Record<string, string> = {}
350
- for (const [label, note] of Object.entries(answer.notes ?? {})) {
351
- const normalized = typeof note === 'string' ? note.trim() : ''
352
- if (normalized) notes[label] = normalized
353
- }
354
- const text = answer.text?.trim()
355
- if (
356
- (!input.multiSelect && selected.length > 1) ||
357
- selectedLabels.size !== selected.length ||
358
- selected.some((label) => !input.options.some((option) => option.label === label)) ||
359
- (text && !input.allowText) ||
360
- Object.keys(notes).some((label) => !selectedLabels.has(label)) ||
361
- Object.values(notes).some((note) => note.length > 10_000)
362
- ) {
363
- throw new HarnessError('invalid_answer', 'Choose the offered options or an allowed text answer, and attach notes only to selected choices.')
364
- }
365
- return { selected, ...(text ? { text } : {}), ...(Object.keys(notes).length ? { notes } : {}) }
366
- }
367
-
368
- activeRunIds(): string[] {
369
- return [...this.runs.keys()]
370
- }
371
-
372
- /** A request the session's own interface already settled: nothing here is waiting on it any more. */
373
- nativeResolved(runId: string, requestId: string): void {
374
- if (!this.runs.has(runId)) return
375
- const approval = this.approvals.get(requestId)
376
- if (approval?.runId === runId) return approval.resolve('native')
377
- const question = this.questions.get(requestId)
378
- if (question?.runId === runId) return question.resolve({ selected: [] })
379
- this.nativeCleared.set(requestId, runId)
380
- }
381
- }
@@ -1,99 +0,0 @@
1
- // Run metadata in the index: which runs a session, an agent, or an account has, without
2
- // reading every run folder.
3
- import type { DatabaseSync } from 'node:sqlite'
4
- import { join } from 'node:path'
5
-
6
- import { readJson } from '../core/fs'
7
- import { all, run as execute, runFolders, transaction, withIndex } from '../core/index'
8
- import { runRecordSchema, type RunRecord } from './contracts'
9
-
10
- export function upsertRun(database: DatabaseSync, record: RunRecord): void {
11
- execute(
12
- database,
13
- `INSERT OR REPLACE INTO runs (id, project_id, mode, harness, session_type, session_id, status, started_at, ended_at, account_id, agent_id)
14
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)`,
15
- record.id,
16
- record.projectId,
17
- record.mode,
18
- record.harness,
19
- record.sessionType,
20
- record.sessionId,
21
- record.status,
22
- record.startedAt,
23
- record.endedAt,
24
- record.accountId,
25
- record.agentId
26
- )
27
- }
28
-
29
- /** Index failures never block a run. */
30
- export function recordRun(root: string, record: RunRecord): void {
31
- try {
32
- withIndex(root, (database) => upsertRun(database, record))
33
- } catch {
34
- // The index is rebuilt from run files when it is next repaired.
35
- }
36
- }
37
-
38
- /** Every readable run record under `<data root>/runs`. */
39
- export function readAllRuns(root: string): RunRecord[] {
40
- const records: RunRecord[] = []
41
- for (const name of runFolders(root)) {
42
- try {
43
- const parsed = runRecordSchema.safeParse(readJson(join(root, 'runs', name, 'run.json')))
44
- if (parsed.success) records.push(parsed.data)
45
- } catch {
46
- // Not a run folder.
47
- }
48
- }
49
- return records
50
- }
51
-
52
- /**
53
- * Adds the runs the table is missing, and those whose status changed, from the run files. A run
54
- * recorded while the index was unavailable would otherwise be absent from session history.
55
- */
56
- export function syncRuns(root: string): number {
57
- const known = new Map<string, { status: string | null; agentId: string | null }>()
58
- withIndex(root, (database) => {
59
- for (const row of all<{ id: string; status: string | null; agent_id: string | null }>(database, 'SELECT id, status, agent_id FROM runs')) known.set(row.id, { status: row.status, agentId: row.agent_id })
60
- })
61
- // A row is rewritten when its status changed, or when it predates the agent column.
62
- const pending = readAllRuns(root).filter((record) => {
63
- const row = known.get(record.id)
64
- return !row || row.status !== record.status || (row.agentId === null && record.agentId !== null)
65
- })
66
- if (!pending.length) return 0
67
- withIndex(root, (database) => transaction(database, () => pending.forEach((record) => upsertRun(database, record))))
68
- return pending.length
69
- }
70
-
71
- export function runsForSession(root: string, sessionId: string, limit: number): string[] {
72
- return withIndex(root, (database) => all<{ id: string }>(database, 'SELECT id FROM runs WHERE session_id = ?1 ORDER BY started_at DESC LIMIT ?2', sessionId, limit).map((row) => row.id))
73
- }
74
-
75
- /** Which runs to read: one session's, one agent's wherever it replied, one account's, or all. */
76
- export interface RunFilter {
77
- session?: string | null
78
- agent?: string | null
79
- account?: string | null
80
- }
81
-
82
- /** Runs matching `filter` started at or after `since` (an RFC 3339 instant), oldest first. */
83
- export function runsSince(root: string, filter: RunFilter, since: string | null): string[] {
84
- return withIndex(root, (database) =>
85
- // A chat run recorded before the agent column belongs to the agent whose own session it ran in.
86
- all<{ id: string }>(
87
- database,
88
- `SELECT id FROM runs WHERE started_at >= ?1
89
- AND (?2 IS NULL OR session_id = ?2)
90
- AND (?3 IS NULL OR agent_id = ?3 OR (agent_id IS NULL AND mode = 'chat' AND session_id = ?3))
91
- AND (?4 IS NULL OR account_id = ?4)
92
- ORDER BY started_at`,
93
- since ?? '',
94
- filter.session ?? null,
95
- filter.agent ?? null,
96
- filter.account ?? null
97
- ).map((row) => row.id)
98
- )
99
- }