@xingular/harness 0.1.6 → 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 (593) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +60 -0
  4. package/README.md +265 -71
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +14842 -9445
  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 +1170 -62
  373. package/docs/README.md +34 -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-0001-owned-terminal.md +87 -0
  403. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  404. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  405. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  406. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  407. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  408. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  409. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  410. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  411. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  412. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  413. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  414. package/docs/decisions/ADR-0013-doctor.md +27 -0
  415. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  416. package/docs/doctor.md +74 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  418. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  420. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  421. package/docs/features/README.md +20 -0
  422. package/docs/features/automations/README.md +41 -0
  423. package/docs/features/cores/README.md +39 -0
  424. package/docs/features/google-harness2/README.md +52 -0
  425. package/docs/features/integrations/README.md +40 -0
  426. package/docs/features/interfaces/README.md +29 -0
  427. package/docs/features/memory/README.md +28 -0
  428. package/docs/releases/1.0.0.md +40 -0
  429. package/docs/releases/README.md +36 -0
  430. package/docs/study/00-index.md +78 -0
  431. package/docs/study/arms/00-matrix.md +20 -0
  432. package/docs/study/arms/01-system-prompt.md +211 -0
  433. package/docs/study/arms/02-tools.md +79 -0
  434. package/docs/study/arms/03-subagents.md +90 -0
  435. package/docs/study/arms/04-skills.md +75 -0
  436. package/docs/study/arms/05-context-management.md +90 -0
  437. package/docs/study/arms/06-memory.md +90 -0
  438. package/docs/study/arms/07-governance.md +71 -0
  439. package/docs/study/arms/08-execution.md +69 -0
  440. package/docs/study/arms/09-observability.md +60 -0
  441. package/docs/study/arms/10-refinement.md +110 -0
  442. package/docs/study/btw-comparison.md +37 -0
  443. package/docs/study/feature-gap-review.md +42 -0
  444. package/docs/study/insights.md +123 -0
  445. package/docs/study/roadmap.md +72 -0
  446. package/docs/study/sources/claude-code.md +44 -0
  447. package/docs/study/sources/deepseek-harness.md +102 -0
  448. package/docs/study/sources/harness2.md +50 -0
  449. package/docs/study/sources/kimi-cli.md +42 -0
  450. package/docs/study/sources/omp.md +93 -0
  451. package/docs/study/sources/opencode.md +43 -0
  452. package/docs/study/sources/openhands.md +46 -0
  453. package/docs/study/sources/smolagents.md +40 -0
  454. package/docs/study/sources/swe-agent.md +34 -0
  455. package/docs/system-prompt-design.md +196 -0
  456. package/docs/terminal-tui.md +671 -0
  457. package/package.json +48 -12
  458. package/src/accounts/accounts.test.ts +0 -223
  459. package/src/accounts/accounts.ts +0 -522
  460. package/src/accounts/env.test.ts +0 -95
  461. package/src/accounts/env.ts +0 -338
  462. package/src/accounts/secrets.ts +0 -50
  463. package/src/accounts/store.ts +0 -338
  464. package/src/capabilities/api.ts +0 -75
  465. package/src/capabilities/runSnapshot.ts +0 -59
  466. package/src/capabilities/types.ts +0 -34
  467. package/src/cli.ts +0 -114
  468. package/src/core/bus.ts +0 -34
  469. package/src/core/changes.ts +0 -33
  470. package/src/core/env.ts +0 -27
  471. package/src/core/errors.ts +0 -32
  472. package/src/core/frontmatter.ts +0 -47
  473. package/src/core/fs.test.ts +0 -38
  474. package/src/core/fs.ts +0 -92
  475. package/src/core/index.ts +0 -193
  476. package/src/core/path.test.ts +0 -14
  477. package/src/core/path.ts +0 -79
  478. package/src/core/projects.ts +0 -90
  479. package/src/core/text.ts +0 -39
  480. package/src/harness.ts +0 -299
  481. package/src/index.ts +0 -70
  482. package/src/mcp/connections.ts +0 -614
  483. package/src/mcp/manager.ts +0 -130
  484. package/src/mcp/oauth.ts +0 -195
  485. package/src/mcp/scopeMigration.test.ts +0 -79
  486. package/src/mcp/scopeMigration.ts +0 -204
  487. package/src/mcp/service.test.ts +0 -376
  488. package/src/mcp/service.ts +0 -549
  489. package/src/mcp/types.ts +0 -108
  490. package/src/memory/api.test.ts +0 -82
  491. package/src/memory/api.ts +0 -289
  492. package/src/memory/blocks.test.ts +0 -78
  493. package/src/memory/blocks.ts +0 -406
  494. package/src/memory/caller.ts +0 -57
  495. package/src/memory/dispatch.ts +0 -59
  496. package/src/memory/facts.test.ts +0 -41
  497. package/src/memory/facts.ts +0 -248
  498. package/src/memory/graph.ts +0 -103
  499. package/src/memory/health.test.ts +0 -130
  500. package/src/memory/health.ts +0 -74
  501. package/src/memory/maintainer.ts +0 -272
  502. package/src/memory/maintenance.test.ts +0 -176
  503. package/src/memory/maintenance.ts +0 -330
  504. package/src/memory/migrate.ts +0 -79
  505. package/src/memory/operations.ts +0 -138
  506. package/src/memory/proposals.test.ts +0 -168
  507. package/src/memory/proposals.ts +0 -576
  508. package/src/memory/recall.test.ts +0 -104
  509. package/src/memory/recall.ts +0 -271
  510. package/src/memory/references.ts +0 -77
  511. package/src/memory/runContext.ts +0 -93
  512. package/src/memory/secrets.ts +0 -6
  513. package/src/memory/store.test.ts +0 -66
  514. package/src/memory/store.ts +0 -385
  515. package/src/memory/wiki.test.ts +0 -47
  516. package/src/memory/wiki.ts +0 -422
  517. package/src/memory/wikiIndex.test.ts +0 -88
  518. package/src/memory/wikiIndex.ts +0 -116
  519. package/src/plugins/api.ts +0 -181
  520. package/src/plugins/attachments.test.ts +0 -84
  521. package/src/plugins/attachments.ts +0 -141
  522. package/src/plugins/builtin.ts +0 -82
  523. package/src/plugins/catalogue.test.ts +0 -254
  524. package/src/plugins/catalogue.ts +0 -251
  525. package/src/plugins/cli.ts +0 -184
  526. package/src/plugins/discover.ts +0 -151
  527. package/src/plugins/firstParty.test.ts +0 -143
  528. package/src/plugins/firstParty.ts +0 -129
  529. package/src/plugins/hooks.test.ts +0 -250
  530. package/src/plugins/hooks.ts +0 -239
  531. package/src/plugins/identity.ts +0 -37
  532. package/src/plugins/install.test.ts +0 -107
  533. package/src/plugins/install.ts +0 -106
  534. package/src/plugins/inventory.ts +0 -123
  535. package/src/plugins/manifest.ts +0 -76
  536. package/src/plugins/plugins.test.ts +0 -205
  537. package/src/plugins/plugins.ts +0 -189
  538. package/src/plugins/proposal.ts +0 -121
  539. package/src/plugins/runtime.test.ts +0 -40
  540. package/src/plugins/runtime.ts +0 -82
  541. package/src/plugins/trust.ts +0 -142
  542. package/src/plugins/types.ts +0 -149
  543. package/src/prompt/compile.test.ts +0 -261
  544. package/src/prompt/compile.ts +0 -732
  545. package/src/server/methods.ts +0 -314
  546. package/src/server/remote.ts +0 -77
  547. package/src/server/rpc.ts +0 -116
  548. package/src/server/serve.ts +0 -28
  549. package/src/server/server.test.ts +0 -174
  550. package/src/sessions/approvals.ts +0 -118
  551. package/src/sessions/contracts.ts +0 -310
  552. package/src/sessions/conversation.test.ts +0 -150
  553. package/src/sessions/extensionSession.test.ts +0 -74
  554. package/src/sessions/extensionUi.test.ts +0 -65
  555. package/src/sessions/extensionUi.ts +0 -102
  556. package/src/sessions/history.ts +0 -51
  557. package/src/sessions/lineageJoin.ts +0 -75
  558. package/src/sessions/policy.ts +0 -32
  559. package/src/sessions/pricing.ts +0 -60
  560. package/src/sessions/reasoningSummaries.ts +0 -59
  561. package/src/sessions/registry.ts +0 -294
  562. package/src/sessions/runIndex.ts +0 -99
  563. package/src/sessions/runStore.test.ts +0 -152
  564. package/src/sessions/runStore.ts +0 -332
  565. package/src/sessions/runner.ts +0 -569
  566. package/src/sessions/runtimeResources.test.ts +0 -61
  567. package/src/sessions/sessions.test.ts +0 -455
  568. package/src/sessions/sessions.ts +0 -295
  569. package/src/skills/registry.test.ts +0 -104
  570. package/src/skills/registry.ts +0 -407
  571. package/src/terminal/cli.ts +0 -149
  572. package/src/terminal/client.ts +0 -74
  573. package/src/terminal/controller.ts +0 -227
  574. package/src/terminal/launch.test.ts +0 -34
  575. package/src/terminal/launch.ts +0 -88
  576. package/src/terminal/piExtension.ts +0 -210
  577. package/src/terminal/pluginControl.test.ts +0 -146
  578. package/src/terminal/pluginMenu.ts +0 -112
  579. package/src/terminal/socket.test.ts +0 -71
  580. package/src/terminal/socket.ts +0 -221
  581. package/src/terminal/standalone.test.ts +0 -130
  582. package/src/terminal/standalone.ts +0 -144
  583. package/src/terminal/terminal.test.ts +0 -330
  584. package/src/terminal/terminals.ts +0 -443
  585. package/src/tools/askUser.ts +0 -45
  586. package/src/tools/definitions.ts +0 -187
  587. package/src/tools/memoryTools.ts +0 -22
  588. package/src/tools/pluginPropose.ts +0 -41
  589. package/src/tools/types.ts +0 -39
  590. package/src/web/safeRequest.ts +0 -171
  591. package/src/web/text.ts +0 -53
  592. package/src/web/tools.ts +0 -134
  593. package/src/web/web.test.ts +0 -141
