@xingular/harness 0.1.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (683) hide show
  1. package/CHANGELOG.md +97 -1
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +22 -0
  4. package/README.md +187 -85
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +13701 -13498
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +808 -151
  373. package/docs/README.md +22 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  403. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  404. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  405. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  406. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  407. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  408. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  409. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  410. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  411. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  412. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  413. package/docs/decisions/ADR-0013-doctor.md +27 -0
  414. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  415. package/docs/doctor.md +74 -0
  416. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  418. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  420. package/docs/features/README.md +20 -0
  421. package/docs/features/automations/README.md +41 -0
  422. package/docs/features/cores/README.md +39 -0
  423. package/docs/features/google-harness2/README.md +52 -0
  424. package/docs/features/integrations/README.md +40 -0
  425. package/docs/features/interfaces/README.md +29 -0
  426. package/docs/features/memory/README.md +28 -0
  427. package/docs/releases/1.0.0.md +40 -0
  428. package/docs/releases/README.md +36 -0
  429. package/docs/study/00-index.md +78 -0
  430. package/docs/study/arms/00-matrix.md +20 -0
  431. package/docs/study/arms/01-system-prompt.md +211 -0
  432. package/docs/study/arms/02-tools.md +79 -0
  433. package/docs/study/arms/03-subagents.md +90 -0
  434. package/docs/study/arms/04-skills.md +75 -0
  435. package/docs/study/arms/05-context-management.md +90 -0
  436. package/docs/study/arms/06-memory.md +90 -0
  437. package/docs/study/arms/07-governance.md +71 -0
  438. package/docs/study/arms/08-execution.md +69 -0
  439. package/docs/study/arms/09-observability.md +60 -0
  440. package/docs/study/arms/10-refinement.md +110 -0
  441. package/docs/study/btw-comparison.md +37 -0
  442. package/docs/study/feature-gap-review.md +42 -0
  443. package/docs/study/insights.md +123 -0
  444. package/docs/study/roadmap.md +72 -0
  445. package/docs/study/sources/claude-code.md +44 -0
  446. package/docs/study/sources/deepseek-harness.md +102 -0
  447. package/docs/study/sources/harness2.md +50 -0
  448. package/docs/study/sources/kimi-cli.md +42 -0
  449. package/docs/study/sources/omp.md +93 -0
  450. package/docs/study/sources/opencode.md +43 -0
  451. package/docs/study/sources/openhands.md +46 -0
  452. package/docs/study/sources/smolagents.md +40 -0
  453. package/docs/study/sources/swe-agent.md +34 -0
  454. package/docs/system-prompt-design.md +196 -0
  455. package/docs/terminal-tui.md +473 -56
  456. package/package.json +43 -13
  457. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  458. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  459. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  460. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  461. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  462. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  463. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  464. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  465. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  466. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  467. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  468. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  469. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  470. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  471. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  472. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  473. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  474. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  475. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  476. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  477. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  478. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  479. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  480. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  481. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  482. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  483. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  484. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  485. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  486. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  487. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  488. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  489. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  490. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  491. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  492. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  493. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  494. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  495. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  496. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  497. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  498. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  499. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
  500. package/src/accounts/accounts.test.ts +0 -333
  501. package/src/accounts/accounts.ts +0 -658
  502. package/src/accounts/env.test.ts +0 -95
  503. package/src/accounts/env.ts +0 -338
  504. package/src/accounts/secrets.ts +0 -50
  505. package/src/accounts/store.ts +0 -338
  506. package/src/capabilities/api.ts +0 -75
  507. package/src/capabilities/runSnapshot.ts +0 -59
  508. package/src/capabilities/types.ts +0 -34
  509. package/src/cli.ts +0 -118
  510. package/src/core/bus.ts +0 -34
  511. package/src/core/changes.ts +0 -33
  512. package/src/core/env.ts +0 -27
  513. package/src/core/errors.ts +0 -32
  514. package/src/core/frontmatter.ts +0 -47
  515. package/src/core/fs.test.ts +0 -38
  516. package/src/core/fs.ts +0 -92
  517. package/src/core/index.ts +0 -193
  518. package/src/core/path.test.ts +0 -14
  519. package/src/core/path.ts +0 -79
  520. package/src/core/projects.ts +0 -90
  521. package/src/core/text.ts +0 -39
  522. package/src/harness.ts +0 -312
  523. package/src/hub/catalog.json +0 -123
  524. package/src/hub/cli.ts +0 -59
  525. package/src/hub/hub.test.ts +0 -205
  526. package/src/hub/hub.ts +0 -256
  527. package/src/hub/schema.ts +0 -81
  528. package/src/index.ts +0 -75
  529. package/src/mcp/connections.ts +0 -614
  530. package/src/mcp/manager.ts +0 -130
  531. package/src/mcp/oauth.ts +0 -195
  532. package/src/mcp/scopeMigration.test.ts +0 -79
  533. package/src/mcp/scopeMigration.ts +0 -204
  534. package/src/mcp/service.test.ts +0 -376
  535. package/src/mcp/service.ts +0 -549
  536. package/src/mcp/types.ts +0 -108
  537. package/src/memory/api.test.ts +0 -82
  538. package/src/memory/api.ts +0 -303
  539. package/src/memory/blocks.test.ts +0 -78
  540. package/src/memory/blocks.ts +0 -408
  541. package/src/memory/caller.ts +0 -69
  542. package/src/memory/curation.test.ts +0 -163
  543. package/src/memory/curation.ts +0 -64
  544. package/src/memory/dispatch.ts +0 -59
  545. package/src/memory/facts.test.ts +0 -41
  546. package/src/memory/facts.ts +0 -248
  547. package/src/memory/graph.ts +0 -103
  548. package/src/memory/health.test.ts +0 -130
  549. package/src/memory/health.ts +0 -74
  550. package/src/memory/maintainer.ts +0 -272
  551. package/src/memory/maintenance.test.ts +0 -176
  552. package/src/memory/maintenance.ts +0 -518
  553. package/src/memory/migrate.ts +0 -79
  554. package/src/memory/operations.ts +0 -150
  555. package/src/memory/proposals.test.ts +0 -168
  556. package/src/memory/proposals.ts +0 -584
  557. package/src/memory/recall.test.ts +0 -115
  558. package/src/memory/recall.ts +0 -278
  559. package/src/memory/references.ts +0 -77
  560. package/src/memory/runContext.ts +0 -93
  561. package/src/memory/secrets.ts +0 -6
  562. package/src/memory/store.test.ts +0 -66
  563. package/src/memory/store.ts +0 -385
  564. package/src/memory/wiki.test.ts +0 -47
  565. package/src/memory/wiki.ts +0 -422
  566. package/src/memory/wikiIndex.test.ts +0 -88
  567. package/src/memory/wikiIndex.ts +0 -116
  568. package/src/plugins/api.ts +0 -181
  569. package/src/plugins/attachments.test.ts +0 -84
  570. package/src/plugins/attachments.ts +0 -141
  571. package/src/plugins/builtin.ts +0 -82
  572. package/src/plugins/catalogue.test.ts +0 -254
  573. package/src/plugins/catalogue.ts +0 -251
  574. package/src/plugins/cli.ts +0 -184
  575. package/src/plugins/discover.ts +0 -151
  576. package/src/plugins/firstParty.test.ts +0 -143
  577. package/src/plugins/firstParty.ts +0 -129
  578. package/src/plugins/hooks.test.ts +0 -250
  579. package/src/plugins/hooks.ts +0 -239
  580. package/src/plugins/identity.ts +0 -37
  581. package/src/plugins/install.test.ts +0 -107
  582. package/src/plugins/install.ts +0 -106
  583. package/src/plugins/inventory.ts +0 -123
  584. package/src/plugins/manifest.ts +0 -76
  585. package/src/plugins/plugins.test.ts +0 -205
  586. package/src/plugins/plugins.ts +0 -189
  587. package/src/plugins/proposal.ts +0 -121
  588. package/src/plugins/runtime.test.ts +0 -40
  589. package/src/plugins/runtime.ts +0 -82
  590. package/src/plugins/trust.ts +0 -142
  591. package/src/plugins/types.ts +0 -149
  592. package/src/prompt/compile.test.ts +0 -261
  593. package/src/prompt/compile.ts +0 -732
  594. package/src/server/methods.ts +0 -349
  595. package/src/server/remote.ts +0 -77
  596. package/src/server/rpc.ts +0 -116
  597. package/src/server/serve.ts +0 -28
  598. package/src/server/server.test.ts +0 -174
  599. package/src/sessions/approvals.ts +0 -118
  600. package/src/sessions/contracts.ts +0 -336
  601. package/src/sessions/conversation.test.ts +0 -177
  602. package/src/sessions/extensionSession.test.ts +0 -74
  603. package/src/sessions/extensionUi.test.ts +0 -65
  604. package/src/sessions/extensionUi.ts +0 -102
  605. package/src/sessions/history.ts +0 -51
  606. package/src/sessions/lineageJoin.ts +0 -75
  607. package/src/sessions/policy.ts +0 -36
  608. package/src/sessions/pricing.ts +0 -60
  609. package/src/sessions/questionBatches.test.ts +0 -110
  610. package/src/sessions/reasoningSummaries.ts +0 -59
  611. package/src/sessions/registry.ts +0 -381
  612. package/src/sessions/runIndex.ts +0 -99
  613. package/src/sessions/runStore.test.ts +0 -152
  614. package/src/sessions/runStore.ts +0 -332
  615. package/src/sessions/runner.ts +0 -604
  616. package/src/sessions/runtimeResources.test.ts +0 -61
  617. package/src/sessions/sessions.test.ts +0 -549
  618. package/src/sessions/sessions.ts +0 -339
  619. package/src/skills/registry.test.ts +0 -104
  620. package/src/skills/registry.ts +0 -413
  621. package/src/terminal/accountsMenu.test.ts +0 -225
  622. package/src/terminal/accountsMenu.ts +0 -382
  623. package/src/terminal/cli.ts +0 -149
  624. package/src/terminal/client.ts +0 -74
  625. package/src/terminal/control.test.ts +0 -23
  626. package/src/terminal/control.ts +0 -23
  627. package/src/terminal/controller.ts +0 -291
  628. package/src/terminal/hubMenu.ts +0 -24
  629. package/src/terminal/launch.test.ts +0 -25
  630. package/src/terminal/launch.ts +0 -48
  631. package/src/terminal/piExtension.lifecycle.test.ts +0 -55
  632. package/src/terminal/piExtension.ts +0 -259
  633. package/src/terminal/pluginControl.test.ts +0 -146
  634. package/src/terminal/pluginMenu.ts +0 -112
  635. package/src/terminal/socket.test.ts +0 -71
  636. package/src/terminal/socket.ts +0 -232
  637. package/src/terminal/standalone.test.ts +0 -167
  638. package/src/terminal/standalone.ts +0 -153
  639. package/src/terminal/terminal.test.ts +0 -399
  640. package/src/terminal/terminals.ts +0 -553
  641. package/src/terminal/tui/application.test.ts +0 -114
  642. package/src/terminal/tui/application.ts +0 -491
  643. package/src/terminal/tui/commands.test.ts +0 -218
  644. package/src/terminal/tui/commands.ts +0 -361
  645. package/src/terminal/tui/dialogs.ts +0 -301
  646. package/src/terminal/tui/editor.test.ts +0 -84
  647. package/src/terminal/tui/editor.ts +0 -79
  648. package/src/terminal/tui/keybindings.test.ts +0 -22
  649. package/src/terminal/tui/keybindings.ts +0 -50
  650. package/src/terminal/tui/piAdapter.ts +0 -62
  651. package/src/terminal/tui/presentation.test.ts +0 -79
  652. package/src/terminal/tui/questions.test.ts +0 -41
  653. package/src/terminal/tui/questions.ts +0 -47
  654. package/src/terminal/tui/runtime.socket.test.ts +0 -104
  655. package/src/terminal/tui/runtime.test.ts +0 -215
  656. package/src/terminal/tui/runtime.ts +0 -388
  657. package/src/terminal/tui/sessionUi.ts +0 -24
  658. package/src/terminal/tui/settings.test.ts +0 -150
  659. package/src/terminal/tui/settings.ts +0 -188
  660. package/src/terminal/tui/status.test.ts +0 -70
  661. package/src/terminal/tui/status.ts +0 -109
  662. package/src/terminal/tui/theme.ts +0 -174
  663. package/src/terminal/tui/tools.test.ts +0 -145
  664. package/src/terminal/tui/tools.ts +0 -142
  665. package/src/terminal/tui/transcript.test.ts +0 -25
  666. package/src/terminal/tui/transcript.ts +0 -124
  667. package/src/terminal/tui/ui.test.ts +0 -313
  668. package/src/terminal/tui/ui.ts +0 -166
  669. package/src/terminal/tui/welcome.ts +0 -102
  670. package/src/tools/askUser.test.ts +0 -69
  671. package/src/tools/askUser.ts +0 -59
  672. package/src/tools/definitions.ts +0 -187
  673. package/src/tools/maintenance.ts +0 -24
  674. package/src/tools/memoryTools.ts +0 -22
  675. package/src/tools/pluginPropose.ts +0 -41
  676. package/src/tools/registryWrite.test.ts +0 -101
  677. package/src/tools/registryWrite.ts +0 -182
  678. package/src/tools/spawnSubagent.ts +0 -92
  679. package/src/tools/types.ts +0 -39
  680. package/src/web/safeRequest.ts +0 -171
  681. package/src/web/text.ts +0 -53
  682. package/src/web/tools.ts +0 -134
  683. package/src/web/web.test.ts +0 -141
