@xingular/harness 0.1.7 → 1.1.1

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 (819) hide show
  1. package/CHANGELOG.md +125 -1
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +22 -0
  4. package/README.md +239 -86
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +17853 -13114
  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/agents/builtin.d.ts +2 -0
  18. package/dist/sdk/agents/builtin.js +34 -0
  19. package/dist/sdk/agents/narrow.d.ts +13 -0
  20. package/dist/sdk/agents/narrow.js +29 -0
  21. package/dist/sdk/agents/profiles.d.ts +80 -0
  22. package/dist/sdk/agents/profiles.js +221 -0
  23. package/dist/sdk/annotations/bridge.d.ts +42 -0
  24. package/dist/sdk/annotations/bridge.js +264 -0
  25. package/dist/sdk/annotations/capture.d.ts +116 -0
  26. package/dist/sdk/annotations/capture.js +308 -0
  27. package/dist/sdk/annotations/delivery.d.ts +72 -0
  28. package/dist/sdk/annotations/delivery.js +130 -0
  29. package/dist/sdk/annotations/inspect.d.ts +10 -0
  30. package/dist/sdk/annotations/inspect.js +33 -0
  31. package/dist/sdk/annotations/isolated.d.ts +6 -0
  32. package/dist/sdk/annotations/isolated.js +51 -0
  33. package/dist/sdk/annotations/pageScript.d.ts +28 -0
  34. package/dist/sdk/annotations/pageScript.js +570 -0
  35. package/dist/sdk/annotations/part.d.ts +10 -0
  36. package/dist/sdk/annotations/part.js +144 -0
  37. package/dist/sdk/annotations/queue.d.ts +4 -0
  38. package/dist/sdk/annotations/queue.js +40 -0
  39. package/dist/sdk/annotations/serverMethods.d.ts +3 -0
  40. package/dist/sdk/annotations/serverMethods.js +62 -0
  41. package/dist/sdk/annotations/store.d.ts +160 -0
  42. package/dist/sdk/annotations/store.js +386 -0
  43. package/dist/sdk/browser/config.d.ts +16 -0
  44. package/dist/sdk/browser/config.js +22 -0
  45. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  46. package/dist/sdk/browser/diagnostics.js +38 -0
  47. package/dist/sdk/browser/index.d.ts +28 -0
  48. package/dist/sdk/browser/index.js +72 -0
  49. package/dist/sdk/browser/network.d.ts +10 -0
  50. package/dist/sdk/browser/network.js +59 -0
  51. package/dist/sdk/browser/serverMethods.d.ts +3 -0
  52. package/dist/sdk/browser/serverMethods.js +7 -0
  53. package/dist/sdk/browser/session.d.ts +85 -0
  54. package/dist/sdk/browser/session.js +228 -0
  55. package/dist/sdk/browser/tools.d.ts +8 -0
  56. package/dist/sdk/browser/tools.js +329 -0
  57. package/dist/sdk/capabilities/api.d.ts +22 -0
  58. package/dist/sdk/capabilities/api.js +54 -0
  59. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  60. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  61. package/dist/sdk/capabilities/types.d.ts +29 -0
  62. package/dist/sdk/capabilities/types.js +1 -0
  63. package/dist/sdk/cli.d.ts +2 -0
  64. package/dist/sdk/cli.js +150 -0
  65. package/dist/sdk/core/bus.d.ts +23 -0
  66. package/dist/sdk/core/bus.js +76 -0
  67. package/dist/sdk/core/caller.d.ts +22 -0
  68. package/dist/sdk/core/caller.js +16 -0
  69. package/dist/sdk/core/changes.d.ts +15 -0
  70. package/dist/sdk/core/changes.js +15 -0
  71. package/dist/sdk/core/effort.d.ts +2 -0
  72. package/dist/sdk/core/effort.js +1 -0
  73. package/dist/sdk/core/env.d.ts +18 -0
  74. package/dist/sdk/core/env.js +8 -0
  75. package/dist/sdk/core/errors.d.ts +15 -0
  76. package/dist/sdk/core/errors.js +24 -0
  77. package/dist/sdk/core/frontmatter.d.ts +12 -0
  78. package/dist/sdk/core/frontmatter.js +50 -0
  79. package/dist/sdk/core/fs.d.ts +18 -0
  80. package/dist/sdk/core/fs.js +106 -0
  81. package/dist/sdk/core/index.d.ts +24 -0
  82. package/dist/sdk/core/index.js +187 -0
  83. package/dist/sdk/core/path.d.ts +7 -0
  84. package/dist/sdk/core/path.js +79 -0
  85. package/dist/sdk/core/projects.d.ts +18 -0
  86. package/dist/sdk/core/projects.js +67 -0
  87. package/dist/sdk/core/secrets.d.ts +2 -0
  88. package/dist/sdk/core/secrets.js +5 -0
  89. package/dist/sdk/core/text.d.ts +7 -0
  90. package/dist/sdk/core/text.js +40 -0
  91. package/dist/sdk/doctor/checks.d.ts +5 -0
  92. package/dist/sdk/doctor/checks.js +208 -0
  93. package/dist/sdk/doctor/probe.d.ts +4 -0
  94. package/dist/sdk/doctor/probe.js +92 -0
  95. package/dist/sdk/doctor/serverMethods.d.ts +3 -0
  96. package/dist/sdk/doctor/serverMethods.js +8 -0
  97. package/dist/sdk/doctor/service.d.ts +23 -0
  98. package/dist/sdk/doctor/service.js +144 -0
  99. package/dist/sdk/doctor/types.d.ts +141 -0
  100. package/dist/sdk/doctor/types.js +29 -0
  101. package/dist/sdk/harness.d.ts +148 -0
  102. package/dist/sdk/harness.js +338 -0
  103. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  104. package/dist/sdk/history/lessonPrompt.js +15 -0
  105. package/dist/sdk/history/lessons.d.ts +52 -0
  106. package/dist/sdk/history/lessons.js +173 -0
  107. package/dist/sdk/history/recall.d.ts +68 -0
  108. package/dist/sdk/history/recall.js +199 -0
  109. package/dist/sdk/history/serverMethods.d.ts +3 -0
  110. package/dist/sdk/history/serverMethods.js +8 -0
  111. package/dist/sdk/history/trajectory.d.ts +7 -0
  112. package/dist/sdk/history/trajectory.js +216 -0
  113. package/dist/sdk/hub/catalog.json +123 -0
  114. package/dist/sdk/hub/cli.d.ts +7 -0
  115. package/dist/sdk/hub/cli.js +81 -0
  116. package/dist/sdk/hub/hub.d.ts +74 -0
  117. package/dist/sdk/hub/hub.js +474 -0
  118. package/dist/sdk/hub/schema.d.ts +280 -0
  119. package/dist/sdk/hub/schema.js +78 -0
  120. package/dist/sdk/hub/serverMethods.d.ts +3 -0
  121. package/dist/sdk/hub/serverMethods.js +11 -0
  122. package/dist/sdk/index.d.ts +73 -0
  123. package/dist/sdk/index.js +55 -0
  124. package/dist/sdk/mcp/connections.d.ts +83 -0
  125. package/dist/sdk/mcp/connections.js +676 -0
  126. package/dist/sdk/mcp/manager.d.ts +26 -0
  127. package/dist/sdk/mcp/manager.js +124 -0
  128. package/dist/sdk/mcp/oauth.d.ts +35 -0
  129. package/dist/sdk/mcp/oauth.js +171 -0
  130. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  131. package/dist/sdk/mcp/scopeMigration.js +198 -0
  132. package/dist/sdk/mcp/serverMethods.d.ts +3 -0
  133. package/dist/sdk/mcp/serverMethods.js +22 -0
  134. package/dist/sdk/mcp/service.d.ts +160 -0
  135. package/dist/sdk/mcp/service.js +510 -0
  136. package/dist/sdk/mcp/types.d.ts +131 -0
  137. package/dist/sdk/mcp/types.js +49 -0
  138. package/dist/sdk/pi/runtime.d.ts +13 -0
  139. package/dist/sdk/pi/runtime.js +31 -0
  140. package/dist/sdk/plugins/api.d.ts +66 -0
  141. package/dist/sdk/plugins/api.js +155 -0
  142. package/dist/sdk/plugins/attachments.d.ts +46 -0
  143. package/dist/sdk/plugins/attachments.js +111 -0
  144. package/dist/sdk/plugins/builtin.d.ts +7 -0
  145. package/dist/sdk/plugins/builtin.js +163 -0
  146. package/dist/sdk/plugins/builtinRegistry.d.ts +53 -0
  147. package/dist/sdk/plugins/builtinRegistry.js +49 -0
  148. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  149. package/dist/sdk/plugins/catalogue.js +196 -0
  150. package/dist/sdk/plugins/cli.d.ts +13 -0
  151. package/dist/sdk/plugins/cli.js +188 -0
  152. package/dist/sdk/plugins/discover.d.ts +42 -0
  153. package/dist/sdk/plugins/discover.js +115 -0
  154. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  155. package/dist/sdk/plugins/firstParty.js +113 -0
  156. package/dist/sdk/plugins/hooks.d.ts +94 -0
  157. package/dist/sdk/plugins/hooks.js +162 -0
  158. package/dist/sdk/plugins/identity.d.ts +19 -0
  159. package/dist/sdk/plugins/identity.js +48 -0
  160. package/dist/sdk/plugins/install.d.ts +20 -0
  161. package/dist/sdk/plugins/install.js +110 -0
  162. package/dist/sdk/plugins/inventory.d.ts +22 -0
  163. package/dist/sdk/plugins/inventory.js +110 -0
  164. package/dist/sdk/plugins/manifest.d.ts +13 -0
  165. package/dist/sdk/plugins/manifest.js +56 -0
  166. package/dist/sdk/plugins/plugins.d.ts +104 -0
  167. package/dist/sdk/plugins/plugins.js +164 -0
  168. package/dist/sdk/plugins/runtime.d.ts +9 -0
  169. package/dist/sdk/plugins/runtime.js +95 -0
  170. package/dist/sdk/plugins/trust.d.ts +44 -0
  171. package/dist/sdk/plugins/trust.js +120 -0
  172. package/dist/sdk/plugins/types.d.ts +159 -0
  173. package/dist/sdk/plugins/types.js +7 -0
  174. package/dist/sdk/prompt/compile.d.ts +177 -0
  175. package/dist/sdk/prompt/compile.js +413 -0
  176. package/dist/sdk/refine/cli.d.ts +4 -0
  177. package/dist/sdk/refine/cli.js +186 -0
  178. package/dist/sdk/refine/demo.d.ts +21 -0
  179. package/dist/sdk/refine/demo.js +114 -0
  180. package/dist/sdk/refine/evidence.d.ts +55 -0
  181. package/dist/sdk/refine/evidence.js +330 -0
  182. package/dist/sdk/refine/host.d.ts +51 -0
  183. package/dist/sdk/refine/host.js +76 -0
  184. package/dist/sdk/refine/ledger.d.ts +48 -0
  185. package/dist/sdk/refine/ledger.js +76 -0
  186. package/dist/sdk/refine/library.d.ts +55 -0
  187. package/dist/sdk/refine/library.js +177 -0
  188. package/dist/sdk/refine/pi.d.ts +72 -0
  189. package/dist/sdk/refine/pi.js +248 -0
  190. package/dist/sdk/refine/prompts.d.ts +45 -0
  191. package/dist/sdk/refine/prompts.js +390 -0
  192. package/dist/sdk/refine/recursion.d.ts +113 -0
  193. package/dist/sdk/refine/recursion.js +258 -0
  194. package/dist/sdk/refine/runner.d.ts +81 -0
  195. package/dist/sdk/refine/runner.js +150 -0
  196. package/dist/sdk/refine/selection.d.ts +57 -0
  197. package/dist/sdk/refine/selection.js +251 -0
  198. package/dist/sdk/refine/serverMethods.d.ts +3 -0
  199. package/dist/sdk/refine/serverMethods.js +20 -0
  200. package/dist/sdk/refine/service.d.ts +84 -0
  201. package/dist/sdk/refine/service.js +165 -0
  202. package/dist/sdk/refine/suite.d.ts +67 -0
  203. package/dist/sdk/refine/suite.js +174 -0
  204. package/dist/sdk/refine/trajectory.d.ts +9 -0
  205. package/dist/sdk/refine/trajectory.js +68 -0
  206. package/dist/sdk/refine/types.d.ts +77 -0
  207. package/dist/sdk/refine/types.js +10 -0
  208. package/dist/sdk/server/methods.d.ts +3 -0
  209. package/dist/sdk/server/methods.js +293 -0
  210. package/dist/sdk/server/params.d.ts +4 -0
  211. package/dist/sdk/server/params.js +11 -0
  212. package/dist/sdk/server/remote.d.ts +19 -0
  213. package/dist/sdk/server/remote.js +84 -0
  214. package/dist/sdk/server/rpc.d.ts +20 -0
  215. package/dist/sdk/server/rpc.js +102 -0
  216. package/dist/sdk/server/serve.d.ts +10 -0
  217. package/dist/sdk/server/serve.js +18 -0
  218. package/dist/sdk/sessions/approvals.d.ts +47 -0
  219. package/dist/sdk/sessions/approvals.js +119 -0
  220. package/dist/sdk/sessions/continuation.d.ts +48 -0
  221. package/dist/sdk/sessions/continuation.js +85 -0
  222. package/dist/sdk/sessions/contracts.d.ts +551 -0
  223. package/dist/sdk/sessions/contracts.js +338 -0
  224. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  225. package/dist/sdk/sessions/extensionUi.js +64 -0
  226. package/dist/sdk/sessions/history.d.ts +16 -0
  227. package/dist/sdk/sessions/history.js +68 -0
  228. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  229. package/dist/sdk/sessions/lineageJoin.js +61 -0
  230. package/dist/sdk/sessions/planMode.d.ts +39 -0
  231. package/dist/sdk/sessions/planMode.js +93 -0
  232. package/dist/sdk/sessions/policy.d.ts +43 -0
  233. package/dist/sdk/sessions/policy.js +1 -0
  234. package/dist/sdk/sessions/pricing.d.ts +34 -0
  235. package/dist/sdk/sessions/pricing.js +40 -0
  236. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  237. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  238. package/dist/sdk/sessions/registry.d.ts +103 -0
  239. package/dist/sdk/sessions/registry.js +386 -0
  240. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  241. package/dist/sdk/sessions/runIndex.js +65 -0
  242. package/dist/sdk/sessions/runStore.d.ts +66 -0
  243. package/dist/sdk/sessions/runStore.js +337 -0
  244. package/dist/sdk/sessions/runner.d.ts +213 -0
  245. package/dist/sdk/sessions/runner.js +589 -0
  246. package/dist/sdk/sessions/sessions.d.ts +152 -0
  247. package/dist/sdk/sessions/sessions.js +461 -0
  248. package/dist/sdk/sessions/sideQuestionServerMethods.d.ts +3 -0
  249. package/dist/sdk/sessions/sideQuestionServerMethods.js +19 -0
  250. package/dist/sdk/sessions/sideQuestions.d.ts +66 -0
  251. package/dist/sdk/sessions/sideQuestions.js +290 -0
  252. package/dist/sdk/sessions/subagentServerMethods.d.ts +3 -0
  253. package/dist/sdk/sessions/subagentServerMethods.js +41 -0
  254. package/dist/sdk/sessions/subagentService.d.ts +52 -0
  255. package/dist/sdk/sessions/subagentService.js +265 -0
  256. package/dist/sdk/sessions/subagents.d.ts +58 -0
  257. package/dist/sdk/sessions/subagents.js +87 -0
  258. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  259. package/dist/sdk/terminal/accountsMenu.js +392 -0
  260. package/dist/sdk/terminal/browser.d.ts +62 -0
  261. package/dist/sdk/terminal/browser.js +41 -0
  262. package/dist/sdk/terminal/browserControl.d.ts +29 -0
  263. package/dist/sdk/terminal/browserControl.js +186 -0
  264. package/dist/sdk/terminal/cli.d.ts +20 -0
  265. package/dist/sdk/terminal/cli.js +121 -0
  266. package/dist/sdk/terminal/client.d.ts +15 -0
  267. package/dist/sdk/terminal/client.js +126 -0
  268. package/dist/sdk/terminal/commandHelp.d.ts +17 -0
  269. package/dist/sdk/terminal/commandHelp.js +20 -0
  270. package/dist/sdk/terminal/control.d.ts +4 -0
  271. package/dist/sdk/terminal/control.js +25 -0
  272. package/dist/sdk/terminal/controller.d.ts +78 -0
  273. package/dist/sdk/terminal/controller.js +383 -0
  274. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  275. package/dist/sdk/terminal/hubMenu.js +34 -0
  276. package/dist/sdk/terminal/launch.d.ts +5 -0
  277. package/dist/sdk/terminal/launch.js +27 -0
  278. package/dist/sdk/terminal/logs.d.ts +14 -0
  279. package/dist/sdk/terminal/logs.js +59 -0
  280. package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +28 -0
  281. package/dist/sdk/terminal/opentui/subagentsWidget.js +52 -0
  282. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  283. package/dist/sdk/terminal/piExtension.js +377 -0
  284. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  285. package/dist/sdk/terminal/pluginMenu.js +101 -0
  286. package/dist/sdk/terminal/socket.d.ts +73 -0
  287. package/dist/sdk/terminal/socket.js +287 -0
  288. package/dist/sdk/terminal/standalone.d.ts +20 -0
  289. package/dist/sdk/terminal/standalone.js +186 -0
  290. package/dist/sdk/terminal/subagentMonitor.d.ts +38 -0
  291. package/dist/sdk/terminal/subagentMonitor.js +121 -0
  292. package/dist/sdk/terminal/terminals.d.ts +212 -0
  293. package/dist/sdk/terminal/terminals.js +1108 -0
  294. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  295. package/dist/sdk/terminal/trajectory.js +30 -0
  296. package/dist/sdk/terminal/tui/annotateCommand.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/annotateCommand.js +22 -0
  298. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  299. package/dist/sdk/terminal/tui/chrome.js +169 -0
  300. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  301. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  302. package/dist/sdk/terminal/tui/commandPages.d.ts +11 -0
  303. package/dist/sdk/terminal/tui/commandPages.js +111 -0
  304. package/dist/sdk/terminal/tui/commands.d.ts +46 -0
  305. package/dist/sdk/terminal/tui/commands.js +399 -0
  306. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  307. package/dist/sdk/terminal/tui/dialogGeometry.js +52 -0
  308. package/dist/sdk/terminal/tui/dialogs.d.ts +80 -0
  309. package/dist/sdk/terminal/tui/dialogs.js +370 -0
  310. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  311. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  312. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  313. package/dist/sdk/terminal/tui/list.js +196 -0
  314. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  315. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  316. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  317. package/dist/sdk/terminal/tui/modelPicker.js +150 -0
  318. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  319. package/dist/sdk/terminal/tui/mouse.js +3 -0
  320. package/dist/sdk/terminal/tui/page.d.ts +17 -0
  321. package/dist/sdk/terminal/tui/page.js +1 -0
  322. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  323. package/dist/sdk/terminal/tui/pageOverlay.js +156 -0
  324. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +76 -0
  325. package/dist/sdk/terminal/tui/pages/accountsPage.js +409 -0
  326. package/dist/sdk/terminal/tui/pages/agentsPage.d.ts +74 -0
  327. package/dist/sdk/terminal/tui/pages/agentsPage.js +190 -0
  328. package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +94 -0
  329. package/dist/sdk/terminal/tui/pages/annotatePage.js +341 -0
  330. package/dist/sdk/terminal/tui/pages/browserPage.d.ts +87 -0
  331. package/dist/sdk/terminal/tui/pages/browserPage.js +738 -0
  332. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  333. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  334. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +39 -0
  335. package/dist/sdk/terminal/tui/pages/doctorPage.js +233 -0
  336. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  337. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  338. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  339. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  340. package/dist/sdk/terminal/tui/pages/notesPage.d.ts +75 -0
  341. package/dist/sdk/terminal/tui/pages/notesPage.js +201 -0
  342. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  343. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  344. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  345. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  346. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +63 -0
  347. package/dist/sdk/terminal/tui/pages/settingsPage.js +103 -0
  348. package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +23 -0
  349. package/dist/sdk/terminal/tui/pages/subagentsPage.js +70 -0
  350. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +65 -0
  351. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +450 -0
  352. package/dist/sdk/terminal/tui/pages/worktreesPage.d.ts +72 -0
  353. package/dist/sdk/terminal/tui/pages/worktreesPage.js +203 -0
  354. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  355. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  356. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  357. package/dist/sdk/terminal/tui/planMode.js +2 -0
  358. package/dist/sdk/terminal/tui/pluginCommands.d.ts +14 -0
  359. package/dist/sdk/terminal/tui/pluginCommands.js +27 -0
  360. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  361. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  362. package/dist/sdk/terminal/tui/questions.d.ts +21 -0
  363. package/dist/sdk/terminal/tui/questions.js +42 -0
  364. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  365. package/dist/sdk/terminal/tui/runtime.js +443 -0
  366. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  367. package/dist/sdk/terminal/tui/search.js +60 -0
  368. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  369. package/dist/sdk/terminal/tui/selection.js +16 -0
  370. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  371. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  372. package/dist/sdk/terminal/tui/settingsModel.d.ts +14 -0
  373. package/dist/sdk/terminal/tui/settingsModel.js +114 -0
  374. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  375. package/dist/sdk/terminal/tui/sideQuestion.js +230 -0
  376. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  377. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  378. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  379. package/dist/sdk/terminal/tui/status.js +67 -0
  380. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  381. package/dist/sdk/terminal/tui/theme.js +176 -0
  382. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  383. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  384. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  385. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  386. package/dist/sdk/terminal/tui/ui.d.ts +49 -0
  387. package/dist/sdk/terminal/tui/ui.js +149 -0
  388. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  389. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  390. package/dist/sdk/tools/askUser.d.ts +6 -0
  391. package/dist/sdk/tools/askUser.js +92 -0
  392. package/dist/sdk/tools/checklist.d.ts +9 -0
  393. package/dist/sdk/tools/checklist.js +54 -0
  394. package/dist/sdk/tools/definitions.d.ts +30 -0
  395. package/dist/sdk/tools/definitions.js +117 -0
  396. package/dist/sdk/tools/dispatch.d.ts +16 -0
  397. package/dist/sdk/tools/dispatch.js +67 -0
  398. package/dist/sdk/tools/harnessTools.d.ts +8 -0
  399. package/dist/sdk/tools/harnessTools.js +20 -0
  400. package/dist/sdk/tools/sessionName.d.ts +7 -0
  401. package/dist/sdk/tools/sessionName.js +31 -0
  402. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  403. package/dist/sdk/tools/spawnSubagent.js +58 -0
  404. package/dist/sdk/tools/types.d.ts +48 -0
  405. package/dist/sdk/tools/types.js +1 -0
  406. package/dist/sdk/variant/components.d.ts +34 -0
  407. package/dist/sdk/variant/components.js +230 -0
  408. package/dist/sdk/variant/materialise.d.ts +66 -0
  409. package/dist/sdk/variant/materialise.js +81 -0
  410. package/dist/sdk/variant/migrate.d.ts +4 -0
  411. package/dist/sdk/variant/migrate.js +41 -0
  412. package/dist/sdk/variant/seed.d.ts +20 -0
  413. package/dist/sdk/variant/seed.js +116 -0
  414. package/dist/sdk/variant/store.d.ts +82 -0
  415. package/dist/sdk/variant/store.js +151 -0
  416. package/dist/sdk/variant/surface.d.ts +56 -0
  417. package/dist/sdk/variant/surface.js +81 -0
  418. package/dist/sdk/variant/trust.d.ts +27 -0
  419. package/dist/sdk/variant/trust.js +64 -0
  420. package/dist/sdk/variant/variant.d.ts +71 -0
  421. package/dist/sdk/variant/variant.js +331 -0
  422. package/dist/sdk/web/markdown.d.ts +10 -0
  423. package/dist/sdk/web/markdown.js +66 -0
  424. package/dist/sdk/web/part.d.ts +10 -0
  425. package/dist/sdk/web/part.js +6 -0
  426. package/dist/sdk/web/safeRequest.d.ts +34 -0
  427. package/dist/sdk/web/safeRequest.js +175 -0
  428. package/dist/sdk/web/search.d.ts +53 -0
  429. package/dist/sdk/web/search.js +168 -0
  430. package/dist/sdk/web/serverMethods.d.ts +3 -0
  431. package/dist/sdk/web/serverMethods.js +7 -0
  432. package/dist/sdk/web/text.d.ts +2 -0
  433. package/dist/sdk/web/text.js +7 -0
  434. package/dist/sdk/web/tools.d.ts +22 -0
  435. package/dist/sdk/web/tools.js +195 -0
  436. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  437. package/dist/sdk/wiki/notes.d.ts +68 -0
  438. package/dist/sdk/wiki/notes.js +297 -0
  439. package/dist/sdk/wiki/serverMethods.d.ts +3 -0
  440. package/dist/sdk/wiki/serverMethods.js +26 -0
  441. package/dist/sdk/worktrees/cli.d.ts +11 -0
  442. package/dist/sdk/worktrees/cli.js +146 -0
  443. package/dist/sdk/worktrees/copy.d.ts +9 -0
  444. package/dist/sdk/worktrees/copy.js +111 -0
  445. package/dist/sdk/worktrees/git.d.ts +16 -0
  446. package/dist/sdk/worktrees/git.js +81 -0
  447. package/dist/sdk/worktrees/serverMethods.d.ts +3 -0
  448. package/dist/sdk/worktrees/serverMethods.js +30 -0
  449. package/dist/sdk/worktrees/service.d.ts +73 -0
  450. package/dist/sdk/worktrees/service.js +483 -0
  451. package/dist/sdk/worktrees/setup.d.ts +23 -0
  452. package/dist/sdk/worktrees/setup.js +65 -0
  453. package/dist/sdk/worktrees/types.d.ts +91 -0
  454. package/dist/sdk/worktrees/types.js +1 -0
  455. package/dist/sdk/world/actions.d.ts +23 -0
  456. package/dist/sdk/world/actions.js +31 -0
  457. package/dist/sdk/world/cli.d.ts +12 -0
  458. package/dist/sdk/world/cli.js +166 -0
  459. package/dist/sdk/world/images.d.ts +20 -0
  460. package/dist/sdk/world/images.js +48 -0
  461. package/dist/sdk/world/untrusted.d.ts +12 -0
  462. package/dist/sdk/world/untrusted.js +20 -0
  463. package/dist/sdk/world/world.d.ts +67 -0
  464. package/dist/sdk/world/world.js +79 -0
  465. package/dist/terminal-opentui.js +20778 -0
  466. package/dist/terminal-pi.js +794 -518
  467. package/docs/README.md +42 -0
  468. package/docs/architecture/00-overview.md +171 -0
  469. package/docs/architecture/01-extension-points.md +78 -0
  470. package/docs/architecture/02-sessions-and-runs.md +203 -0
  471. package/docs/architecture/03-variants.md +103 -0
  472. package/docs/architecture/04-prompt.md +122 -0
  473. package/docs/architecture/05-refinement.md +107 -0
  474. package/docs/architecture/06-plugins-and-capabilities.md +129 -0
  475. package/docs/architecture/07-tools-and-gate.md +103 -0
  476. package/docs/architecture/08-memory-and-history.md +94 -0
  477. package/docs/architecture/09-accounts-and-connectors.md +98 -0
  478. package/docs/architecture/10-server-protocol.md +193 -0
  479. package/docs/architecture/11-terminal.md +261 -0
  480. package/docs/architecture/12-storage.md +75 -0
  481. package/docs/architecture/13-world-tools.md +45 -0
  482. package/docs/architecture/14-surfaces-and-parity.md +89 -0
  483. package/docs/architecture/README.md +125 -0
  484. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  485. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  486. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  487. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  488. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  489. package/docs/architecture/proposals/PROP-0006-run-checklist.md +70 -0
  490. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  491. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  492. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  493. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  494. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  495. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  496. package/docs/architecture/proposals/PROP-0013-resource-browser.md +58 -0
  497. package/docs/architecture/proposals/PROP-0014-fullscreen-browser-tabs.md +58 -0
  498. package/docs/architecture/proposals/PROP-0015-one-capability-surface.md +88 -0
  499. package/docs/architecture/proposals/PROP-0016-managed-worktrees.md +156 -0
  500. package/docs/architecture/proposals/PROP-0017-page-annotations.md +127 -0
  501. package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +179 -0
  502. package/docs/architecture/proposals/PROP-0019-contextual-side-questions.md +122 -0
  503. package/docs/architecture/proposals/PROP-0020-builtin-feature-plugins.md +105 -0
  504. package/docs/architecture/proposals/PROP-0021-command-namespaces-and-duplicates.md +99 -0
  505. package/docs/architecture/proposals/PROP-0022-plan-only-questions.md +102 -0
  506. package/docs/architecture/proposals/PROP-0023-xagent-cli-name.md +61 -0
  507. package/docs/architecture/proposals/PROP-0024-question-sketch-previews.md +130 -0
  508. package/docs/architecture/proposals/PROP-0025-contextual-question-wireframes.md +49 -0
  509. package/docs/architecture/proposals/PROP-0026-connected-sketch-display.md +94 -0
  510. package/docs/architecture/proposals/PROP-0027-xingular-agent-product-identity.md +60 -0
  511. package/docs/architecture/proposals/PROP-0028-normalize-question-wireframes.md +55 -0
  512. package/docs/architecture/proposals/PROP-0029-agent-profiles.md +124 -0
  513. package/docs/architecture/proposals/PROP-0030-subagent-title.md +86 -0
  514. package/docs/architecture/proposals/README.md +101 -0
  515. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  516. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  517. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  518. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  519. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  520. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  521. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  522. package/docs/decisions/ADR-0009-xharness-command.md +39 -0
  523. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  524. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  525. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  526. package/docs/decisions/ADR-0013-doctor.md +27 -0
  527. package/docs/decisions/ADR-0014-public-release-baseline.md +22 -0
  528. package/docs/decisions/ADR-0015-resource-browser.md +28 -0
  529. package/docs/decisions/ADR-0016-fullscreen-browser-tabs.md +31 -0
  530. package/docs/decisions/ADR-0017-one-capability-surface.md +34 -0
  531. package/docs/decisions/ADR-0018-builtin-feature-plugins.md +35 -0
  532. package/docs/decisions/ADR-0019-managed-git-worktrees.md +31 -0
  533. package/docs/decisions/ADR-0020-page-annotations.md +37 -0
  534. package/docs/decisions/ADR-0021-required-command-namespaces.md +40 -0
  535. package/docs/decisions/ADR-0022-plan-only-question-tools.md +34 -0
  536. package/docs/decisions/ADR-0023-contextual-side-question-runs.md +35 -0
  537. package/docs/decisions/ADR-0024-xagent-command.md +40 -0
  538. package/docs/decisions/ADR-0025-question-choice-sketches.md +49 -0
  539. package/docs/decisions/ADR-0026-contextual-question-wireframes.md +58 -0
  540. package/docs/decisions/ADR-0027-connected-sketch-display.md +60 -0
  541. package/docs/decisions/ADR-0028-xingular-agent-product-identity.md +56 -0
  542. package/docs/decisions/ADR-0029-normalized-question-wireframe-borders.md +33 -0
  543. package/docs/decisions/ADR-0030-agent-profiles.md +43 -0
  544. package/docs/doctor.md +80 -0
  545. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  546. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  547. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  548. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  549. package/docs/features/README.md +46 -0
  550. package/docs/features/automations/README.md +41 -0
  551. package/docs/features/cores/README.md +39 -0
  552. package/docs/features/google-harness2/README.md +52 -0
  553. package/docs/features/integrations/README.md +40 -0
  554. package/docs/features/interfaces/README.md +29 -0
  555. package/docs/features/memory/README.md +28 -0
  556. package/docs/future-work.md +48 -0
  557. package/docs/parity.md +78 -0
  558. package/docs/releases/1.0.0.md +40 -0
  559. package/docs/releases/4.0.0.md +46 -0
  560. package/docs/releases/README.md +41 -0
  561. package/docs/study/00-index.md +83 -0
  562. package/docs/study/arms/00-matrix.md +20 -0
  563. package/docs/study/arms/01-system-prompt.md +211 -0
  564. package/docs/study/arms/02-tools.md +79 -0
  565. package/docs/study/arms/03-subagents.md +90 -0
  566. package/docs/study/arms/04-skills.md +75 -0
  567. package/docs/study/arms/05-context-management.md +90 -0
  568. package/docs/study/arms/06-memory.md +90 -0
  569. package/docs/study/arms/07-governance.md +71 -0
  570. package/docs/study/arms/08-execution.md +69 -0
  571. package/docs/study/arms/09-observability.md +60 -0
  572. package/docs/study/arms/10-refinement.md +110 -0
  573. package/docs/study/autonomous-engineering-sources.md +277 -0
  574. package/docs/study/autonomy-sources.md +147 -0
  575. package/docs/study/btw-comparison.md +37 -0
  576. package/docs/study/feature-gap-review.md +42 -0
  577. package/docs/study/insights.md +123 -0
  578. package/docs/study/proactive-autonomy.md +408 -0
  579. package/docs/study/roadmap.md +72 -0
  580. package/docs/study/sources/claude-code.md +44 -0
  581. package/docs/study/sources/deepseek-harness.md +102 -0
  582. package/docs/study/sources/harness2.md +50 -0
  583. package/docs/study/sources/kimi-cli.md +42 -0
  584. package/docs/study/sources/omp.md +93 -0
  585. package/docs/study/sources/opencode.md +43 -0
  586. package/docs/study/sources/openhands.md +46 -0
  587. package/docs/study/sources/smolagents.md +40 -0
  588. package/docs/study/sources/swe-agent.md +34 -0
  589. package/docs/study/tui-resource-browser.md +78 -0
  590. package/docs/system-prompt-design.md +196 -0
  591. package/docs/terminal-tui.md +707 -58
  592. package/package.json +43 -13
  593. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  594. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  595. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  596. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  597. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  598. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  599. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  600. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  601. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  602. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  603. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  604. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  605. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  606. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  607. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  608. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  609. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  610. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  611. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  612. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  613. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  614. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  615. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  616. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  617. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  618. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  619. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  620. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  621. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  622. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  623. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  624. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  625. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  626. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  627. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  628. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  629. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  630. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  631. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  632. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  633. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  634. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  635. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
  636. package/src/accounts/accounts.test.ts +0 -333
  637. package/src/accounts/accounts.ts +0 -658
  638. package/src/accounts/env.test.ts +0 -95
  639. package/src/accounts/env.ts +0 -338
  640. package/src/accounts/secrets.ts +0 -50
  641. package/src/accounts/store.ts +0 -338
  642. package/src/capabilities/api.ts +0 -75
  643. package/src/capabilities/runSnapshot.ts +0 -59
  644. package/src/capabilities/types.ts +0 -34
  645. package/src/cli.ts +0 -118
  646. package/src/core/bus.ts +0 -34
  647. package/src/core/changes.ts +0 -33
  648. package/src/core/env.ts +0 -27
  649. package/src/core/errors.ts +0 -32
  650. package/src/core/frontmatter.ts +0 -47
  651. package/src/core/fs.test.ts +0 -38
  652. package/src/core/fs.ts +0 -92
  653. package/src/core/index.ts +0 -193
  654. package/src/core/path.test.ts +0 -14
  655. package/src/core/path.ts +0 -79
  656. package/src/core/projects.ts +0 -90
  657. package/src/core/text.ts +0 -39
  658. package/src/harness.ts +0 -312
  659. package/src/hub/catalog.json +0 -123
  660. package/src/hub/cli.ts +0 -59
  661. package/src/hub/hub.test.ts +0 -205
  662. package/src/hub/hub.ts +0 -256
  663. package/src/hub/schema.ts +0 -81
  664. package/src/index.ts +0 -75
  665. package/src/mcp/connections.ts +0 -614
  666. package/src/mcp/manager.ts +0 -130
  667. package/src/mcp/oauth.ts +0 -195
  668. package/src/mcp/scopeMigration.test.ts +0 -79
  669. package/src/mcp/scopeMigration.ts +0 -204
  670. package/src/mcp/service.test.ts +0 -376
  671. package/src/mcp/service.ts +0 -549
  672. package/src/mcp/types.ts +0 -108
  673. package/src/memory/api.test.ts +0 -82
  674. package/src/memory/api.ts +0 -303
  675. package/src/memory/blocks.test.ts +0 -78
  676. package/src/memory/blocks.ts +0 -408
  677. package/src/memory/caller.ts +0 -69
  678. package/src/memory/curation.test.ts +0 -163
  679. package/src/memory/curation.ts +0 -64
  680. package/src/memory/dispatch.ts +0 -59
  681. package/src/memory/facts.test.ts +0 -41
  682. package/src/memory/facts.ts +0 -248
  683. package/src/memory/graph.ts +0 -103
  684. package/src/memory/health.test.ts +0 -130
  685. package/src/memory/health.ts +0 -74
  686. package/src/memory/maintainer.ts +0 -272
  687. package/src/memory/maintenance.test.ts +0 -176
  688. package/src/memory/maintenance.ts +0 -518
  689. package/src/memory/migrate.ts +0 -79
  690. package/src/memory/operations.ts +0 -150
  691. package/src/memory/proposals.test.ts +0 -168
  692. package/src/memory/proposals.ts +0 -584
  693. package/src/memory/recall.test.ts +0 -115
  694. package/src/memory/recall.ts +0 -278
  695. package/src/memory/references.ts +0 -77
  696. package/src/memory/runContext.ts +0 -93
  697. package/src/memory/secrets.ts +0 -6
  698. package/src/memory/store.test.ts +0 -66
  699. package/src/memory/store.ts +0 -385
  700. package/src/memory/wiki.test.ts +0 -47
  701. package/src/memory/wiki.ts +0 -422
  702. package/src/memory/wikiIndex.test.ts +0 -88
  703. package/src/memory/wikiIndex.ts +0 -116
  704. package/src/plugins/api.ts +0 -181
  705. package/src/plugins/attachments.test.ts +0 -84
  706. package/src/plugins/attachments.ts +0 -141
  707. package/src/plugins/builtin.ts +0 -82
  708. package/src/plugins/catalogue.test.ts +0 -254
  709. package/src/plugins/catalogue.ts +0 -251
  710. package/src/plugins/cli.ts +0 -184
  711. package/src/plugins/discover.ts +0 -151
  712. package/src/plugins/firstParty.test.ts +0 -143
  713. package/src/plugins/firstParty.ts +0 -129
  714. package/src/plugins/hooks.test.ts +0 -250
  715. package/src/plugins/hooks.ts +0 -239
  716. package/src/plugins/identity.ts +0 -37
  717. package/src/plugins/install.test.ts +0 -107
  718. package/src/plugins/install.ts +0 -106
  719. package/src/plugins/inventory.ts +0 -123
  720. package/src/plugins/manifest.ts +0 -76
  721. package/src/plugins/plugins.test.ts +0 -205
  722. package/src/plugins/plugins.ts +0 -189
  723. package/src/plugins/proposal.ts +0 -121
  724. package/src/plugins/runtime.test.ts +0 -40
  725. package/src/plugins/runtime.ts +0 -82
  726. package/src/plugins/trust.ts +0 -142
  727. package/src/plugins/types.ts +0 -149
  728. package/src/prompt/compile.test.ts +0 -261
  729. package/src/prompt/compile.ts +0 -732
  730. package/src/server/methods.ts +0 -349
  731. package/src/server/remote.ts +0 -77
  732. package/src/server/rpc.ts +0 -116
  733. package/src/server/serve.ts +0 -28
  734. package/src/server/server.test.ts +0 -174
  735. package/src/sessions/approvals.ts +0 -118
  736. package/src/sessions/contracts.ts +0 -336
  737. package/src/sessions/conversation.test.ts +0 -177
  738. package/src/sessions/extensionSession.test.ts +0 -74
  739. package/src/sessions/extensionUi.test.ts +0 -65
  740. package/src/sessions/extensionUi.ts +0 -102
  741. package/src/sessions/history.ts +0 -51
  742. package/src/sessions/lineageJoin.ts +0 -75
  743. package/src/sessions/policy.ts +0 -36
  744. package/src/sessions/pricing.ts +0 -60
  745. package/src/sessions/questionBatches.test.ts +0 -110
  746. package/src/sessions/reasoningSummaries.ts +0 -59
  747. package/src/sessions/registry.ts +0 -381
  748. package/src/sessions/runIndex.ts +0 -99
  749. package/src/sessions/runStore.test.ts +0 -152
  750. package/src/sessions/runStore.ts +0 -332
  751. package/src/sessions/runner.ts +0 -604
  752. package/src/sessions/runtimeResources.test.ts +0 -61
  753. package/src/sessions/sessions.test.ts +0 -549
  754. package/src/sessions/sessions.ts +0 -339
  755. package/src/skills/registry.test.ts +0 -104
  756. package/src/skills/registry.ts +0 -413
  757. package/src/terminal/accountsMenu.test.ts +0 -225
  758. package/src/terminal/accountsMenu.ts +0 -382
  759. package/src/terminal/cli.ts +0 -149
  760. package/src/terminal/client.ts +0 -74
  761. package/src/terminal/control.test.ts +0 -23
  762. package/src/terminal/control.ts +0 -23
  763. package/src/terminal/controller.ts +0 -291
  764. package/src/terminal/hubMenu.ts +0 -24
  765. package/src/terminal/launch.test.ts +0 -25
  766. package/src/terminal/launch.ts +0 -48
  767. package/src/terminal/piExtension.lifecycle.test.ts +0 -55
  768. package/src/terminal/piExtension.ts +0 -259
  769. package/src/terminal/pluginControl.test.ts +0 -146
  770. package/src/terminal/pluginMenu.ts +0 -112
  771. package/src/terminal/socket.test.ts +0 -71
  772. package/src/terminal/socket.ts +0 -232
  773. package/src/terminal/standalone.test.ts +0 -167
  774. package/src/terminal/standalone.ts +0 -153
  775. package/src/terminal/terminal.test.ts +0 -399
  776. package/src/terminal/terminals.ts +0 -553
  777. package/src/terminal/tui/application.test.ts +0 -114
  778. package/src/terminal/tui/application.ts +0 -491
  779. package/src/terminal/tui/commands.test.ts +0 -218
  780. package/src/terminal/tui/commands.ts +0 -361
  781. package/src/terminal/tui/dialogs.ts +0 -301
  782. package/src/terminal/tui/editor.test.ts +0 -84
  783. package/src/terminal/tui/editor.ts +0 -79
  784. package/src/terminal/tui/keybindings.test.ts +0 -22
  785. package/src/terminal/tui/keybindings.ts +0 -50
  786. package/src/terminal/tui/piAdapter.ts +0 -62
  787. package/src/terminal/tui/presentation.test.ts +0 -79
  788. package/src/terminal/tui/questions.test.ts +0 -41
  789. package/src/terminal/tui/questions.ts +0 -47
  790. package/src/terminal/tui/runtime.socket.test.ts +0 -104
  791. package/src/terminal/tui/runtime.test.ts +0 -215
  792. package/src/terminal/tui/runtime.ts +0 -388
  793. package/src/terminal/tui/sessionUi.ts +0 -24
  794. package/src/terminal/tui/settings.test.ts +0 -150
  795. package/src/terminal/tui/settings.ts +0 -188
  796. package/src/terminal/tui/status.test.ts +0 -70
  797. package/src/terminal/tui/status.ts +0 -109
  798. package/src/terminal/tui/theme.ts +0 -174
  799. package/src/terminal/tui/tools.test.ts +0 -145
  800. package/src/terminal/tui/tools.ts +0 -142
  801. package/src/terminal/tui/transcript.test.ts +0 -25
  802. package/src/terminal/tui/transcript.ts +0 -124
  803. package/src/terminal/tui/ui.test.ts +0 -313
  804. package/src/terminal/tui/ui.ts +0 -166
  805. package/src/terminal/tui/welcome.ts +0 -102
  806. package/src/tools/askUser.test.ts +0 -69
  807. package/src/tools/askUser.ts +0 -59
  808. package/src/tools/definitions.ts +0 -187
  809. package/src/tools/maintenance.ts +0 -24
  810. package/src/tools/memoryTools.ts +0 -22
  811. package/src/tools/pluginPropose.ts +0 -41
  812. package/src/tools/registryWrite.test.ts +0 -101
  813. package/src/tools/registryWrite.ts +0 -182
  814. package/src/tools/spawnSubagent.ts +0 -92
  815. package/src/tools/types.ts +0 -39
  816. package/src/web/safeRequest.ts +0 -171
  817. package/src/web/text.ts +0 -53
  818. package/src/web/tools.ts +0 -134
  819. package/src/web/web.test.ts +0 -141