@@ -1,104 +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 { writeFile } from '../../tests/helpers'
7
- import { createEnv, type HarnessEnv } from '../core/env'
8
- import { newId, writeJson } from '../core/fs'
9
- import { closeIndex } from '../core/index'
10
- import { runRecordSchema, type RunRecord } from '../sessions/contracts'
11
- import { parseEvent } from '../sessions/runStore'
12
- import type { CallerContext } from './caller'
13
- import { passages, read, readTool, search, searchTool, sync } from './recall'
14
-
15
- const run = (id: string, mode: string, session: string, project: string | null, goal: string): RunRecord =>
16
- runRecordSchema.parse({ id, projectId: project, mode, harness: 'pi', sessionType: 'structured', sessionId: session, nativeSessionId: null, workingDirectory: null, worktreeId: null, goal, startedAt: '2026-10-01T10:00:00.000Z', endedAt: '2026-10-01T10:01:00.000Z', status: 'completed' })
17
-
18
- const event = (runId: string, type: string, payload: unknown) => ({ id: newId(), runId, sessionId: 's', sequence: 1, timestamp: '2026-10-01T10:00:30.000Z', type, payload })
19
-
20
- function save(root: string, record: RunRecord, events: unknown[]): void {
21
- writeJson(join(root, 'runs', record.id, 'run.json'), record)
22
- writeFile(join(root, 'runs', record.id, 'events.jsonl'), `${events.map((entry) => JSON.stringify(entry)).join('\n')}\n`)
23
- }
24
-
25
- const roots: string[] = []
26
- afterEach(() => roots.splice(0).forEach(closeIndex))
27
-
28
- function setup(): HarnessEnv {
29
- const root = mkdtempSync(join(tmpdir(), 'harness-recall-'))
30
- roots.push(root)
31
- writeJson(join(root, 'projects.json'), [
32
- { id: 'p1', name: 'App', slug: 'app', rootPath: '/tmp/app', autoMaintenance: true, createdAt: 't' },
33
- { id: 'p2', name: 'Site', slug: 'site', rootPath: '/tmp/site', autoMaintenance: true, createdAt: 't' }
34
- ])
35
- save(root, run('chat-1', 'chat', 'agent-a', null, 'Which package manager do we use?'), [
36
- event('chat-1', 'tool.started', { toolCallId: 't1', name: 'read', summary: 'package.json' }),
37
- event('chat-1', 'message.completed', { messageId: 'm1', role: 'assistant', text: 'We use pnpm for every workspace.' })
38
- ])
39
- save(root, run('chat-2', 'chat', 'agent-b', null, 'Plan the launch'), [event('chat-2', 'message.completed', { messageId: 'm1', role: 'assistant', text: 'The launch is on Friday; pnpm build first.' })])
40
- save(root, run('code-1', 'code', 'pane-1', 'p1', 'Fix the pnpm lockfile'), [event('code-1', 'message.completed', { messageId: 'm1', role: 'assistant', text: 'Regenerated the lockfile.' })])
41
- save(root, run('code-2', 'code', 'pane-2', 'p2', 'Deploy the site with pnpm'), [])
42
- return createEnv(root, { directory: { agentName: (id) => (id === 'agent-a' ? 'Nora' : id === 'agent-b' ? 'Kai' : null), sessionAgent: () => null } })
43
- }
44
-
45
- const agent = (id: string): CallerContext => ({ agentId: id, actor: 'Chat' })
46
-
47
- test('a run becomes its request, messages and tool summaries', () => {
48
- const record = run('r', 'chat', 'a', null, '[App coordination event e1 / review — not a user message]')
49
- const events = [event('r', 'tool.started', { toolCallId: 't1', name: 'grep', summary: 'TODO' }), event('r', 'message.completed', { messageId: 'm1', role: 'assistant', text: ' Done. ' }), event('r', 'message.delta', { messageId: 'm1', text: 'x' })].flatMap((entry) => parseEvent(entry) ?? [])
50
- const found = passages(record, events)
51
- expect(found.map((passage) => passage.role)).toEqual(['event', 'tool', 'assistant'])
52
- expect(found[1].text).toBe('grep: TODO')
53
- expect(found[2].text).toBe('Done.')
54
- })
55
-
56
- test('sync indexes missing runs once and reindexes changed ones', () => {
57
- const { root } = setup()
58
- expect(sync(root)).toBe(4)
59
- expect(sync(root)).toBe(0)
60
- save(root, { ...run('code-2', 'code', 'pane-2', 'p2', 'Deploy the site with pnpm'), status: 'failed' }, [event('code-2', 'message.completed', { messageId: 'm1', role: 'assistant', text: 'Wrangler failed pnpm.' })])
61
- expect(sync(root)).toBe(1)
62
- expect(read(root, 'code-2')).toHaveLength(2)
63
- expect(search(root, 'pnpm', {}, 30)).toHaveLength(5)
64
- })
65
-
66
- test('an agent recalls its own chats by default and everything on request', () => {
67
- const env = setup()
68
- sync(env.root)
69
- const mine = searchTool(env, agent('agent-a'), { query: 'pnpm package manager' })
70
- expect(mine).toContain('run chat-1')
71
- expect(mine).toContain('chat with Nora')
72
- expect(mine).not.toContain('chat-2')
73
- expect(mine).not.toContain('code-1')
74
- const all = searchTool(env, agent('agent-a'), { query: 'pnpm', scope: 'all' })
75
- expect(all).toContain('chat-2')
76
- expect(all).toContain('code-1')
77
- expect(all).toContain('Harness session in App')
78
- const project = searchTool(env, agent('agent-a'), { query: 'pnpm', project: 'site' })
79
- expect(project).toContain('code-2')
80
- expect(project).not.toContain('code-1')
81
- expect(searchTool(env, agent('agent-a'), { query: 'zebra' })).toContain('scope "all"')
82
- expect(searchTool(env, agent('agent-a'), { query: 'pnpm', since: '2027-01-01' })).toContain('Nothing')
83
- const transcript = readTool(env, agent('agent-a'), { run: 'chat-2' })
84
- expect(transcript).toContain('user: Plan the launch')
85
- expect(transcript).toContain('assistant: The launch is on Friday')
86
- // The run a caller is in is not offered back to it.
87
- expect(searchTool(env, { ...agent('agent-a'), runId: 'chat-1' }, { query: 'pnpm' })).not.toContain('run chat-1')
88
- })
89
-
90
- test('a session recalls only session runs of its project', () => {
91
- const env = setup()
92
- sync(env.root)
93
- const session: CallerContext = { sessionId: 'pane-9', projectId: 'p1', actor: 'Code' }
94
- const hits = searchTool(env, session, { query: 'pnpm', scope: 'all' })
95
- expect(hits).toContain('code-1')
96
- for (const other of ['chat-1', 'chat-2', 'code-2']) expect(hits).not.toContain(other)
97
- expect(readTool(env, session, { run: 'code-1' })).toContain('Run code-1')
98
- expect(() => readTool(env, session, { run: 'chat-1' })).toThrow()
99
- expect(() => readTool(env, session, { run: 'code-2' })).toThrow()
100
- // Without a project, a session sees only its own runs.
101
- const loose: CallerContext = { sessionId: 'pane-1', actor: 'Code' }
102
- expect(searchTool(env, loose, { query: 'pnpm' })).toContain('code-1')
103
- expect(() => readTool(env, loose, { run: 'code-2' })).toThrow()
104
- })
@@ -1,271 +0,0 @@
1
- // Recall: the searchable record of what happened in conversations and runs. Each run's request,
2
- // assistant messages, and tool summaries are indexed as passages in `index.sqlite`. Run records
3
- // and events stay canonical; the recall index is rebuilt from `runs/`.
4
- import type { DatabaseSync } from 'node:sqlite'
5
-
6
- import type { HarnessEnv } from '../core/env'
7
- import { invalid, notFound } from '../core/errors'
8
- import { all, run as execute, transaction, withIndex } from '../core/index'
9
- import { findProject, listProjects } from '../core/projects'
10
- import { charCount, takeChars } from '../core/text'
11
- import type { RunEvent, RunRecord } from '../sessions/contracts'
12
- import { readAllRuns } from '../sessions/runIndex'
13
- import { findRun, readEvents } from '../sessions/runStore'
14
- import { isSession, projectOf, type CallerContext } from './caller'
15
-
16
- const PASSAGE_LIMIT = 6000
17
- const READ_LIMIT = 12_000
18
- const SEARCH_DEFAULT = 8
19
- const SEARCH_MAX = 30
20
-
21
- export interface Passage {
22
- /** `user`, `event` (a turn the application started, not the user), `assistant`, or `tool`. */
23
- role: 'user' | 'event' | 'assistant' | 'tool'
24
- at: string
25
- text: string
26
- }
27
-
28
- /** A run as recall sees it: what was asked, what the assistant said, and which tools it used. */
29
- export function passages(run: RunRecord, events: readonly RunEvent[]): Passage[] {
30
- const found: Passage[] = []
31
- const goal = run.goal?.trim()
32
- if (goal) found.push({ role: goal.startsWith('[App coordination event') ? 'event' : 'user', at: run.startedAt, text: takeChars(goal, PASSAGE_LIMIT) })
33
- for (const event of events) {
34
- const payload = event.payload as { role?: unknown; text?: unknown; name?: unknown; summary?: unknown }
35
- if (event.type === 'message.completed' && payload.role === 'assistant') {
36
- const text = typeof payload.text === 'string' ? payload.text.trim() : ''
37
- if (text) found.push({ role: 'assistant', at: event.timestamp, text: takeChars(text, PASSAGE_LIMIT) })
38
- } else if (event.type === 'tool.started') {
39
- const summary = typeof payload.summary === 'string' ? payload.summary.trim() : ''
40
- if (summary) found.push({ role: 'tool', at: event.timestamp, text: takeChars(`${typeof payload.name === 'string' ? payload.name : 'tool'}: ${summary}`, PASSAGE_LIMIT) })
41
- }
42
- }
43
- return found
44
- }
45
-
46
- function writeRun(database: DatabaseSync, run: RunRecord, found: readonly Passage[]): void {
47
- execute(database, 'DELETE FROM recall_fts WHERE run_id = ?1', run.id)
48
- found.forEach((passage, seq) => {
49
- execute(database, 'INSERT INTO recall_fts (run_id, seq, role, at, mode, session_id, project_id, text) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)', run.id, seq, passage.role, passage.at, run.mode, run.sessionId, run.projectId, passage.text)
50
- })
51
- execute(database, 'INSERT OR REPLACE INTO recall_runs (run_id, passages, status) VALUES (?1, ?2, ?3)', run.id, found.length, run.status)
52
- }
53
-
54
- function eventsOf(root: string, runId: string): RunEvent[] {
55
- try {
56
- return readEvents(root, runId)
57
- } catch {
58
- return []
59
- }
60
- }
61
-
62
- /** Indexes one run from its record and events. Index failures never block a run. */
63
- export function indexRun(root: string, runId: string): void {
64
- const run = findRun(root, runId)
65
- if (!run) return
66
- const found = passages(run, eventsOf(root, runId))
67
- try {
68
- withIndex(root, (database) => writeRun(database, run, found))
69
- } catch (error) {
70
- process.stderr.write(`[recall] run ${runId} was not indexed: ${error instanceof Error ? error.message : String(error)}\n`)
71
- }
72
- }
73
-
74
- /**
75
- * Indexes every run that is missing or whose status changed since it was indexed. Returns how
76
- * many were (re)indexed. Called at startup, so earlier conversations are searchable.
77
- */
78
- export function sync(root: string): number {
79
- const known = new Map<string, string>()
80
- withIndex(root, (database) => {
81
- for (const row of all<{ run_id: string; status: string }>(database, 'SELECT run_id, status FROM recall_runs')) known.set(row.run_id, row.status)
82
- })
83
- const pending = readAllRuns(root)
84
- .filter((run) => known.get(run.id) !== run.status)
85
- .map((run) => ({ run, found: passages(run, eventsOf(root, run.id)) }))
86
- if (pending.length) withIndex(root, (database) => transaction(database, () => pending.forEach(({ run, found }) => writeRun(database, run, found))))
87
- return pending.length
88
- }
89
-
90
- // ---- Search ---------------------------------------------------------------------------------
91
-
92
- /**
93
- * What a caller may recall. An agent searches its own conversations by default and everything
94
- * when it asks; a session only sees session runs in its own project (or its own session when
95
- * it has none), never an agent's conversation.
96
- */
97
- export interface Scope {
98
- /** Only runs of this session. */
99
- sessionId?: string | null
100
- /** Only runs of this mode (`code` for sessions). */
101
- mode?: string | null
102
- projectId?: string | null
103
- /** ISO date or timestamp; only passages at or after it. */
104
- since?: string | null
105
- }
106
-
107
- export interface RecallHit {
108
- runId: string
109
- seq: number
110
- role: string
111
- at: string
112
- mode: string
113
- sessionId: string
114
- projectId: string | null
115
- snippet: string
116
- }
117
-
118
- /** Any word may match; passages that match more of them, and rarer ones, rank first. */
119
- function ftsAny(query: string): string | null {
120
- const terms: string[] = []
121
- for (const word of query.split(/[^\p{Alphabetic}\p{N}]+/u)) {
122
- if (charCount(word) <= 1) continue
123
- const term = `"${word.toLowerCase()}"*`
124
- if (!terms.includes(term) && terms.length < 24) terms.push(term)
125
- }
126
- return terms.length ? terms.join(' OR ') : null
127
- }
128
-
129
- interface HitRow {
130
- run_id: string
131
- seq: number | string
132
- role: string
133
- at: string | null
134
- mode: string | null
135
- session_id: string | null
136
- project_id: string | null
137
- snippet: string
138
- }
139
-
140
- export function search(root: string, query: string, scope: Scope, limit: number): RecallHit[] {
141
- const fts = ftsAny(query)
142
- if (!fts) return []
143
- return withIndex(root, (database) =>
144
- all<HitRow>(
145
- database,
146
- `SELECT run_id, seq, role, at, mode, session_id, project_id, snippet(recall_fts, 7, '', '', '…', 40) AS snippet
147
- FROM recall_fts WHERE recall_fts MATCH ?1
148
- AND (?2 IS NULL OR session_id = ?2) AND (?3 IS NULL OR mode = ?3)
149
- AND (?4 IS NULL OR project_id = ?4) AND (?5 IS NULL OR at >= ?5)
150
- ORDER BY bm25(recall_fts), at DESC LIMIT ?6`,
151
- fts,
152
- scope.sessionId ?? null,
153
- scope.mode ?? null,
154
- scope.projectId ?? null,
155
- scope.since ?? null,
156
- Math.min(Math.max(limit, 1), SEARCH_MAX)
157
- ).map((row) => ({ runId: row.run_id, seq: Number(row.seq), role: row.role, at: row.at ?? '', mode: row.mode ?? '', sessionId: row.session_id ?? '', projectId: row.project_id, snippet: row.snippet }))
158
- )
159
- }
160
-
161
- export interface RecallMessage {
162
- seq: number
163
- role: string
164
- at: string
165
- text: string
166
- }
167
-
168
- export function read(root: string, runId: string): RecallMessage[] {
169
- return withIndex(root, (database) =>
170
- all<{ seq: number | string; role: string; at: string | null; text: string }>(database, 'SELECT seq, role, at, text FROM recall_fts WHERE run_id = ?1 ORDER BY CAST(seq AS INTEGER)', runId).map((row) => ({ seq: Number(row.seq), role: row.role, at: row.at ?? '', text: row.text }))
171
- )
172
- }
173
-
174
- // ---- Tools ----------------------------------------------------------------------------------
175
-
176
- type Params = Record<string, unknown> | null | undefined
177
-
178
- function textParam(params: Params, key: string): string {
179
- const value = params?.[key]
180
- return typeof value === 'string' ? value.trim() : ''
181
- }
182
-
183
- /** The widest scope a caller may use, narrowed by what it asked for. */
184
- function callerScope(root: string, context: CallerContext, params: Params): Scope {
185
- const since = textParam(params, 'since') || null
186
- if (isSession(context)) {
187
- // A session never reads an agent's conversations: only session runs of its project, or its own.
188
- const projectId = projectOf(root, context)?.id ?? null
189
- if (!projectId && !context.sessionId) throw invalid('Recall needs a session.')
190
- return { sessionId: projectId ? null : context.sessionId, mode: 'code', projectId, since }
191
- }
192
- if (!context.agentId) throw invalid('Recall needs an agent or a Harness session.')
193
- const key = textParam(params, 'project')
194
- let projectId: string | null = null
195
- if (key) {
196
- const project = listProjects(root).find((entry) => entry.id === key || entry.slug === key || entry.name.toLowerCase() === key.toLowerCase())
197
- if (!project) throw invalid(`There is no project called ${key}.`)
198
- projectId = project.id
199
- }
200
- const everything = textParam(params, 'scope') === 'all' || projectId !== null
201
- return { sessionId: everything ? null : context.agentId, mode: null, projectId, since }
202
- }
203
-
204
- function mayRead(scope: Scope, run: RunRecord): boolean {
205
- if (!scope.mode) return true
206
- return scope.mode === run.mode && (!scope.projectId || scope.projectId === run.projectId) && (!scope.sessionId || scope.sessionId === run.sessionId)
207
- }
208
-
209
- /** Who a run belonged to, for a person or a model reading a hit. */
210
- export function sourceLabel(env: HarnessEnv, mode: string, sessionId: string, projectId: string | null): string {
211
- if (mode === 'chat') {
212
- // One of an agent's extra conversations has its own id.
213
- const owner = env.directory.sessionAgent(sessionId)
214
- const name = env.directory.agentName(sessionId) ?? (owner ? env.directory.agentName(owner) : null)
215
- return name ? `chat with ${name}` : 'group or earlier chat'
216
- }
217
- try {
218
- return projectId ? `Harness session in ${findProject(env.root, projectId).name}` : 'Harness session'
219
- } catch {
220
- return 'Harness session'
221
- }
222
- }
223
-
224
- /** `recall.search` as text for a model. */
225
- export function searchTool(env: HarnessEnv, context: CallerContext, params: Params): string {
226
- const query = textParam(params, 'query')
227
- if (!query) throw invalid('Give a query.')
228
- const scope = callerScope(env.root, context, params)
229
- const requested = params?.limit
230
- const limit = typeof requested === 'number' && Number.isInteger(requested) && requested >= 0 ? requested : SEARCH_DEFAULT
231
- // The caller's current run is what it is in the middle of, not something to recall.
232
- const hits = search(env.root, query, scope, limit + 4).filter((hit) => hit.runId !== context.runId).slice(0, Math.min(Math.max(limit, 1), SEARCH_MAX))
233
- if (!hits.length) {
234
- return scope.sessionId && !isSession(context) ? 'Nothing in your own conversations matches. Pass scope "all" to search every conversation and Harness run.' : 'Nothing in the recorded history matches.'
235
- }
236
- return `${hits.map((hit) => `- [run ${hit.runId} · ${hit.at.slice(0, 10)} · ${sourceLabel(env, hit.mode, hit.sessionId, hit.projectId)}] ${hit.role}: ${hit.snippet.replaceAll('\n', ' ')}`).join('\n')}\n\nRead a whole run with history_read and its run id.`
237
- }
238
-
239
- /** `recall.read` as text for a model. */
240
- export function readTool(env: HarnessEnv, context: CallerContext, params: Params): string {
241
- const runId = textParam(params, 'run') || textParam(params, 'runId')
242
- const run = findRun(env.root, runId)
243
- if (!run) throw notFound('Run')
244
- // Reading is as wide as an "all" search for an agent, and as narrow as a search for a session.
245
- if (!mayRead(callerScope(env.root, context, { scope: 'all' }), run)) throw notFound('Run')
246
- const messages = read(env.root, run.id)
247
- if (!messages.length) return 'That run has no recorded messages.'
248
- let text = `Run ${run.id} · ${run.startedAt.slice(0, 16)} · ${sourceLabel(env, run.mode, run.sessionId, run.projectId)} · ${run.status}\n`
249
- for (const message of messages) {
250
- const line = `\n${message.role}: ${message.text}\n`
251
- if (charCount(text) + charCount(line) > READ_LIMIT) {
252
- text += '\n(The rest of the run was left out.)\n'
253
- break
254
- }
255
- text += line
256
- }
257
- return text
258
- }
259
-
260
- export interface RecallFilter {
261
- sessionId?: string | null
262
- projectId?: string | null
263
- since?: string | null
264
- }
265
-
266
- export type RecallResult = RecallHit & { source: string }
267
-
268
- /** A person's search: every conversation and run, narrowed only by the filter. */
269
- export function searchAll(env: HarnessEnv, query: string, filter: RecallFilter = {}): RecallResult[] {
270
- return search(env.root, query, { sessionId: filter.sessionId, mode: null, projectId: filter.projectId, since: filter.since || null }, SEARCH_MAX).map((hit) => ({ ...hit, source: sourceLabel(env, hit.mode, hit.sessionId, hit.projectId) }))
271
- }
@@ -1,77 +0,0 @@
1
- // Selected references: Wiki pages and skills a person attached to one request. Each is pinned to
2
- // a revision when it is selected, so what the model reads cannot change under it, and the rest
3
- // of a long reference can be retrieved only at that revision.
4
- import { readFileSync } from 'node:fs'
5
- import { join } from 'node:path'
6
-
7
- import { invalid, notFound } from '../core/errors'
8
- import * as frontmatter from '../core/frontmatter'
9
- import { readJson, safeId } from '../core/fs'
10
- import { charCount } from '../core/text'
11
- import type { Source } from './runContext'
12
- import * as store from './store'
13
- import { entryFile, entryId, resolveEntry } from './wiki'
14
-
15
- export interface PinnedReference {
16
- kind: 'page' | 'skill'
17
- id: string
18
- label: string
19
- revision: string
20
- }
21
-
22
- /**
23
- * Pins the entry's current content. The latest revision is reused when it already holds that
24
- * content; otherwise a new one is written. The entry must be a page or a saved skill.
25
- */
26
- export function pin(root: string, kind: 'page' | 'skill', id: string): string {
27
- return pinAll(root, [{ kind, id }])[0]
28
- }
29
-
30
- /** Pins several entries, resolving every one before any snapshot is written. */
31
- export function pinAll(root: string, items: readonly { kind: 'page' | 'skill'; id: string }[]): string[] {
32
- const wiki = store.wikiDir(root)
33
- const contents = items.map(({ kind, id }) => {
34
- const entry = resolveEntry(root, id)
35
- const valid = kind === 'page' ? entry.kind === 'page' : entry.kind === 'registry' && entry.item.kind === 'skills'
36
- if (!valid || entryId(entry) !== id) throw invalid('The selected reference is not a Wiki page or saved skill.')
37
- return readFileSync(entryFile(entry), 'utf8')
38
- })
39
- return items.map(({ id }, index) => {
40
- const current = store.currentRevision(wiki, id)
41
- if (current) {
42
- try {
43
- if (store.revisionText(wiki, id, current) === contents[index]) return current
44
- } catch {
45
- // The manifest names a revision whose text is gone; pin a new one.
46
- }
47
- }
48
- return store.snapshot(wiki, id, contents[index], 'user', 'Pinned chat reference').id
49
- })
50
- }
51
-
52
- /** The pinned revision's body without its frontmatter. */
53
- export function body(root: string, id: string, revision: string | null): string {
54
- if (!revision) throw invalid('This reference has no pinned revision.')
55
- const text = store.revisionText(store.wikiDir(root), id, revision)
56
- return frontmatter.bodyOf(text)
57
- }
58
-
59
- const PAGE_CHARS = 12_000
60
-
61
- /** A window of a reference that was selected for the caller's current run. */
62
- export function readPinned(root: string, runId: string | null | undefined, id: string, revision: string, offset: number): string {
63
- if (!runId) throw invalid('Pinned references require a current run.')
64
- const pack = readJson<{ sections?: { id: string; sources?: Source[] }[] }>(join(root, 'runs', safeId(runId), 'context.json'))
65
- if (!pack) throw notFound('Run context')
66
- const selected = (pack.sections ?? [])
67
- .filter((section) => section.id === 'references')
68
- .flatMap((section) => section.sources ?? [])
69
- .find((source) => source.id === id && source.revision === revision && (source.kind === 'page' || source.kind === 'skill'))
70
- if (!selected) throw invalid('This revision was not selected for the current reply.')
71
- const characters = Array.from(body(root, id, revision))
72
- const count = characters.length
73
- if (offset > count) throw invalid('The reference offset is past the end.')
74
- const excerpt = characters.slice(offset, offset + PAGE_CHARS).join('')
75
- const end = offset + charCount(excerpt)
76
- return `[${id}@${revision}] · characters ${offset}–${end} of ${count} · nextOffset: ${end < count ? end : 'none'}\n\n${excerpt}`
77
- }
@@ -1,93 +0,0 @@
1
- // What a run was given and what it read: every Wiki entry a run uses is recorded in
2
- // `runs/<id>/wiki-context.json`, so a person can see what informed a reply.
3
- import { join } from 'node:path'
4
-
5
- import { now, readJsonOr, safeId, writeJson } from '../core/fs'
6
- import { runsForSession } from '../sessions/runIndex'
7
- import type { CallerContext } from './caller'
8
- import * as store from './store'
9
-
10
- /** An entry and the revision that was current when it was used. */
11
- export interface Source {
12
- id: string
13
- kind: string
14
- revision: string | null
15
- }
16
-
17
- export interface ContextEntry {
18
- id: string
19
- kind: string
20
- revisionId: string | null
21
- /** `entrypoint`, `search`, `read`, `skill`, `memory`, or `edit` (an entry the run changed). */
22
- via: string
23
- at: string
24
- }
25
-
26
- export function contextPath(root: string, runId: string): string {
27
- return join(root, 'runs', safeId(runId), 'wiki-context.json')
28
- }
29
-
30
- export function readRunContext(root: string, runId: string): ContextEntry[] {
31
- return readJsonOr<ContextEntry[]>(contextPath(root, runId), [])
32
- }
33
-
34
- /** The blocks, facts, and pages these runs changed, without repeats: `[id, kind]`. */
35
- export function editedBy(root: string, runIds: readonly string[]): [string, string][] {
36
- const edited: [string, string][] = []
37
- for (const runId of runIds) {
38
- let entries: ContextEntry[]
39
- try {
40
- entries = readRunContext(root, runId)
41
- } catch {
42
- continue
43
- }
44
- for (const entry of entries) if (entry.via === 'edit' && !edited.some(([id]) => id === entry.id)) edited.push([entry.id, entry.kind])
45
- }
46
- return edited
47
- }
48
-
49
- /** The run a call belongs to: the caller's run, else the session's latest run. */
50
- function runOf(root: string, context: CallerContext): string | null {
51
- if (context.runId) return context.runId
52
- if (!context.sessionId) return null
53
- try {
54
- return runsForSession(root, context.sessionId, 1)[0] ?? null
55
- } catch {
56
- return null
57
- }
58
- }
59
-
60
- export function recordSources(root: string, context: CallerContext, via: string, sources: readonly Source[]): void {
61
- const runId = runOf(root, context)
62
- if (!runId || !sources.length) return
63
- let path: string
64
- try {
65
- path = contextPath(root, runId)
66
- } catch {
67
- return
68
- }
69
- if (!store.isDir(join(root, 'runs', runId))) return
70
- const recorded = readRunContext(root, runId)
71
- for (const source of sources) {
72
- if (!recorded.some((entry) => entry.id === source.id && entry.revisionId === source.revision && entry.via === via)) {
73
- recorded.push({ id: source.id, kind: source.kind, revisionId: source.revision, via, at: now() })
74
- }
75
- }
76
- try {
77
- writeJson(path, recorded)
78
- } catch {
79
- // A record that cannot be written never fails the call it describes.
80
- }
81
- }
82
-
83
- /** `recordSources` for entries at their current revision: `[id, kind]`. */
84
- export function record(root: string, context: CallerContext, via: string, entries: readonly [string, string][]): void {
85
- const wiki = store.wikiDir(root)
86
- recordSources(root, context, via, entries.map(([id, kind]) => ({ id, kind, revision: store.currentRevision(wiki, id) })))
87
- }
88
-
89
- /** `[id@revision]`, the citation form every reply uses. */
90
- export function cite(wiki: string, id: string): string {
91
- const revision = store.currentRevision(wiki, id)
92
- return revision ? `[${id}@${revision.slice(0, 8)}]` : `[${id}]`
93
- }
@@ -1,6 +0,0 @@
1
- const SECRET_MARKERS = ['-----BEGIN', 'sk-ant-', 'sk-proj-', 'ghp_', 'github_pat_', 'AKIA', 'xoxb-']
2
-
3
- /** Text that carries a credential marker is never written to the Wiki. */
4
- export function looksSecret(text: string): boolean {
5
- return SECRET_MARKERS.some((marker) => text.includes(marker))
6
- }
@@ -1,66 +0,0 @@
1
- import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { expect, test } from 'vitest'
5
-
6
- import { ensureLayout, ensureProjectNamespace, importSource, isSkeleton, listSources, locate, namespaceDir, parsePage, projectNamespaceOf, revisionsDir, serializePage, wikiDir } from './store'
7
-
8
- const temp = () => mkdtempSync(join(tmpdir(), 'harness-store-'))
9
-
10
- test('every project has a links page that starts as a map and is never replaced', () => {
11
- const root = temp()
12
- ensureLayout(root)
13
- ensureProjectNamespace(root, 'app', 'App')
14
- const links = join(wikiDir(root), 'projects/app/links.md')
15
- const text = readFileSync(links, 'utf8')
16
- const page = parsePage(text, wikiDir(root), links)!
17
- expect([page.frontmatter.id, page.frontmatter.type]).toEqual(['app-links', 'reference'])
18
- expect(page.body).toContain('one line each')
19
- expect(page.body).toContain('do not copy')
20
- expect(isSkeleton(page.location)).toBe(true)
21
- // The agent's or user's entries survive the next start, which runs this for every project.
22
- writeFileSync(links, text.replace('Nothing recorded yet.', '- docs/specs/product.md: what the app is for'))
23
- ensureProjectNamespace(root, 'app', 'App')
24
- expect(readFileSync(links, 'utf8')).toContain('docs/specs/product.md')
25
- })
26
-
27
- test('derives paths and namespaces from file locations', () => {
28
- const wiki = '/data/wiki'
29
- expect(locate(wiki, '/data/wiki/projects/xingular-agent/design/arch.md')).toEqual({ path: '/projects/xingular-agent/design/arch', namespace: '/projects/xingular-agent' })
30
- expect(locate(wiki, '/data/wiki/library/tauri.md').namespace).toBe('/library')
31
- expect(locate(wiki, '/data/wiki/home.md')).toEqual({ path: '/home', namespace: '/' })
32
- expect(namespaceDir(wiki, '/projects/xingular-agent')).toBe('/data/wiki/projects/xingular-agent')
33
- expect(namespaceDir(wiki, '/')).toBe('/data/wiki/library')
34
- expect(namespaceDir(wiki, '/docs/guides')).toBe('/data/wiki/library/guides')
35
- expect(() => namespaceDir(wiki, '/projects/../x')).toThrow()
36
- expect(() => namespaceDir(wiki, '/facts')).toThrow()
37
- expect(projectNamespaceOf('/projects/a/b')).toBe('/projects/a')
38
- expect(projectNamespaceOf('/library')).toBeNull()
39
- })
40
-
41
- test('imports each source once and versions replacements', () => {
42
- const root = temp()
43
- ensureLayout(root)
44
- const wiki = wikiDir(root)
45
- const first = importSource(wiki, 'notes.md', Buffer.from('one'))
46
- expect(importSource(wiki, 'notes.md', Buffer.from('one')).id).toBe(first.id)
47
- const second = importSource(wiki, 'notes.md', Buffer.from('two'))
48
- expect(second.version).toBe(2)
49
- expect(second.previousId).toBe(first.id)
50
- expect(listSources(wiki)).toHaveLength(2)
51
- })
52
-
53
- test('round-trips frontmatter and drops legacy scope', () => {
54
- const text = '---\nid: a\ntitle: A\ntype: concept\nscope: personal\nsourceIds:\n- src-1\n---\n\nBody\n'
55
- const page = parsePage(text, '/w', '/w/library/a.md')!
56
- const serialized = serializePage(page.frontmatter, page.body)
57
- expect(serialized).not.toContain('scope')
58
- const reparsed = parsePage(serialized, '/w', '/w/library/a.md')!
59
- expect(reparsed.frontmatter.sourceIds).toEqual(['src-1'])
60
- expect(reparsed.body.trim()).toBe('Body')
61
- })
62
-
63
- test('registry ids get revision folders', () => {
64
- expect(revisionsDir('/w', 'skills/review')).toBe('/w/revisions/skills--review')
65
- expect(() => revisionsDir('/w', '../x')).toThrow()
66
- })