@@ -1,106 +0,0 @@
1
- // Installing, updating and removing a package. Pi's own package manager does the work, against
2
- // the settings every account shares, so the `pi` command and the harness agree on what is
3
- // installed. Fetching runs none of a package's code, and what was installed is switched off and
4
- // untrusted until a person has looked at it.
5
- import { existsSync, mkdirSync, renameSync, statSync } from 'node:fs'
6
- import { homedir } from 'node:os'
7
- import { basename, isAbsolute, join, resolve } from 'node:path'
8
-
9
- import { ensureSharedDir } from '../accounts/env'
10
- import { invalid, notFound } from '../core/errors'
11
- import { now } from '../core/fs'
12
- import type { Harness } from '../harness'
13
- import { ensureAdopted, list, type PluginScope } from './api'
14
- import * as attachments from './attachments'
15
- import { withoutInstallScripts } from './discover'
16
- import type { Plugin } from './types'
17
-
18
- /** A folder on this machine, or a package as Pi's settings name it. A bare name is an npm package. */
19
- export function normalizeSource(input: string): string {
20
- const source = input.trim()
21
- if (!source) throw invalid('Name a package: a folder, an npm name, or a git address.')
22
- if (source.startsWith('~/')) return join(process.env.HOME || homedir(), source.slice(2))
23
- if (isAbsolute(source)) return resolve(source)
24
- if (source.startsWith('./') || source.startsWith('../')) throw invalid('Give the whole path of the folder.')
25
- return /^(npm:|git:|https?:\/\/|ssh:\/\/|git@)/.test(source) ? source : `npm:${source}`
26
- }
27
-
28
- async function manager(harness: Harness) {
29
- const pi = await import('@earendil-works/pi-coding-agent')
30
- // The shared folder is where `settings.json` really is; an account's own is a link to it.
31
- const agentDir = ensureSharedDir(harness.accounts.dir)
32
- const settings = pi.SettingsManager.create(harness.stateDir, agentDir)
33
- return { settings, packages: new pi.DefaultPackageManager({ cwd: harness.stateDir, agentDir, settingsManager: settings }) }
34
- }
35
-
36
- const changed = (harness: Harness): void => harness.bus.emit({ type: 'plugins.changed' })
37
-
38
- /**
39
- * Installs a package for every account. It arrives switched off, and if it brings code, not
40
- * trusted: nothing of it reaches a session until a person switches it on and trusts it.
41
- */
42
- export async function install(harness: Harness, params: PluginScope & { source: string }): Promise<Plugin[]> {
43
- const source = normalizeSource(params.source)
44
- if (isAbsolute(source) && !(existsSync(source) && statSync(source).isDirectory())) throw invalid('That folder does not exist.')
45
- // What was already there is taken over as trusted before anything new arrives, never after.
46
- await ensureAdopted(harness)
47
- const before = new Set((await list(harness, params)).map((plugin) => plugin.id))
48
- const { settings, packages } = await manager(harness)
49
- if (isAbsolute(source)) {
50
- // Pi would save a folder as a path relative to the settings file, and each account reads
51
- // that file through a link in its own folder, where a relative path points somewhere else.
52
- const named = settings.getGlobalSettings().packages ?? []
53
- if (!named.some((entry) => (typeof entry === 'string' ? entry : entry.source) === source)) settings.setPackages([...named, source])
54
- await settings.flush()
55
- } else {
56
- await withoutInstallScripts(() => packages.installAndPersist(source))
57
- }
58
- const after = await list(harness, params)
59
- const added = after.filter((plugin) => plugin.install && !before.has(plugin.id))
60
- if (added.length) {
61
- const choices = attachments.load(harness.env.root)
62
- for (const plugin of added) attachments.set(choices, [plugin.id], {}, false, true)
63
- attachments.save(harness.env.root, choices)
64
- }
65
- changed(harness)
66
- return added.length ? list(harness, params) : after
67
- }
68
-
69
- function installed(plugins: readonly Plugin[], pluginId: string): Plugin & { install: NonNullable<Plugin['install']> } {
70
- const plugin = plugins.find((candidate) => candidate.id === pluginId)
71
- if (!plugin) throw notFound('Plugin')
72
- if (!plugin.install) throw invalid(`${plugin.title} was not installed as a package, so it cannot be removed or updated here.`)
73
- return plugin as Plugin & { install: NonNullable<Plugin['install']> }
74
- }
75
-
76
- /** Removes an installed package. One kept as a folder beside a person's data is moved to the trash there. */
77
- export async function remove(harness: Harness, params: PluginScope & { pluginId: string }): Promise<Plugin[]> {
78
- const plugin = installed(await list(harness, params), params.pluginId)
79
- if (plugin.install.kind === 'folder') {
80
- const trash = join(harness.env.root, 'trash', 'plugins')
81
- mkdirSync(trash, { recursive: true })
82
- renameSync(plugin.install.source, join(trash, `${basename(plugin.install.source)}-${now().replace(/[:.]/g, '-')}`))
83
- } else {
84
- await (await manager(harness)).packages.removeAndPersist(plugin.install.source)
85
- }
86
- const choices = attachments.load(harness.env.root)
87
- for (const scope of [choices.global, ...Object.values(choices.agents), ...Object.values(choices.projects)]) {
88
- scope.on = scope.on.filter((id) => id !== plugin.id && !id.startsWith(`${plugin.id}/`))
89
- scope.off = scope.off.filter((id) => id !== plugin.id && !id.startsWith(`${plugin.id}/`))
90
- }
91
- delete choices.settings[plugin.id]
92
- attachments.save(harness.env.root, choices)
93
- if (plugin.code) harness.plugins.trust.revoke(plugin.code.hash)
94
- changed(harness)
95
- return list(harness, params)
96
- }
97
-
98
- /** Fetches a newer version of one installed package, or of all of them. Changed code waits for trust again. */
99
- export async function update(harness: Harness, params: PluginScope & { pluginId?: string | null }): Promise<Plugin[]> {
100
- const plugin = params.pluginId ? installed(await list(harness, params), params.pluginId) : null
101
- if (plugin?.install.kind === 'folder') throw invalid(`${plugin.title} is a folder on this machine. Change its files to update it.`)
102
- const { packages } = await manager(harness)
103
- await withoutInstallScripts(() => packages.update(plugin?.install.source))
104
- changed(harness)
105
- return list(harness, params)
106
- }
@@ -1,123 +0,0 @@
1
- // What reaches one caller: every prompt section, tool, skill, connection and extension, each
2
- // attributed to the plugin it comes from. Anything no plugin accounts for is reported, so a new
3
- // source of model-visible text cannot appear without showing up here.
4
- import { readFileSync } from 'node:fs'
5
-
6
- import type { HarnessEnv } from '../core/env'
7
- import { charCount } from '../core/text'
8
- import { allowed } from '../mcp/connections'
9
- import type { Connection } from '../mcp/types'
10
- import type { CallerContext } from '../memory/caller'
11
- import { BUILT_IN_DYNAMIC, compile, toolGroups, type Launch } from '../prompt/compile'
12
- import * as registry from '../skills/registry'
13
- import { ASK_USER } from '../tools/askUser'
14
- import { PLUGIN_PROPOSE } from '../tools/pluginPropose'
15
- import { WIKI_TOOL_NAMES } from '../tools/definitions'
16
- import { INCLUDED_PLUGIN, YOURS_PLUGIN } from './builtin'
17
- import type { Contribution, Inventory, InventoryItem, Plugin, PluginDescriptor } from './types'
18
-
19
- export interface InventoryInput {
20
- env: HarnessEnv
21
- context: CallerContext
22
- /** What the application adds to the prompt for this caller, as it would for a session. */
23
- launch: Launch
24
- /** The tools the caller has switched on, as a session's `allow` list. */
25
- tools: readonly string[]
26
- /** Whether the caller gets the connected-apps tools. */
27
- connections: boolean
28
- plugins: readonly Plugin[]
29
- descriptors: readonly PluginDescriptor[]
30
- saved: readonly Connection[]
31
- }
32
-
33
- const size = (path: string | null): number | null => {
34
- if (!path) return null
35
- try {
36
- return charCount(readFileSync(path, 'utf8'))
37
- } catch {
38
- return null
39
- }
40
- }
41
-
42
- export function inventory(input: InventoryInput): Inventory {
43
- const { env, context, launch, descriptors } = input
44
- const items: InventoryItem[] = []
45
- const unattributed: Inventory['unattributed'] = []
46
- const item = (pluginId: string, kind: InventoryItem['kind'], name: string, delivery: InventoryItem['delivery'], chars: number | null, rest: Partial<InventoryItem> = {}): void => {
47
- items.push({ pluginId, contributionId: null, kind, name, delivery, chars, cut: false, ...rest })
48
- }
49
-
50
- const pack = compile(env, context, launch)
51
- const dynamic = new Set([...BUILT_IN_DYNAMIC.map((entry) => entry.id), ...(launch.sections ?? []).filter((section) => section.dynamic).map((section) => section.id)])
52
- const active = registry.enabledFor(env.root, context.projectId ?? null, context.agentId ?? null)
53
- const owner = (entry: registry.RegistryItem): string => (entry.builtin ? INCLUDED_PLUGIN.id : YOURS_PLUGIN.id)
54
- let systemChars = 0
55
- let contextChars = 0
56
-
57
- for (const section of pack.sections) {
58
- const delivery = dynamic.has(section.id) ? 'context' : 'system'
59
- if (delivery === 'context') contextChars += section.size
60
- else systemChars += section.size
61
- if (section.id === 'tools') {
62
- // One paragraph per tool group; each belongs to the plugin that provides the group.
63
- for (const group of toolGroups(context, launch)) {
64
- if (!group.guidance) continue
65
- const plugin = descriptors.find((descriptor) => descriptor.toolGroups?.includes(group.group))
66
- if (!plugin) unattributed.push({ kind: 'toolGroup', id: group.group })
67
- item(plugin?.id ?? '', 'instruction', `Tool guidance: ${group.group}`, delivery, charCount(group.guidance), { cut: section.cut })
68
- }
69
- continue
70
- }
71
- if (section.id === 'rules') {
72
- for (const rule of active.filter((entry) => entry.kind === 'rules')) {
73
- item(owner(rule), 'instruction', rule.name, delivery, charCount(`### ${rule.name} (${rule.id})\n\n${registry.itemBody(rule).trim()}`), { contributionId: `${owner(rule)}/${rule.id}`, cut: section.cut })
74
- }
75
- continue
76
- }
77
- const plugin = descriptors.find((descriptor) => descriptor.sections?.some((declared) => declared.id === section.id))
78
- if (!plugin) unattributed.push({ kind: 'section', id: section.id })
79
- const name = plugin?.sections?.find((declared) => declared.id === section.id)?.name ?? section.title
80
- item(plugin?.id ?? '', 'instruction', name, delivery, section.size, { contributionId: plugin ? `${plugin.id}/instruction/${name}` : null, cut: section.cut })
81
- }
82
-
83
- // A skill's or a prompt's own text is loaded only when it is used.
84
- for (const entry of active.filter((candidate) => candidate.kind === 'skills' || candidate.kind === 'prompts')) {
85
- item(owner(entry), entry.kind === 'skills' ? 'skill' : 'command', entry.name, 'on-demand', size(entry.path), { contributionId: `${owner(entry)}/${entry.id}` })
86
- }
87
-
88
- const names = [...input.tools]
89
- const extensionToolNames = new Set(input.plugins.filter((plugin) => ['project', 'package', 'shared', 'home'].includes(plugin.source)).flatMap((plugin) => plugin.contributions.filter((entry) => entry.kind === 'tool' && entry.state === 'on').map((entry) => entry.name)))
90
- for (const name of [ASK_USER, PLUGIN_PROPOSE, ...WIKI_TOOL_NAMES, ...(input.connections ? ['mcp_list_tools', 'mcp_call_tool'] : [])]) if (!names.includes(name)) names.push(name)
91
- for (const name of names) {
92
- if (extensionToolNames.has(name)) continue
93
- const plugin = descriptors.find((descriptor) => descriptor.tools?.some((tool) => tool.name === name))
94
- if (!plugin) unattributed.push({ kind: 'tool', id: name })
95
- item(plugin?.id ?? '', 'tool', name, 'tool', null, { contributionId: plugin ? `${plugin.id}/tool/${name}` : null })
96
- }
97
-
98
- if (input.connections) {
99
- for (const connection of input.saved.filter((candidate) => allowed(candidate, { agentId: context.agentId ?? null, projectId: context.projectId ?? null }))) {
100
- item('connected-apps', 'connection', connection.name || connection.id, 'tool', null, { contributionId: `connected-apps/connection/${connection.id}` })
101
- }
102
- }
103
-
104
- // What the harness found on disk and lets load. Pi's command's own extensions exist only in a terminal.
105
- const delivered: Record<Contribution['kind'], InventoryItem['delivery']> = { code: 'code', skill: 'on-demand', command: 'on-demand', instruction: 'system', theme: 'code', tool: 'tool', connection: 'tool' }
106
- const terminal = context.surface === 'cli'
107
- for (const plugin of input.plugins) {
108
- if (!['project', 'package', 'shared', 'home', 'pi'].includes(plugin.source)) continue
109
- for (const found of plugin.contributions) {
110
- if (found.state !== 'on' || (plugin.source === 'pi' && (found.kind !== 'code' || !terminal)) || (found.kind === 'theme' && !terminal)) continue
111
- item(plugin.id, found.kind, found.name, found.background ? 'background' : delivered[found.kind], ['instruction', 'skill', 'command'].includes(found.kind) ? size(found.path) : null, { contributionId: found.id })
112
- }
113
- }
114
- // The harness's own switched-on extensions.
115
- for (const plugin of input.plugins) {
116
- if (plugin.source !== 'builtin') continue
117
- for (const own of plugin.contributions) if (own.kind === 'code' && own.state === 'on') item(plugin.id, 'code', own.name, 'code', null, { contributionId: own.id })
118
- }
119
- item('pi', 'instruction', 'Base prompt', 'system', null)
120
-
121
- const used = new Set(items.map((entry) => entry.pluginId))
122
- return { plugins: input.plugins.filter((plugin) => used.has(plugin.id)), others: input.plugins.filter((plugin) => !used.has(plugin.id)), items, unattributed, systemChars, contextChars }
123
- }
@@ -1,76 +0,0 @@
1
- // What a package says about itself in its `package.json`: Pi's own fields, and under `harness`
2
- // which part of the harness it extends and the file of hooks the harness runs for it.
3
- import { basename, join } from 'node:path'
4
- import { z } from 'zod'
5
-
6
- import { readJsonOr, safeRelative } from '../core/fs'
7
- import type { ConnectorTemplate } from './types'
8
-
9
- export interface PackageManifest {
10
- name: string
11
- description: string
12
- version: string | null
13
- /** The parts it adds to, by id: `memory`, `wiki`, `history`. */
14
- extends: string[]
15
- /** The hooks file, inside the package, or `null` when it has none. */
16
- hooks: string | null
17
- /** Data-only remote connector forms. Invalid templates are ignored; none can carry credentials. */
18
- connectorTemplates: ConnectorTemplate[]
19
- }
20
-
21
- interface Raw {
22
- name?: unknown
23
- description?: unknown
24
- version?: unknown
25
- harness?: unknown
26
- }
27
-
28
- const connectorTemplateSchema = z.object({
29
- id: z.string().regex(/^[a-z0-9-]+$/),
30
- name: z.string().min(1).max(120),
31
- description: z.string().max(500),
32
- url: z.string().url().startsWith('https://'),
33
- auth: z.enum(['none', 'headers', 'oauth']),
34
- oauthClient: z.enum(['dynamic', 'user']).nullable(),
35
- oauthScopes: z.array(z.string().max(500)).max(30),
36
- docsUrl: z.string().url().startsWith('https://').nullable(),
37
- fields: z.array(z.object({
38
- header: z.string().regex(/^[A-Za-z0-9_-]+$/),
39
- label: z.string().min(1).max(120),
40
- prefix: z.string().max(100),
41
- help: z.string().max(500)
42
- }).strict()).max(12),
43
- setup: z.array(z.string().max(1000)).max(20),
44
- notice: z.string().max(1000).nullable()
45
- }).strict().superRefine((template, context) => {
46
- const oauth = template.auth === 'oauth'
47
- const headers = template.auth === 'headers'
48
- if (oauth !== (template.oauthClient !== null)) context.addIssue({ code: 'custom', message: 'OAuth templates must state a client type and other templates must not.', path: ['oauthClient'] })
49
- if (headers !== (template.fields.length > 0)) context.addIssue({ code: 'custom', message: 'Header templates must declare input fields and other templates must not.', path: ['fields'] })
50
- })
51
-
52
- /** A path inside the package, or `null` for one that is missing, absolute, or climbs out of it. */
53
- function inside(path: unknown): string | null {
54
- if (typeof path !== 'string' || !path.trim()) return null
55
- try {
56
- return safeRelative(path.replace(/^\.\//, ''))
57
- } catch {
58
- return null
59
- }
60
- }
61
-
62
- export function packageManifest(packageRoot: string): PackageManifest {
63
- const manifest = readJsonOr<Raw>(join(packageRoot, 'package.json'), {})
64
- const own = (manifest.harness && typeof manifest.harness === 'object' && !Array.isArray(manifest.harness) ? manifest.harness : {}) as { extends?: unknown; hooks?: unknown; connectors?: unknown }
65
- return {
66
- name: typeof manifest.name === 'string' && manifest.name ? manifest.name : basename(packageRoot),
67
- description: typeof manifest.description === 'string' ? manifest.description : '',
68
- version: typeof manifest.version === 'string' ? manifest.version : null,
69
- extends: (Array.isArray(own.extends) ? own.extends : typeof own.extends === 'string' ? [own.extends] : []).filter((id): id is string => typeof id === 'string' && !!id),
70
- hooks: inside(own.hooks),
71
- connectorTemplates: (Array.isArray(own.connectors) ? own.connectors : []).flatMap((value) => {
72
- const parsed = connectorTemplateSchema.safeParse(value)
73
- return parsed.success ? [parsed.data] : []
74
- })
75
- }
76
- }
@@ -1,205 +0,0 @@
1
- import { existsSync, mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
- import { describe, expect, it } from 'vitest'
5
-
6
- import { Bus } from '../core/bus'
7
- import type { Attachments } from './attachments'
8
- import { loadResources, type TurnParams } from '../sessions/runner'
9
- import { piResolver, type Found } from './discover'
10
- import { Plugins } from './plugins'
11
- import { projectCode } from './trust'
12
-
13
- const temp = (prefix: string): string => mkdtempSync(join(tmpdir(), prefix))
14
-
15
- function write(path: string, text: string): void {
16
- mkdirSync(join(path, '..'), { recursive: true })
17
- writeFileSync(path, text)
18
- }
19
-
20
- /** An extension that leaves a file behind when Pi loads it, and registers a command and a hook. */
21
- const extension = (marker: string, command: string): string =>
22
- `import { writeFileSync } from 'node:fs'\nwriteFileSync(${JSON.stringify(marker)}, 'ran')\nexport default function (pi) {\n pi.registerCommand('${command}', { description: 'A test command', handler: async () => {} })\n pi.on('tool_call', async () => undefined)\n}\n`
23
-
24
- function workspace() {
25
- const base = temp('harness-plugins-')
26
- const agentDir = join(base, 'agent')
27
- const cwd = join(base, 'project')
28
- const markers = { shared: join(base, 'ran-shared'), project: join(base, 'ran-project'), packaged: join(base, 'ran-packaged') }
29
- write(join(agentDir, 'extensions/shared.ts'), extension(markers.shared, 'shared'))
30
- write(join(agentDir, 'skills/alpha/SKILL.md'), '---\nname: alpha\ndescription: Alpha skill\n---\nAlpha.\n')
31
- write(join(agentDir, 'prompts/review.md'), 'Review this.\n')
32
- write(join(cwd, '.pi/extensions/project.ts'), extension(markers.project, 'project'))
33
- write(join(cwd, '.pi/skills/beta/SKILL.md'), '---\nname: beta\ndescription: Beta skill\n---\nBeta.\n')
34
- write(join(base, 'package/package.json'), JSON.stringify({ name: 'local-package', description: 'A local package', version: '0.1.0', keywords: ['pi-package'] }))
35
- write(join(base, 'package/extensions/packaged.ts'), extension(markers.packaged, 'packaged'))
36
- write(join(base, 'package/skills/gamma/SKILL.md'), '---\nname: gamma\ndescription: Gamma skill\n---\nGamma.\n')
37
- write(join(agentDir, 'settings.json'), JSON.stringify({ packages: [join(base, 'package')], extensions: ['-builtin:llama.cpp'] }))
38
- const stateDir = join(base, 'state')
39
- mkdirSync(stateDir)
40
- const notices: string[] = []
41
- const bus = new Bus()
42
- bus.on((notice) => void notices.push(notice.type))
43
- return { base, agentDir, cwd, markers, notices, plugins: new Plugins({ stateDir, bus }) }
44
- }
45
-
46
- const ran = (markers: Record<string, string>): Record<string, boolean> => Object.fromEntries(Object.entries(markers).map(([name, path]) => [name, existsSync(path)]))
47
-
48
- describe('what Pi would load', () => {
49
- it('is found without running any of it, with where each item comes from', async () => {
50
- const { agentDir, cwd, markers, base } = workspace()
51
- const found = await piResolver({ cwd, agentDir })
52
- const of = (kind: Found['kind']) => found.filter((item) => item.kind === kind).map((item) => [item.origin, item.path.replace(`${base}/`, ''), item.enabled])
53
- expect(of('extension')).toEqual([
54
- ['project', 'project/.pi/extensions/project.ts', true],
55
- ['shared', 'agent/extensions/shared.ts', true],
56
- ['package', 'package/extensions/packaged.ts', true],
57
- ['builtin', 'builtin:llama.cpp', false],
58
- ['builtin', 'builtin:codemode', true],
59
- ['builtin', 'builtin:tool-search', true],
60
- ['builtin', 'builtin:mcp', true]
61
- ])
62
- expect(of('skill')).toEqual([
63
- ['project', 'project/.pi/skills/beta/SKILL.md', true],
64
- ['shared', 'agent/skills/alpha/SKILL.md', true],
65
- ['package', 'package/skills/gamma/SKILL.md', true]
66
- ])
67
- expect(found.find((item) => item.origin === 'package')).toMatchObject({ packageRoot: join(base, 'package'), source: join(base, 'package'), project: false })
68
- expect(ran(markers)).toEqual({ shared: false, project: false, packaged: false })
69
- })
70
-
71
- it('names a package nobody installed, and installs nothing when only listing', async () => {
72
- const { agentDir, cwd } = workspace()
73
- writeFileSync(join(agentDir, 'settings.json'), JSON.stringify({ packages: ['npm:@no-such-scope/never-installed'] }))
74
- const found = await piResolver({ cwd, agentDir })
75
- expect(found.some((item) => item.origin === 'package')).toBe(false)
76
- expect(existsSync(join(agentDir, 'npm'))).toBe(false)
77
- })
78
- })
79
-
80
- describe('what a session loads', () => {
81
- it("leaves a working folder's code out until a person trusts it", async () => {
82
- const { agentDir, cwd, plugins, base, notices } = workspace()
83
- const before = await plugins.loading({ cwd, agentDir })
84
- const short = (paths: string[]) => paths.map((path) => path.replace(`${base}/`, ''))
85
- expect(short(before.extensionPaths)).toEqual(['agent/extensions/shared.ts', 'package/extensions/packaged.ts'])
86
- expect(short(before.skillPaths)).toEqual(['project/.pi/skills/beta/SKILL.md', 'agent/skills/alpha/SKILL.md', 'package/skills/gamma/SKILL.md'])
87
- expect(before.builtins).toEqual(['builtin:codemode', 'builtin:tool-search', 'builtin:mcp'])
88
- expect(before.projectCode).toMatchObject({ trusted: false, files: ['.pi/extensions/project.ts'] })
89
-
90
- plugins.trust.grant(before.projectCode!, cwd)
91
- expect(notices).toContain('plugins.changed')
92
- const trusted = await plugins.loading({ cwd, agentDir })
93
- expect(short(trusted.extensionPaths)).toEqual(['project/.pi/extensions/project.ts', 'agent/extensions/shared.ts', 'package/extensions/packaged.ts'])
94
-
95
- // A changed file is different code: it asks again.
96
- writeFileSync(join(cwd, '.pi/extensions/project.ts'), 'export default function () {}\n')
97
- const changed = await plugins.loading({ cwd, agentDir })
98
- expect(changed.projectCode?.trusted).toBe(false)
99
- expect(changed.projectCode?.hash).not.toBe(before.projectCode?.hash)
100
- expect(short(changed.extensionPaths)).toEqual(['agent/extensions/shared.ts', 'package/extensions/packaged.ts'])
101
-
102
- plugins.trust.revoke(before.projectCode!.hash)
103
- // What is left is the package that was there when trust was first asked per package.
104
- expect(plugins.trust.list().map((record) => record.folder)).toEqual([join(base, 'package')])
105
- })
106
-
107
- it('takes over the packages present once, then makes a new or changed package wait', async () => {
108
- const { agentDir, cwd, plugins, base } = workspace()
109
- const packaged = join(base, 'package/extensions/packaged.ts')
110
- const first = await plugins.loading({ cwd, agentDir })
111
- expect(first.packageCode[join(base, 'package')]).toMatchObject({ trusted: true, files: ['extensions/packaged.ts', 'package.json', 'skills/gamma/SKILL.md'] })
112
- expect(first.extensionPaths).toContain(packaged)
113
-
114
- // An update changes the code: it does not load until a person trusts it again.
115
- writeFileSync(packaged, 'export default function () {}\n')
116
- const changed = await plugins.loading({ cwd, agentDir })
117
- expect(changed.packageCode[join(base, 'package')].trusted).toBe(false)
118
- expect(changed.extensionPaths).not.toContain(packaged)
119
- // Its text still loads: a skill runs nothing by itself.
120
- expect(changed.skillPaths).toContain(join(base, 'package/skills/gamma/SKILL.md'))
121
- plugins.trust.grant(changed.packageCode[join(base, 'package')], join(base, 'package'))
122
- expect((await plugins.loading({ cwd, agentDir })).extensionPaths).toContain(packaged)
123
-
124
- // A package added after the first start was never taken over.
125
- write(join(base, 'second/package.json'), JSON.stringify({ name: 'second', version: '1.0.0' }))
126
- write(join(base, 'second/extensions/later.ts'), 'export default function () {}\n')
127
- write(join(agentDir, 'settings.json'), JSON.stringify({ packages: [join(base, 'package'), join(base, 'second')] }))
128
- const later = await plugins.loading({ cwd, agentDir })
129
- expect(later.packageCode[join(base, 'second')].trusted).toBe(false)
130
- expect(later.extensionPaths).not.toContain(join(base, 'second/extensions/later.ts'))
131
- })
132
-
133
- it('trusts the same code in another folder, and names files from the folder they are in', () => {
134
- const one = temp('harness-code-')
135
- const two = temp('harness-code-')
136
- for (const cwd of [one, two]) write(join(cwd, '.pi/extensions/tool/index.ts'), 'export default function () {}\n')
137
- const item = (cwd: string): Found => ({ kind: 'extension', path: join(cwd, '.pi/extensions/tool/index.ts'), origin: 'project', project: true, packageRoot: null, source: null, enabled: true })
138
- write(join(one, '.pi/extensions/tool/node_modules/dep/index.js'), 'ignored')
139
- expect(projectCode([item(one)], one)).toEqual(projectCode([item(two)], two))
140
- expect(projectCode([item(one)], one)?.files).toEqual(['.pi/extensions/tool/index.ts'])
141
- // A helper beside `index.ts` is part of the same extension.
142
- write(join(two, '.pi/extensions/tool/helper.ts'), 'export const x = 1\n')
143
- expect(projectCode([item(two)], two)?.hash).not.toBe(projectCode([item(one)], one)?.hash)
144
- expect(projectCode([{ ...item(one), project: false }], one)).toBeNull()
145
- })
146
-
147
- it('removes the skill links an earlier version kept in the shared folder', async () => {
148
- const { agentDir, cwd, plugins, base } = workspace()
149
- symlinkSync(join(agentDir, 'skills/alpha'), join(agentDir, 'skills/agentx-old'))
150
- const loading = await plugins.loading({ cwd, agentDir })
151
- expect(existsSync(join(agentDir, 'skills/agentx-old'))).toBe(false)
152
- expect(loading.skillPaths.filter((path) => path.startsWith(join(base, 'agent')))).toEqual([join(agentDir, 'skills/alpha/SKILL.md')])
153
- })
154
- })
155
-
156
- describe('a Pi session loader', () => {
157
- const params = (cwd: string, agentDir: string, plugins: Plugins, extra: Partial<TurnParams> = {}) =>
158
- ({
159
- cwd,
160
- account: { configDir: agentDir } as TurnParams['account'],
161
- system: '',
162
- plugins: { loading: () => plugins.loading({ cwd, agentDir }), loaded: (extensions) => plugins.loaded(extensions) },
163
- ...extra
164
- }) satisfies Parameters<typeof loadResources>[1]
165
-
166
- it('runs only what the harness chose, and records what each extension registered', async () => {
167
- const { agentDir, cwd, plugins, markers } = workspace()
168
- const pi = await import('@earendil-works/pi-coding-agent')
169
- const loader = await loadResources(pi, params(cwd, agentDir, plugins), () => undefined)
170
- expect(ran(markers)).toEqual({ shared: true, project: false, packaged: true })
171
- expect(loader.getSkills().skills.map((skill) => skill.name).sort()).toEqual(['alpha', 'beta', 'gamma'])
172
- expect(loader.getPrompts().prompts.map((prompt) => prompt.name)).toEqual(['review'])
173
- expect(Object.values(plugins.registered()).map((entry) => [entry.commands, entry.hooks])).toEqual([
174
- [['shared'], ['tool_call']],
175
- [['packaged'], ['tool_call']]
176
- ])
177
-
178
- const code = (await plugins.loading({ cwd, agentDir })).projectCode!
179
- plugins.trust.grant(code, cwd)
180
- await loadResources(pi, params(cwd, agentDir, plugins), () => undefined)
181
- expect(ran(markers).project).toBe(true)
182
- })
183
-
184
- it('does not run an extension a person switched off for the caller', async () => {
185
- const { agentDir, cwd, markers, base } = workspace()
186
- const choices: Attachments = { version: 1, global: { on: [], off: [] }, agents: { a1: { on: [], off: ['shared/code/shared.ts'] } }, projects: {}, settings: {} }
187
- const plugins = new Plugins({ stateDir: join(base, 'state'), bus: new Bus(), attachments: () => choices })
188
- const pi = await import('@earendil-works/pi-coding-agent')
189
- const forAgent = (agentId: string) => ({ ...params(cwd, agentDir, plugins), plugins: { loading: () => plugins.loading({ cwd, agentDir, caller: { agentId } }), loaded: () => undefined } })
190
- const loader = await loadResources(pi, forAgent('a1'), () => undefined)
191
- expect(ran(markers)).toEqual({ shared: false, project: false, packaged: true })
192
- // Its skills are a different contribution and still load.
193
- expect(loader.getSkills().skills.map((skill) => skill.name).sort()).toEqual(['alpha', 'beta', 'gamma'])
194
- await loadResources(pi, forAgent('a2'), () => undefined)
195
- expect(ran(markers).shared).toBe(true)
196
- })
197
-
198
- it('loads no extension at all for an unattended run', async () => {
199
- const { agentDir, cwd, plugins, markers } = workspace()
200
- const pi = await import('@earendil-works/pi-coding-agent')
201
- const settings = pi.SettingsManager.inMemory({})
202
- await loadResources(pi, params(cwd, agentDir, plugins, { automatic: true }), () => undefined, settings)
203
- expect(ran(markers)).toEqual({ shared: false, project: false, packaged: false })
204
- })
205
- })