@@ -1,250 +0,0 @@
1
- import { existsSync, mkdtempSync, readFileSync, readdirSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { afterEach, describe, expect, it } from 'vitest'
5
-
6
- import { memorySecretStore } from '../accounts/secrets'
7
- import { Bus } from '../core/bus'
8
- import { createHarness, type Harness } from '../harness'
9
- import { listInbox } from '../memory/operations'
10
- import { wikiDir } from '../memory/store'
11
- import { methods } from '../server/methods'
12
- import { pluginProposeTool } from '../tools/pluginPropose'
13
- import { rootWithProject, writeFile } from '../../tests/helpers'
14
- import { entryEvent, Hooks, type HookEvent } from './hooks'
15
- import { checkPluginProposal } from './proposal'
16
- import type { Plugin } from './types'
17
-
18
- const open: Harness[] = []
19
- afterEach(async () => {
20
- for (const harness of open.splice(0)) await harness.close()
21
- })
22
-
23
- const temp = (): string => mkdtempSync(join(tmpdir(), 'hooks-'))
24
- // The test runner owns `import()` here; in a real process the harness uses Node's own.
25
- const importFile = (address: string): Promise<unknown> => import(/* @vite-ignore */ address)
26
-
27
- /** A hooks file that appends what it was told to a file, so a test can read it back. */
28
- const recorder = (out: string, events: string[], extra = ''): string =>
29
- `import { appendFileSync } from 'node:fs'\nexport default function (harness) {\n${events.map((event) => ` harness.on('${event}', async (event, ctx) => { appendFileSync(${JSON.stringify(out)}, JSON.stringify({ type: event.type, id: event.id ?? event.runId, title: event.title, body: event.body, actor: event.actor }) + '\\n')${extra} })`).join('\n')}\n}\n`
30
-
31
- const told = (out: string): Record<string, unknown>[] => (existsSync(out) ? readFileSync(out, 'utf8').trim().split('\n').filter(Boolean).map((line) => JSON.parse(line)) : [])
32
-
33
- function kit(folder: string, name: string, hooks: string): void {
34
- writeFile(join(folder, 'package.json'), JSON.stringify({ name, version: '1.0.0', description: `${name} mirrors memory.`, harness: { extends: ['memory', 'nonsense'], hooks: './hooks.mjs' } }))
35
- writeFile(join(folder, 'hooks.mjs'), hooks)
36
- }
37
-
38
- function setup() {
39
- const root = rootWithProject()
40
- const base = temp()
41
- const harness = createHarness({ dataRoot: root, stateDir: join(base, 'state'), secrets: memorySecretStore(), hookImporter: importFile })
42
- open.push(harness)
43
- const table = methods(harness)
44
- const call = <T>(method: string, params: Record<string, unknown> = {}) => table[method](params) as Promise<T>
45
- const saveFact = (title: string, body: string) => call('facts.save', { input: { title, kind: 'fact', body, namespace: '/' } })
46
- return { harness, root, base, call, saveFact }
47
- }
48
-
49
- describe('a written file as an event', () => {
50
- it('is a fact, a memory block, or a page by where it is in the Wiki', () => {
51
- const wiki = '/data/wiki'
52
- const change = (path: string, text: string) => entryEvent({ wiki, id: 'x', path: join(wiki, path), text, actor: 'user', reason: 'Edited' })
53
- expect(change('facts/pnpm.md', '---\ntitle: Use pnpm\nkind: preference\n---\n\nAlways pnpm.\n')).toMatchObject({ type: 'memory.saved', title: 'Use pnpm', body: 'Always pnpm.', actor: 'user' })
54
- expect(change('blocks/agents/a1/notes.md', '---\nlabel: notes\n---\n\nLikes tabs.\n')).toMatchObject({ type: 'memory.block.changed', title: 'notes', body: 'Likes tabs.' })
55
- expect(change('library/arch.md', '---\ntitle: Architecture\n---\n\nLayers.\n')).toMatchObject({ type: 'wiki.page.saved', title: 'Architecture' })
56
- expect(change('home.md', 'No front matter.')).toMatchObject({ type: 'wiki.page.saved', title: 'x', body: 'No front matter.' })
57
- })
58
- })
59
-
60
- describe('hooks a plugin gives the harness', () => {
61
- it('mirrors saved facts through a real disposable MCP subprocess and stops on detach, changed code or revoked permission', async () => {
62
- const { harness, base, call, saveFact } = setup()
63
- const output = join(base, 'mirrored.jsonl')
64
- await harness.apps.save({ id: 'mirror', name: 'Disposable mirror', kind: 'local', command: process.execPath, args: [join(process.cwd(), 'tests/mcp-hook-fixture.mjs'), output], enabled: true, global: true, readTools: ['mirror_fact'] })
65
- const paths = ['one', 'two'].map((name) => join(base, name))
66
- for (const [index, path] of paths.entries()) {
67
- const name = ['mirror-one', 'mirror-two'][index]
68
- kit(path, name, `export default function(harness) { harness.on('memory.saved', async (event, ctx) => { await ctx.call('Disposable mirror', 'mirror_fact', { plugin: '${name}', id: event.id, title: event.title, body: event.body }) }) }\n`)
69
- const plugins = await call<Plugin[]>('plugins.install', { source: path })
70
- const plugin = plugins.find((entry) => entry.id === `package:${name}`)!
71
- await call('plugins.attach', { id: plugin.id })
72
- await call('plugins.trust', { hash: plugin.code!.hash })
73
- }
74
- await harness.hooks.reload()
75
- await saveFact('Synthetic one', 'Generated probe body.')
76
- await harness.hooks.settled()
77
- expect(told(output).map((row) => row.plugin)).toEqual(['mirror-one', 'mirror-two'])
78
- expect(told(output)[0]).toMatchObject({ title: 'Synthetic one', body: 'Generated probe body.' })
79
- await call('plugins.detach', { id: 'package:mirror-one' })
80
- await saveFact('Synthetic two', 'Second body.')
81
- await harness.hooks.settled()
82
- expect(told(output).map((row) => row.plugin)).toEqual(['mirror-one', 'mirror-two', 'mirror-two'])
83
- writeFile(join(paths[1], 'hooks.mjs'), '// Changed since trust\nexport default function() {}\n')
84
- await saveFact('Synthetic three', 'Untrusted code hears nothing.')
85
- await harness.hooks.settled()
86
- expect(told(output)).toHaveLength(3)
87
- await call('plugins.attach', { id: 'package:mirror-one' })
88
- await harness.apps.save({ id: 'mirror', name: 'Disposable mirror', kind: 'local', command: process.execPath, args: [join(process.cwd(), 'tests/mcp-hook-fixture.mjs'), output], enabled: true, global: true, readTools: [] })
89
- await harness.hooks.reload()
90
- await saveFact('Synthetic four', 'Write succeeds with permission revoked.')
91
- await harness.hooks.settled()
92
- expect(told(output)).toHaveLength(3)
93
- expect(harness.hooks.status()[join(paths[0], 'hooks.mjs')].lastError).toContain('asks before running')
94
- })
95
-
96
- it('run for every plugin that listens, only once the plugin is switched on for everyone and trusted', async () => {
97
- const { harness, base, call, saveFact } = setup()
98
- const one = join(base, 'one.log')
99
- const two = join(base, 'two.log')
100
- kit(join(base, 'docs'), 'memory-to-docs', recorder(one, ['memory.saved']))
101
- kit(join(base, 'sheet'), 'memory-to-sheet', recorder(two, ['memory.saved', 'history.run.ended']))
102
- await call('plugins.install', { source: join(base, 'docs') })
103
- const listed = await call<Plugin[]>('plugins.install', { source: join(base, 'sheet') })
104
- const docs = listed.find((plugin) => plugin.id === 'package:memory-to-docs')!
105
- const sheet = listed.find((plugin) => plugin.id === 'package:memory-to-sheet')!
106
- // What it says it extends is kept only for parts that exist.
107
- expect(docs).toMatchObject({ extends: ['memory'], runsCode: true, trust: 'untrusted', attachment: { global: false } })
108
- expect(docs.contributions.map((entry) => [entry.kind, entry.name, entry.state])).toEqual([['code', 'hooks.mjs', 'off']])
109
-
110
- // Installed, switched off, untrusted: a saved fact reaches nobody.
111
- await saveFact('Use pnpm', 'Always pnpm.')
112
- await harness.hooks.settled()
113
- expect([told(one), told(two)]).toEqual([[], []])
114
-
115
- // Switched on but not trusted is still nothing.
116
- await call('plugins.attach', { id: docs.id })
117
- await call('plugins.attach', { id: sheet.id })
118
- await harness.hooks.reload()
119
- await saveFact('Tabs', 'Use tabs.')
120
- await harness.hooks.settled()
121
- expect([told(one), told(two)]).toEqual([[], []])
122
-
123
- // Trusted: both hear the next fact, each in its own way.
124
- await call('plugins.trust', { hash: docs.code!.hash })
125
- const trusted = await call<Plugin[]>('plugins.trust', { hash: sheet.code!.hash })
126
- await harness.hooks.reload()
127
- await saveFact('Line length', 'Wrap at 100.')
128
- await harness.hooks.settled()
129
- expect(told(one)).toEqual([{ type: 'memory.saved', id: expect.any(String), title: 'Line length', body: 'Wrap at 100.', actor: 'user' }])
130
- expect(told(two)).toEqual(told(one))
131
- expect(trusted.find((plugin) => plugin.id === docs.id)!.contributions[0]).toMatchObject({ state: 'on', problem: null })
132
- const described = (await call<Plugin[]>('plugins.list')).find((plugin) => plugin.id === sheet.id)!.contributions[0]
133
- expect(described.description).toBe('Runs in the background after: memory.saved, history.run.ended.')
134
-
135
- // Switched off for everyone again, it stops hearing; the other keeps going.
136
- await call('plugins.detach', { id: docs.id })
137
- await harness.hooks.reload()
138
- await saveFact('Indent', 'Two spaces.')
139
- await harness.hooks.settled()
140
- expect([told(one).length, told(two).length]).toEqual([1, 2])
141
- })
142
-
143
- it('never lets a hook that throws or hangs touch the write, and shows what went wrong on its plugin', async () => {
144
- const bus = new Bus()
145
- const base = temp()
146
- const out = join(base, 'ok.log')
147
- writeFile(join(base, 'bad.mjs'), `export default function (harness) { harness.on('memory.saved', async () => { throw new Error('the document is gone') }) }\n`)
148
- writeFile(join(base, 'slow.mjs'), `export default function (harness) { harness.on('memory.saved', () => new Promise(() => {})) }\n`)
149
- writeFile(join(base, 'good.mjs'), recorder(out, ['memory.saved']))
150
- writeFile(join(base, 'broken.mjs'), `export const nothing = 1\n`)
151
- writeFile(join(base, 'unknown.mjs'), `export default function (harness) { harness.on('memory.deleted', () => {}) }\n`)
152
- const hooks = new Hooks({ stateDir: base, bus, timeoutMs: 40, importFile, call: async () => undefined, wanted: async () => ['bad', 'slow', 'good', 'broken', 'unknown'].map((name) => ({ path: join(base, `${name}.mjs`), hash: 'h1' })) })
153
- await hooks.reload()
154
- const event: HookEvent = { type: 'memory.saved', id: 'f1', path: '/w/facts/f1.md', title: 'Fact', body: 'Body', text: 'Body', actor: 'user', reason: 'Created', at: '2026-10-13T00:00:00.000Z' }
155
- hooks.emit(event)
156
- await hooks.settled()
157
- // The good hook ran although two before it failed.
158
- expect(told(out)).toHaveLength(1)
159
- const status = hooks.status()
160
- expect(status[join(base, 'bad.mjs')]).toMatchObject({ events: ['memory.saved'], lastError: 'memory.saved: the document is gone' })
161
- expect(status[join(base, 'slow.mjs')].lastError).toMatch(/took longer than/)
162
- expect(status[join(base, 'good.mjs')]).toMatchObject({ lastError: null, lastRunAt: expect.any(String) })
163
- expect(status[join(base, 'broken.mjs')].lastError).toBe('It could not be loaded: It must export a default function.')
164
- expect(status[join(base, 'unknown.mjs')].lastError).toMatch(/There is no event called "memory.deleted"/)
165
- hooks.close()
166
- })
167
-
168
- it('reads a hooks file again when its code changed, and keeps the one it has when it did not', async () => {
169
- const base = temp()
170
- const path = join(base, 'hooks.mjs')
171
- let hash = 'h1'
172
- const read: string[] = []
173
- const heard: string[] = []
174
- // Stands in for the file on disk: each read gives the code as it is at that moment.
175
- const importer = async (address: string) => {
176
- read.push(address.slice(address.indexOf('?')))
177
- const version = read.length
178
- return { default: (harness: { on(event: string, handler: () => void): void }) => harness.on('wiki.page.saved', () => void heard.push(`version ${version}`)) }
179
- }
180
- const hooks = new Hooks({ stateDir: base, bus: new Bus(), call: async () => undefined, importFile: importer, wanted: async () => [{ path, hash }] })
181
- const event: HookEvent = { type: 'wiki.page.saved', id: 'p1', path: '/w/library/p1.md', title: 'Page', body: 'One', text: 'One', actor: 'user', reason: 'Edited', at: '2026-10-13T00:00:00.000Z' }
182
- await hooks.reload()
183
- await hooks.reload()
184
- hooks.emit(event)
185
- await hooks.settled()
186
- hash = 'h2'
187
- await hooks.reload()
188
- hooks.emit(event)
189
- await hooks.settled()
190
- // The fingerprint is part of the address, so Node does not hand back the module it already has.
191
- expect(read).toEqual(['?v=h1', '?v=h2'])
192
- expect(heard).toEqual(['version 1', 'version 2'])
193
- hooks.close()
194
- })
195
-
196
- it('lets a hook reach a connected app only through a tool marked to run without asking', async () => {
197
- const { harness } = setup()
198
- await harness.apps.save({ id: 'docs', name: 'Docs', kind: 'local', command: process.execPath, args: [join(process.cwd(), 'tests/mcp-fixture.mjs')], enabled: true, global: true, readTools: ['read_record'] })
199
- await harness.apps.save({ id: 'private', name: 'Private', kind: 'local', command: process.execPath, args: [join(process.cwd(), 'tests/mcp-fixture.mjs')], enabled: true, global: false, agentIds: ['a1'], readTools: ['read_record'] })
200
- expect(await harness.apps.callUnattended('Docs', 'read_record', {})).toMatchObject({ content: [{ type: 'text', text: 'fixture' }] })
201
- await expect(harness.apps.callUnattended('Docs', 'change_record', {})).rejects.toThrow('asks before running "change_record"')
202
- // A hook runs for everyone, so an app that is on for one agent only is out of its reach.
203
- await expect(harness.apps.callUnattended('Private', 'read_record', {})).rejects.toThrow('on for everyone')
204
- await expect(harness.apps.callUnattended('Nope', 'read_record', {})).rejects.toThrow('no connected app called "Nope"')
205
- })
206
- })
207
-
208
- describe('a plugin an agent proposes', () => {
209
- const proposal = { name: 'Memory to Docs', description: 'Adds every saved memory to the team document.', extends: ['memory'], reason: 'You asked for a copy in Docs.', files: [{ path: 'hooks.mjs', content: "export default function (harness) { harness.on('memory.saved', async () => {}) }\n" }, { path: 'skills/docs/SKILL.md', content: '---\nname: docs\ndescription: How the copy works.\n---\nSteps.\n' }] }
210
-
211
- it('waits in the Inbox, and is saved switched off and untrusted only when the person accepts it', async () => {
212
- const { harness, root, call } = setup()
213
- const tool = pluginProposeTool(harness.env, { agentId: 'a1', agentName: 'Helper', actor: 'Chat' })
214
- expect(await tool.execute(proposal)).toBe('The plugin "memory-to-docs" is waiting in the Inbox. It is saved only if the user accepts it, and it does nothing until they switch it on and trust its code.')
215
- expect(existsSync(join(root, 'plugins'))).toBe(false)
216
- const [item] = listInbox(wikiDir(root))
217
- expect(item).toMatchObject({ kind: 'proposed', title: 'Proposed plugin "Memory to Docs"' })
218
- expect(item.detail).toContain('- hooks.mjs (')
219
- expect(item.detail).toContain('It brings code.')
220
- expect(item.detail).toContain('From Helper (Chat).')
221
-
222
- expect(await call<string>('wiki.inboxAccept', { itemId: item.id })).toBe('Saved the plugin "memory-to-docs", switched off. Its code does not run until you switch it on and trust it.')
223
- expect(readdirSync(join(root, 'plugins'))).toEqual(['memory-to-docs'])
224
- expect(JSON.parse(readFileSync(join(root, 'plugins/memory-to-docs/package.json'), 'utf8'))).toMatchObject({ name: 'memory-to-docs', description: proposal.description, harness: { extends: ['memory'], hooks: './hooks.mjs' } })
225
- const plugin = (await call<Plugin[]>('plugins.list')).find((candidate) => candidate.id === 'package:memory-to-docs')!
226
- expect(plugin).toMatchObject({ extends: ['memory'], trust: 'untrusted', install: { kind: 'folder' }, attachment: { global: false } })
227
- expect(plugin.contributions.map((entry) => [entry.kind, entry.name, entry.state])).toEqual([['skill', 'docs', 'off'], ['code', 'hooks.mjs', 'off']])
228
- await harness.hooks.reload()
229
- expect(Object.keys(harness.hooks.status())).toEqual([])
230
- // Accepting the same proposal again would overwrite a folder, so it is refused.
231
- await tool.execute(proposal)
232
- await expect(call('wiki.inboxAccept', { itemId: listInbox(wikiDir(root))[0].id })).rejects.toThrow('already a plugin folder')
233
- })
234
-
235
- it('refuses what could not be a safe plugin, and says why', () => {
236
- const bad = (change: Partial<typeof proposal>) => () => checkPluginProposal({ ...proposal, ...change })
237
- expect(bad({ name: ' ' })).toThrow('short name')
238
- expect(bad({ description: '' })).toThrow('one line')
239
- expect(bad({ extends: ['approvals'] })).toThrow('"approvals" is none of them')
240
- expect(bad({ files: [] })).toThrow('between 1 and 40 files')
241
- expect(bad({ files: [{ path: '../outside.mjs', content: 'x' }] })).toThrow('not a path inside the plugin')
242
- expect(bad({ files: [{ path: '/etc/hosts', content: 'x' }] })).toThrow('not a path inside the plugin')
243
- expect(bad({ files: [{ path: '.env', content: 'x' }] })).toThrow('cannot be part of a plugin')
244
- expect(bad({ files: [{ path: 'node_modules/x/index.js', content: 'x' }] })).toThrow('cannot be part of a plugin')
245
- expect(bad({ files: [{ path: 'package.json', content: '{}' }] })).toThrow('Leave package.json out')
246
- expect(bad({ files: [{ path: 'a.md', content: 'x' }, { path: 'A.md', content: 'y' }] })).toThrow('listed twice')
247
- expect(bad({ files: [{ path: 'big.md', content: 'x'.repeat(300 * 1024) }] })).toThrow('larger than 256 KiB')
248
- expect(checkPluginProposal({ ...proposal, files: [{ path: './skills/a/SKILL.md', content: 'x' }] })).toMatchObject({ slug: 'memory-to-docs', hooks: null, runsCode: false })
249
- })
250
- })
@@ -1,239 +0,0 @@
1
- // Hooks: code a plugin gives the harness to run after something changed. A Pi extension lives
2
- // only while a session is open, and most memory is written outside one (a person accepts an
3
- // Inbox item, edits a fact, the background upkeep runs), so these are the harness's own events,
4
- // delivered in its own process.
5
- //
6
- // A hook is told after the fact. It cannot stop or change a write, it runs with a time limit,
7
- // and what it throws is recorded and shown on its plugin. It reaches outside only through
8
- // `ctx.call`, which the harness limits to connected-app tools a person marked to run without asking.
9
- import { chmodSync } from 'node:fs'
10
- import { join, sep } from 'node:path'
11
- import { pathToFileURL } from 'node:url'
12
-
13
- import type { Bus } from '../core/bus'
14
- import { log } from '../core/bus'
15
- import { onChange, type Change } from '../core/changes'
16
- import * as frontmatter from '../core/frontmatter'
17
- import { now, readJsonOr, writeJson } from '../core/fs'
18
-
19
- export const HOOK_EVENTS = ['memory.saved', 'memory.block.changed', 'wiki.page.saved', 'history.run.ended'] as const
20
- export type HookEventType = (typeof HOOK_EVENTS)[number]
21
-
22
- /** A fact, a memory block, or a page, as it is after the change. */
23
- export interface EntryEvent {
24
- type: 'memory.saved' | 'memory.block.changed' | 'wiki.page.saved'
25
- id: string
26
- path: string
27
- title: string
28
- /** The entry without its front matter. */
29
- body: string
30
- /** The whole file. */
31
- text: string
32
- /** Who made the change: `user`, an agent's name, or the background upkeep. */
33
- actor: string
34
- reason: string
35
- at: string
36
- }
37
-
38
- export interface RunEndedEvent {
39
- type: 'history.run.ended'
40
- runId: string
41
- sessionId: string
42
- status: string
43
- goal: string | null
44
- agentId: string | null
45
- projectId: string | null
46
- startedAt: string
47
- endedAt: string | null
48
- at: string
49
- }
50
-
51
- export type HookEvent = EntryEvent | RunEndedEvent
52
-
53
- export interface HookContext {
54
- /** Calls a tool of a connected app that is on for everyone, if a person marked that tool to run without asking. */
55
- call(connection: string, tool: string, args?: Record<string, unknown>): Promise<unknown>
56
- log(message: string): void
57
- }
58
-
59
- type Handler = (event: HookEvent, context: HookContext) => unknown
60
-
61
- /** What a hooks file is given: `export default function (harness) { harness.on('memory.saved', …) }`. */
62
- export interface HookApi {
63
- on(event: HookEventType, handler: Handler): void
64
- }
65
-
66
- export interface HookTarget {
67
- /** The hooks file. */
68
- path: string
69
- /** A hash of the package's code, so a changed file is loaded again. */
70
- hash: string
71
- }
72
-
73
- export interface HookStatus {
74
- /** The events it listens for. */
75
- events: string[]
76
- lastRunAt: string | null
77
- /** Why it could not be loaded, or what its last failing run threw. */
78
- lastError: string | null
79
- }
80
-
81
- export interface HooksOptions {
82
- stateDir: string
83
- bus: Bus
84
- /** The hooks files that should run now: attached for everyone, and trusted. */
85
- wanted: () => Promise<HookTarget[]>
86
- call: HookContext['call']
87
- /** How long one handler may take. */
88
- timeoutMs?: number
89
- /** Reads a hooks file as a module. Replaced in tests, where the runner owns `import()`. */
90
- importFile?: (address: string) => Promise<unknown>
91
- }
92
-
93
- // Node's own `import()`, out of reach of a bundler or a test runner that would rewrite it: a hooks
94
- // file is a person's file on disk, loaded as it is, and its address must reach Node unchanged.
95
- const importFile = new Function('address', 'return import(address)') as (address: string) => Promise<unknown>
96
-
97
- interface Loaded extends HookTarget {
98
- handlers: Map<string, Handler[]>
99
- }
100
-
101
- /** Which event a written file is, from where it is in the Wiki. */
102
- export function entryEvent(change: Change): EntryEvent {
103
- const within = change.path.startsWith(`${change.wiki}${sep}`) ? change.path.slice(change.wiki.length + 1).split(sep) : []
104
- const type = within[0] === 'facts' ? 'memory.saved' : within[0] === 'blocks' ? 'memory.block.changed' : 'wiki.page.saved'
105
- const parsed = frontmatter.parse(change.text)
106
- const front = (parsed?.front ?? {}) as Record<string, unknown>
107
- const title = typeof front.title === 'string' ? front.title : typeof front.label === 'string' ? front.label : change.id
108
- return { type, id: change.id, path: change.path, title, body: (parsed?.body ?? change.text).trim(), text: change.text, actor: change.actor, reason: change.reason, at: now() }
109
- }
110
-
111
- export class Hooks {
112
- private loaded: Loaded[] = []
113
- private readonly queue: HookEvent[] = []
114
- private working: Promise<void> = Promise.resolve()
115
- private reloading: Promise<void> = Promise.resolve()
116
- private readonly statusPath: string
117
- private wiki: string | null = null
118
- private readonly stop: () => void
119
-
120
- constructor(private readonly options: HooksOptions) {
121
- this.statusPath = join(options.stateDir, 'plugin-hooks.json')
122
- this.stop = onChange((change) => {
123
- // Several harnesses can share a process; each hears only about its own Wiki.
124
- if (change.wiki === this.wiki) this.emit(entryEvent(change))
125
- })
126
- }
127
-
128
- /** The Wiki whose changes these hooks hear about. */
129
- watch(wiki: string | null): void {
130
- this.wiki = wiki
131
- }
132
-
133
- /** What each hooks file listens for, and how its last run went. */
134
- status(): Record<string, HookStatus> {
135
- return readJsonOr<Record<string, HookStatus>>(this.statusPath, {})
136
- }
137
-
138
- private record(path: string, change: Partial<HookStatus>): void {
139
- const all = this.status()
140
- const before = all[path] ?? { events: [], lastRunAt: null, lastError: null }
141
- const next = { ...before, ...change }
142
- if (JSON.stringify(before) === JSON.stringify(next) && all[path]) return
143
- all[path] = next
144
- writeJson(this.statusPath, all)
145
- chmodSync(this.statusPath, 0o600)
146
- // A new failure, or a failure that cleared, is something a person looking at the plugin should see.
147
- if (before.lastError !== next.lastError || before.events.join() !== next.events.join()) this.options.bus.emit({ type: 'plugins.changed' })
148
- }
149
-
150
- /** Loads the hooks files that should run and drops the ones that should not. Safe to call often. */
151
- reload(): Promise<void> {
152
- this.reloading = this.reloading.then(async () => {
153
- let wanted: HookTarget[]
154
- try {
155
- wanted = await this.options.wanted()
156
- } catch (error) {
157
- log('plugin hooks', error instanceof Error ? error.message : String(error))
158
- return
159
- }
160
- const next: Loaded[] = []
161
- for (const target of wanted) {
162
- const kept = this.loaded.find((hook) => hook.path === target.path && hook.hash === target.hash)
163
- if (kept) {
164
- next.push(kept)
165
- continue
166
- }
167
- const handlers = new Map<string, Handler[]>()
168
- try {
169
- // The hash is part of the address, so a changed file is read again and not served from the module cache.
170
- const module = (await (this.options.importFile ?? importFile)(`${pathToFileURL(target.path).href}?v=${target.hash}`)) as { default?: unknown }
171
- if (typeof module.default !== 'function') throw new Error('It must export a default function.')
172
- const api: HookApi = {
173
- on: (event, handler) => {
174
- if (!(HOOK_EVENTS as readonly string[]).includes(event)) throw new Error(`There is no event called "${String(event)}". The events are ${HOOK_EVENTS.join(', ')}.`)
175
- if (typeof handler !== 'function') throw new Error('A handler must be a function.')
176
- handlers.set(event, [...(handlers.get(event) ?? []), handler])
177
- }
178
- }
179
- await (module.default as (api: HookApi) => unknown)(api)
180
- next.push({ ...target, handlers })
181
- this.record(target.path, { events: [...handlers.keys()], lastError: null })
182
- } catch (error) {
183
- this.record(target.path, { events: [], lastError: `It could not be loaded: ${error instanceof Error ? error.message : String(error)}` })
184
- }
185
- }
186
- this.loaded = next
187
- })
188
- return this.reloading
189
- }
190
-
191
- /** Takes an event down. It is delivered afterwards, in the order events arrived. */
192
- emit(event: HookEvent): void {
193
- this.queue.push(event)
194
- this.working = this.working.then(() => this.drain())
195
- }
196
-
197
- private async drain(): Promise<void> {
198
- // A file can change on disk without anyone telling the harness. What is loaded is checked
199
- // against what should run before it is told anything, so code that changed since it was
200
- // trusted stops here. With nothing loaded there is nothing to check: a new hook arrives
201
- // with a `plugins.changed` notice.
202
- if (this.loaded.length) await this.reload()
203
- else await this.reloading
204
- for (let event = this.queue.shift(); event; event = this.queue.shift()) {
205
- for (const hook of this.loaded) {
206
- for (const handler of hook.handlers.get(event.type) ?? []) await this.run(hook, handler, event)
207
- }
208
- }
209
- }
210
-
211
- private async run(hook: Loaded, handler: Handler, event: HookEvent): Promise<void> {
212
- const context: HookContext = { call: this.options.call, log: (message) => log(`plugin hook ${hook.path}`, String(message)) }
213
- let timer: ReturnType<typeof setTimeout> | undefined
214
- try {
215
- await Promise.race([
216
- Promise.resolve().then(() => handler(event, context)),
217
- new Promise((_, reject) => {
218
- timer = setTimeout(() => reject(new Error(`It took longer than ${Math.round((this.options.timeoutMs ?? 30_000) / 1000)} seconds and was left behind.`)), this.options.timeoutMs ?? 30_000)
219
- })
220
- ])
221
- this.record(hook.path, { lastRunAt: now(), lastError: null })
222
- } catch (error) {
223
- this.record(hook.path, { lastRunAt: now(), lastError: `${event.type}: ${error instanceof Error ? error.message : String(error)}`.slice(0, 1000) })
224
- } finally {
225
- if (timer) clearTimeout(timer)
226
- }
227
- }
228
-
229
- /** Resolves when every event taken down so far was delivered. */
230
- async settled(): Promise<void> {
231
- await this.reloading
232
- await this.working
233
- }
234
-
235
- close(): void {
236
- this.stop()
237
- this.loaded = []
238
- }
239
- }
@@ -1,37 +0,0 @@
1
- // Which plugin a found file belongs to, and what it is called there. The list a person sees and
2
- // the choice of what loads both use this, so a switch on the page names exactly what stops loading.
3
- import { basename, dirname } from 'node:path'
4
-
5
- import * as registry from '../skills/registry'
6
- import { BUILTIN_PREFIX, type Found } from './discover'
7
- import { packageManifest } from './manifest'
8
- import type { ContributionKind } from './types'
9
-
10
- export { packageManifest } from './manifest'
11
-
12
- export const FOUND_KINDS: Record<Found['kind'], ContributionKind> = { extension: 'code', hook: 'code', skill: 'skill', prompt: 'command', theme: 'theme', context: 'instruction' }
13
-
14
- /** The id of the plugin a found item is listed under. */
15
- export function pluginIdOf(item: Found): string {
16
- if (item.origin === 'builtin') return 'pi'
17
- if (item.packageRoot) return `package:${packageManifest(item.packageRoot).name}`
18
- return item.origin === 'home' ? 'home' : item.origin === 'project' ? 'project' : 'shared'
19
- }
20
-
21
- /** A found item's name and description as a person reads them. */
22
- export function describeFound(item: Found): { name: string; description: string | null } {
23
- if (item.path.startsWith(BUILTIN_PREFIX)) return { name: item.path.slice(BUILTIN_PREFIX.length), description: null }
24
- const file = basename(item.path)
25
- if (item.kind === 'extension') return { name: file.startsWith('index.') ? basename(dirname(item.path)) : file, description: null }
26
- if (item.kind === 'context' || item.kind === 'theme' || item.kind === 'hook') return { name: file, description: null }
27
- const described = registry.describeFile(item.path)
28
- return { name: described?.name ?? file, description: described?.description ?? '' }
29
- }
30
-
31
- export const contributionId = (pluginId: string, kind: ContributionKind, name: string): string => `${pluginId}/${kind}/${name}`
32
-
33
- /** The ids a choice about a found item is stored under: the item itself, then its plugin. */
34
- export function foundIds(item: Found): [string, string] {
35
- const pluginId = pluginIdOf(item)
36
- return [contributionId(pluginId, FOUND_KINDS[item.kind], describeFound(item).name), pluginId]
37
- }
@@ -1,107 +0,0 @@
1
- import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { afterEach, describe, expect, it } from 'vitest'
5
-
6
- import { sharedDir } from '../accounts/env'
7
- import { memorySecretStore } from '../accounts/secrets'
8
- import { createHarness, type Harness } from '../harness'
9
- import { methods } from '../server/methods'
10
- import { rootWithProject, writeFile } from '../../tests/helpers'
11
- import { normalizeSource } from './install'
12
- import type { Plugin } from './types'
13
-
14
- const open: Harness[] = []
15
- afterEach(async () => {
16
- for (const harness of open.splice(0)) await harness.close()
17
- })
18
-
19
- function setup() {
20
- const root = rootWithProject()
21
- const base = mkdtempSync(join(tmpdir(), 'install-'))
22
- const harness = createHarness({ dataRoot: root, stateDir: join(base, 'state'), secrets: memorySecretStore() })
23
- open.push(harness)
24
- harness.accounts.create('Main', 'apiKey')
25
- const agentDir = harness.accounts.context(harness.accounts.resolve(null, null)).configDir
26
- const table = methods(harness)
27
- const call = <T>(method: string, params: Record<string, unknown> = {}) => table[method](params) as Promise<T>
28
- const loaded = async () => {
29
- const loading = await harness.plugins.loading({ cwd: base, agentDir, caller: {} })
30
- return { extensions: loading.extensionPaths.map((path) => path.replace(`${base}/`, '')), skills: loading.skillPaths.map((path) => path.replace(`${base}/`, '')) }
31
- }
32
- return { harness, root, base, call, loaded }
33
- }
34
-
35
- function kit(folder: string): void {
36
- writeFile(join(folder, 'package.json'), JSON.stringify({ name: 'review-kit', description: 'Review helpers.', version: '1.0.0' }))
37
- writeFile(join(folder, 'extensions/guard.ts'), 'export default function () {}\n')
38
- writeFile(join(folder, 'skills/audit/SKILL.md'), '---\nname: audit\ndescription: Audit a change.\n---\nSteps.\n')
39
- }
40
-
41
- describe('installing a package', () => {
42
- it('reads a name as an npm package, keeps a folder or an address as it is, and refuses a relative path', () => {
43
- expect(normalizeSource(' pi-tools ')).toBe('npm:pi-tools')
44
- expect(normalizeSource('npm:@scope/pi-tools@1.0.0')).toBe('npm:@scope/pi-tools@1.0.0')
45
- expect(normalizeSource('git:github.com/example/pi-tools@v1')).toBe('git:github.com/example/pi-tools@v1')
46
- expect(normalizeSource('https://github.com/example/pi-tools')).toBe('https://github.com/example/pi-tools')
47
- expect(normalizeSource('/tmp/kit/')).toBe('/tmp/kit')
48
- expect(() => normalizeSource('./kit')).toThrow('whole path')
49
- expect(() => normalizeSource(' ')).toThrow()
50
- })
51
-
52
- it('arrives switched off and untrusted, and loads only once it is both switched on and trusted', async () => {
53
- const { harness, base, call, loaded } = setup()
54
- kit(join(base, 'kit'))
55
- const after = await call<Plugin[]>('plugins.install', { source: join(base, 'kit') })
56
- const plugin = after.find((candidate) => candidate.id === 'package:review-kit')!
57
- expect(plugin).toMatchObject({ source: 'package', version: '1.0.0', runsCode: true, trust: 'untrusted', install: { kind: 'settings', source: join(base, 'kit') }, attachment: { global: false } })
58
- expect(plugin.contributions.map((entry) => `${entry.kind}:${entry.name}:${entry.state}`)).toEqual(['code:guard.ts:off', 'skill:audit:off'])
59
- // It is named in the settings every account shares, as `pi install` would have done.
60
- expect(JSON.parse(readFileSync(join(sharedDir(harness.accounts.dir), 'settings.json'), 'utf8')).packages).toEqual([join(base, 'kit')])
61
- expect(await loaded()).toEqual({ extensions: [], skills: [] })
62
-
63
- // Switched on, its text loads; its code still waits for trust.
64
- await call('plugins.attach', { id: plugin.id })
65
- expect(await loaded()).toEqual({ extensions: [], skills: ['kit/skills/audit/SKILL.md'] })
66
- const trusted = await call<Plugin[]>('plugins.trust', { hash: plugin.code!.hash })
67
- expect(trusted.find((candidate) => candidate.id === plugin.id)).toMatchObject({ trust: 'trusted' })
68
- expect(await loaded()).toEqual({ extensions: ['kit/extensions/guard.ts'], skills: ['kit/skills/audit/SKILL.md'] })
69
-
70
- // A stale fingerprint is refused, and changed code waits again.
71
- writeFileSync(join(base, 'kit/extensions/guard.ts'), 'export default function () { /* changed */ }\n')
72
- await expect(call('plugins.trust', { hash: plugin.code!.hash })).rejects.toThrow('changed since it was shown')
73
- expect((await loaded()).extensions).toEqual([])
74
-
75
- const removed = await call<Plugin[]>('plugins.remove', { pluginId: plugin.id })
76
- expect(removed.some((candidate) => candidate.id === plugin.id)).toBe(false)
77
- expect(JSON.parse(readFileSync(join(sharedDir(harness.accounts.dir), 'settings.json'), 'utf8')).packages ?? []).toEqual([])
78
- // A folder that was installed in place is not deleted with its entry.
79
- expect(existsSync(join(base, 'kit/package.json'))).toBe(true)
80
- expect(await loaded()).toEqual({ extensions: [], skills: [] })
81
- })
82
-
83
- it('refuses a folder that is not there, and a plugin that was not installed', async () => {
84
- const { base, call } = setup()
85
- await expect(call('plugins.install', { source: join(base, 'missing') })).rejects.toThrow('does not exist')
86
- await expect(call('plugins.remove', { pluginId: 'memory' })).rejects.toThrow('was not installed as a package')
87
- await expect(call('plugins.update', { pluginId: 'nope' })).rejects.toThrow()
88
- })
89
-
90
- it('finds a package kept as a folder beside the data, and moves it to the trash when removed', async () => {
91
- const { root, call, loaded, harness } = setup()
92
- // Trust has been asked per package before this folder appears, so its code waits.
93
- harness.plugins.trust.adopt([])
94
- kit(join(root, 'plugins/review-kit'))
95
- mkdirSync(join(root, 'plugins/.hidden'), { recursive: true })
96
- const plugins = await call<Plugin[]>('plugins.list')
97
- const plugin = plugins.find((candidate) => candidate.id === 'package:review-kit')!
98
- expect(plugin).toMatchObject({ trust: 'untrusted', install: { kind: 'folder', source: join(root, 'plugins/review-kit') }, attachment: { global: true } })
99
- expect((await loaded()).skills.some((path) => path.endsWith('plugins/review-kit/skills/audit/SKILL.md'))).toBe(true)
100
- expect((await loaded()).extensions).toEqual([])
101
- await expect(call('plugins.update', { pluginId: plugin.id })).rejects.toThrow('is a folder on this machine')
102
-
103
- await call('plugins.remove', { pluginId: plugin.id })
104
- expect(existsSync(join(root, 'plugins/review-kit'))).toBe(false)
105
- expect(readdirSync(join(root, 'trash/plugins')).some((name) => name.startsWith('review-kit-'))).toBe(true)
106
- })
107
- })