@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
@@ -0,0 +1,767 @@
1
+ // A host owns the PTY and process supervision; Harness owns the terminal application inside it.
2
+ // This service prepares the isolated account, compiled context, trusted resource selection and
3
+ // socket bridge. The default launch runs our frontend with Pi's persistent SDK runtime.
4
+ import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
5
+ import { dirname, join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { Type } from 'typebox';
8
+ import { freezeRun } from "../capabilities/runSnapshot.js";
9
+ import { SPAWN_SUBAGENT, WAIT_SUBAGENTS } from "../sessions/subagents.js";
10
+ import { subagentTools } from "../tools/spawnSubagent.js";
11
+ import { configDir, launchEnv } from "../accounts/env.js";
12
+ import { readAudit } from "../accounts/store.js";
13
+ import { log } from "../core/bus.js";
14
+ import { HarnessError, invalid } from "../core/errors.js";
15
+ import { newId, now } from "../core/fs.js";
16
+ import { prependSearchPath, searchPath } from "../core/path.js";
17
+ import { dispatch } from "../tools/dispatch.js";
18
+ import { materialise } from "../variant/materialise.js";
19
+ import * as componentLibrary from "../variant/components.js";
20
+ import * as variantStore from "../variant/store.js";
21
+ import { compile, copyToRun, record, render, saveForSession } from "../prompt/compile.js";
22
+ import { isActiveStatus } from "../sessions/contracts.js";
23
+ import { findRun, loadRun, saveRun, updateRun } from "../sessions/runStore.js";
24
+ import { SESSION_NAME } from "../tools/sessionName.js";
25
+ import { contributionId } from "../plugins/identity.js";
26
+ import { APPS_COMMAND, WIKI_COMMAND } from "./cli.js";
27
+ import { SOCKET_ENV, TOKEN_ENV } from "./client.js";
28
+ import { TerminalController } from "./controller.js";
29
+ import { terminalCommandFiles } from "./launch.js";
30
+ import { SessionSocket, socketPath } from "./socket.js";
31
+ import { harnessLogInfo, readHarnessLogChunk } from "./logs.js";
32
+ import { listTerminalTrajectoryRuns, readTerminalTrajectory } from "./trajectory.js";
33
+ /** Identity of the exact resource decision that this terminal was prepared with. */
34
+ function resourceIdentity(loading) {
35
+ if (!loading)
36
+ return 'null';
37
+ return JSON.stringify({
38
+ extensions: loading.extensionPaths, builtins: loading.builtins, skills: loading.skillPaths,
39
+ prompts: loading.promptPaths, themes: loading.themePaths, detached: loading.detached,
40
+ project: loading.projectCode, packages: loading.packageCode
41
+ });
42
+ }
43
+ /** Where the package's own build puts them. An application that bundles the harness passes its own. */
44
+ export function defaultAssets() {
45
+ const here = dirname(fileURLToPath(import.meta.url));
46
+ const dist = [here, join(here, '..', '..'), join(here, '..', '..', 'dist'), join(here, '..', 'dist')].find((folder) => existsSync(join(folder, 'terminal-pi.js'))) ?? here;
47
+ return {
48
+ node: process.execPath,
49
+ cli: join(dist, 'cli.js'),
50
+ piExtension: join(dist, 'terminal-pi.js'),
51
+ openTui: join(dist, 'terminal-opentui.js')
52
+ };
53
+ }
54
+ const READ_ONLY_TOOLS = new Set(['read', 'grep', 'find', 'ls']);
55
+ export class Terminals {
56
+ options;
57
+ sessions = new Map();
58
+ diagnosticOwners = new Map();
59
+ /** The variant each live session runs, for loading its skills. */
60
+ variantDirs = new Map();
61
+ /** The world tools each session was given, so a call can only reach one of them. */
62
+ worldNames = new Map();
63
+ worldReadOnly = new Set();
64
+ socket;
65
+ assets;
66
+ /** A session's `/accounts` switch, taken once its Pi process has ended. */
67
+ relaunches = new Map();
68
+ constructor(options) {
69
+ this.options = options;
70
+ this.assets = options.assets ?? defaultAssets();
71
+ options.runs.listen(event => {
72
+ this.sessions.get(event.sessionId)?.controller.observe(event);
73
+ const record = findRun(options.env.root, event.runId);
74
+ if (record?.relation !== 'subagent')
75
+ return;
76
+ let parentId = record.parentRunId;
77
+ const seen = new Set();
78
+ while (parentId && !seen.has(parentId)) {
79
+ seen.add(parentId);
80
+ const parent = findRun(options.env.root, parentId);
81
+ if (!parent)
82
+ break;
83
+ const owner = this.sessions.get(parent.sessionId);
84
+ if (owner?.controller.activeRun?.runId === parent.id) {
85
+ owner.controller.observe(event, true);
86
+ break;
87
+ }
88
+ parentId = parent.parentRunId;
89
+ }
90
+ });
91
+ this.socket = new SessionSocket(socketPath(options.stateDir), {
92
+ memory: (caller, call, params) => dispatch(options.env, caller, call, params, { variantDir: (caller.sessionId && this.variantDirs.get(caller.sessionId)) || null }),
93
+ apps: (session, call, params) => this.appsCall(session, call, params),
94
+ plugins: (grant, call, params, control) => this.pluginsCall(grant.sessionId, call, params, control),
95
+ accounts: (grant, call, params, control) => this.accountsCall(grant.sessionId, call, params, control)
96
+ });
97
+ }
98
+ /** The commands a terminal session finds on PATH. Rewritten only when they change. */
99
+ ensureCommands() {
100
+ const bin = join(this.options.stateDir, 'run', 'bin');
101
+ mkdirSync(bin, { recursive: true });
102
+ for (const name of ['agentx-wiki', 'agentx-mcp', 'agentx-wiki.cmd', 'agentx-mcp.cmd']) {
103
+ const path = join(bin, name);
104
+ try {
105
+ if (lstatSync(path).isFile())
106
+ unlinkSync(path);
107
+ }
108
+ catch {
109
+ // These names belonged to the previous generated wrappers.
110
+ }
111
+ }
112
+ for (const [name, mode] of [[WIKI_COMMAND, 'wiki'], [APPS_COMMAND, 'mcp']]) {
113
+ for (const file of terminalCommandFiles(process.platform, this.assets.node, this.assets.cli, name, mode)) {
114
+ const path = join(bin, file.name);
115
+ let current = null;
116
+ try {
117
+ current = readFileSync(path, 'utf8');
118
+ }
119
+ catch {
120
+ current = null;
121
+ }
122
+ if (current !== file.content) {
123
+ writeFileSync(path, file.content);
124
+ chmodSync(path, 0o755);
125
+ }
126
+ }
127
+ }
128
+ return bin;
129
+ }
130
+ /** The broker's tools, then the world tools whose plugins are on for this session. */
131
+ async tools(session, listing) {
132
+ const brokered = this.options.apps.brokerTools(session);
133
+ const live = this.sessions.get(session.sessionId);
134
+ const { world } = this.options;
135
+ if (!world || !live)
136
+ return brokered;
137
+ const context = { run: live.controller.activeRun, caller: live.caller, attended: true, subagent: false, sessionKey: session.sessionId, cwd: live.input.cwd };
138
+ if (!listing)
139
+ return [...brokered, ...world.tools(context, (_plugin, tool) => this.worldNames.get(session.sessionId)?.has(tool) ?? false)];
140
+ const on = await this.worldOn(live);
141
+ const tools = world.tools(context, (plugin, tool) => on(plugin, tool));
142
+ this.worldNames.set(session.sessionId, new Set(tools.map((tool) => tool.name)));
143
+ for (const tool of tools)
144
+ if (tool.readOnly)
145
+ this.worldReadOnly.add(tool.name);
146
+ return [...brokered, ...tools];
147
+ }
148
+ /** The world tools a new session will have, named in its instructions. */
149
+ async worldToolNames(input, account) {
150
+ const { world } = this.options;
151
+ if (!world || input.connections === false)
152
+ return [];
153
+ const list = this.options.pluginControl?.list;
154
+ const plugins = list ? await list({ cwd: input.cwd, accountId: account.id, projectId: input.projectId ?? null }) : null;
155
+ const on = plugins ? new Set(plugins.flatMap((plugin) => plugin.contributions.filter((item) => item.state === 'on').map((item) => item.id))) : null;
156
+ return world.plugins.flatMap((plugin) => (plugin.tools ?? []).map((tool) => tool.name).filter((name) => !on || on.has(contributionId(plugin.id, 'tool', name))));
157
+ }
158
+ /** Whether a world tool's plugin is switched on for a session's folder, account and project. */
159
+ async worldOn(live) {
160
+ const list = this.options.pluginControl?.list;
161
+ if (!list)
162
+ return () => true;
163
+ const plugins = await list({ cwd: live.input.cwd, accountId: live.account.id, projectId: live.input.projectId ?? null });
164
+ const on = new Set(plugins.flatMap((plugin) => plugin.contributions.filter((item) => item.state === 'on').map((item) => item.id)));
165
+ return (plugin, tool) => on.has(contributionId(plugin, 'tool', tool));
166
+ }
167
+ async appsCall(session, call, params) {
168
+ const { apps } = this.options;
169
+ switch (call) {
170
+ case 'mcp.list':
171
+ return apps.list(session);
172
+ case 'mcp.call':
173
+ return apps.invoke(session, String(params.name ?? ''), (params.args && typeof params.args === 'object' ? params.args : {}));
174
+ case 'mcp.revision':
175
+ return apps.revision(session);
176
+ case 'tools.list': {
177
+ const { Type } = await import('typebox');
178
+ return { tools: (await this.tools(session, true)).map((tool) => ({ name: tool.name, label: tool.label, description: tool.description, parameters: tool.parameters(Type) })) };
179
+ }
180
+ case 'tools.call': {
181
+ const tool = (await this.tools(session, false)).find((candidate) => candidate.name === params.name);
182
+ if (!tool)
183
+ throw new HarnessError('unknown_method', `Unknown tool ${String(params.name)}.`);
184
+ const result = await tool.execute((params.input && typeof params.input === 'object' ? params.input : {}));
185
+ if (typeof result === 'string')
186
+ return { text: result };
187
+ const images = [...(result.image ? [result.image] : []), ...(result.images ?? [])];
188
+ return { text: result.text, ...(images.length ? { images } : {}), ...(result.details ? { details: result.details } : {}) };
189
+ }
190
+ default:
191
+ throw new HarnessError('unknown_method', `Unknown call ${call}.`);
192
+ }
193
+ }
194
+ /**
195
+ * `/plugins` in a terminal. Listing is open to the session. A change is taken only from the
196
+ * session's own extension, which asks the person in the terminal first: the model can reach
197
+ * this socket from a shell command, and must not be able to trust code or switch it on.
198
+ */
199
+ async pluginsCall(sessionId, call, params, control) {
200
+ const api = this.options.pluginControl;
201
+ const live = this.sessions.get(sessionId);
202
+ if (!api || !live)
203
+ throw new HarnessError('unknown_method', `Unknown call ${call}.`);
204
+ const projectId = live.input.projectId ?? null;
205
+ const scope = { cwd: live.input.cwd, accountId: live.account.id, projectId };
206
+ if (call === 'hub.list' && this.options.hub)
207
+ return this.options.hub.list(params.refresh === true);
208
+ if (call === 'hub.install' && this.options.hub) {
209
+ if (!control)
210
+ throw new HarnessError('unauthorized', 'Only a person at this terminal can install items. Type /hub.');
211
+ if (typeof params.id !== 'string' || typeof params.version !== 'string')
212
+ throw invalid('An item id and version are required.');
213
+ return this.options.hub.install(params.id, params.version);
214
+ }
215
+ if (call === 'plugins.list')
216
+ return api.list(scope);
217
+ if (call === 'plugins.session')
218
+ return { projectId };
219
+ if (!control)
220
+ throw new HarnessError('unauthorized', 'Only a person at this terminal can change plugins. Type /plugins.');
221
+ const text = (name) => {
222
+ if (typeof params[name] !== 'string' || !params[name])
223
+ throw invalid(`${name} is required.`);
224
+ return params[name];
225
+ };
226
+ switch (call) {
227
+ case 'plugins.attach':
228
+ case 'plugins.detach':
229
+ return api.attach({ ...scope, id: text('id'), scope: params.everywhere === true || !projectId ? {} : { projectId } }, call === 'plugins.attach');
230
+ case 'plugins.trust':
231
+ return api.trust({ ...scope, hash: text('hash') });
232
+ case 'plugins.untrust':
233
+ return api.untrust({ ...scope, hash: text('hash') });
234
+ case 'plugins.configure': {
235
+ const settings = params.settings && typeof params.settings === 'object' && !Array.isArray(params.settings) ? params.settings : {};
236
+ return api.configure({ ...scope, pluginId: text('pluginId'), settings });
237
+ }
238
+ default:
239
+ throw new HarnessError('unknown_method', `Unknown call ${call}.`);
240
+ }
241
+ }
242
+ /**
243
+ * `/accounts` in a terminal. Every call needs the session's control key: adding, signing in,
244
+ * or removing an account is a person's choice, never the model's shell command.
245
+ */
246
+ async accountsCall(sessionId, call, params, control) {
247
+ const { accounts } = this.options;
248
+ const live = this.sessions.get(sessionId);
249
+ if (!live)
250
+ throw new HarnessError('unknown_method', `Unknown call ${call}.`);
251
+ if (!control)
252
+ throw new HarnessError('unauthorized', 'Only a person at this terminal can manage accounts. Type /accounts.');
253
+ const text = (name) => {
254
+ if (typeof params[name] !== 'string' || !params[name])
255
+ throw invalid(`${name} is required.`);
256
+ return params[name];
257
+ };
258
+ const optional = (name) => (typeof params[name] === 'string' ? params[name] : null);
259
+ switch (call) {
260
+ case 'accounts.deviceId':
261
+ return accounts.installationDeviceId();
262
+ case 'accounts.list':
263
+ return accounts.overview();
264
+ case 'accounts.session':
265
+ return { accountId: live.account.id, label: live.account.label };
266
+ case 'accounts.create':
267
+ return accounts.create(text('label'), optional('authKind') ?? 'subscription');
268
+ case 'accounts.rename':
269
+ return accounts.rename(text('accountId'), text('label'));
270
+ case 'accounts.setDefault':
271
+ return accounts.setDefault(text('accountId'));
272
+ case 'accounts.remove': {
273
+ const accountId = text('accountId');
274
+ // Every terminal in this process counts, this session's own included. Another process's terminals are not visible here.
275
+ if (accounts.terminalCount(accountId) > 0)
276
+ throw new HarnessError('account_in_use', 'A running terminal is using this account, this one included.', 'Switch this session to another account first, then remove it.');
277
+ return accounts.remove(accountId);
278
+ }
279
+ case 'accounts.refresh':
280
+ return accounts.refresh(optional('accountId'));
281
+ case 'accounts.providers':
282
+ return accounts.providers();
283
+ // A terminal reads and writes only its own account's choices, never the id a caller names.
284
+ case 'accounts.choices.get':
285
+ return accounts.choices(live.account.id);
286
+ case 'accounts.choices.set':
287
+ return accounts.choose(live.account.id, text('mode'), {
288
+ ...(typeof params.model === 'string' ? { model: params.model } : {}),
289
+ ...(typeof params.effort === 'string' ? { effort: params.effort } : {})
290
+ });
291
+ case 'accounts.loginStart':
292
+ return accounts.loginStart(text('accountId'), text('provider'), optional('method'));
293
+ case 'accounts.loginStatus':
294
+ return accounts.loginStatus(text('accountId'));
295
+ case 'accounts.loginRespond':
296
+ accounts.loginRespond(text('loginId'), text('promptId'), optional('value'));
297
+ return {};
298
+ case 'accounts.loginCancel':
299
+ accounts.loginCancel(text('accountId'), optional('loginId'));
300
+ return {};
301
+ case 'accounts.setApiKey':
302
+ return accounts.setApiKey(text('accountId'), text('key'), text('provider'));
303
+ case 'accounts.removeProvider':
304
+ return accounts.removeProvider(text('accountId'), text('provider'));
305
+ case 'accounts.signOut':
306
+ return accounts.signOut(text('accountId'));
307
+ case 'accounts.savePool': {
308
+ const pool = params.pool;
309
+ if (!pool || typeof pool.label !== 'string' || !Array.isArray(pool.accountIds) || !pool.accountIds.every((id) => typeof id === 'string'))
310
+ throw invalid('A pool needs a label and its account ids.');
311
+ return accounts.savePool({ id: typeof pool.id === 'string' ? pool.id : undefined, label: pool.label, accountIds: pool.accountIds });
312
+ }
313
+ case 'accounts.removePool':
314
+ return accounts.removePool(text('poolId'));
315
+ case 'accounts.audit':
316
+ return readAudit(accounts.dir, optional('accountId'), typeof params.limit === 'number' ? params.limit : 100);
317
+ case 'accounts.relaunch': {
318
+ // Checked here so a bad choice is refused before the session is asked to end.
319
+ const target = accounts.resolve(text('accountId'));
320
+ this.relaunches.set(sessionId, { accountId: target.id, nativeSessionId: live.controller.nativeSessionId });
321
+ return { accountId: target.id, label: target.label };
322
+ }
323
+ default:
324
+ throw new HarnessError('unknown_method', `Unknown call ${call}.`);
325
+ }
326
+ }
327
+ /** The account a session asked to switch to. Taken once, after its Pi process has ended and before `dispose`. */
328
+ takeRelaunch(sessionId) {
329
+ const request = this.relaunches.get(sessionId) ?? null;
330
+ this.relaunches.delete(sessionId);
331
+ return request;
332
+ }
333
+ live(sessionId) {
334
+ const live = this.sessions.get(sessionId);
335
+ if (!live)
336
+ throw new HarnessError('terminal_not_ready', 'The terminal controller is unavailable. Reopen this session.');
337
+ return live;
338
+ }
339
+ historyDir(input) {
340
+ return join(input.sessionFolder, 'pi');
341
+ }
342
+ runRecord(live, runId, text) {
343
+ const { input } = live;
344
+ return {
345
+ resumedFromRunId: null,
346
+ parentRunId: null,
347
+ relation: null,
348
+ terminalReason: null,
349
+ agentId: null,
350
+ trigger: null,
351
+ id: runId,
352
+ projectId: input.projectId ?? null,
353
+ mode: input.run?.mode ?? 'code',
354
+ harness: 'pi',
355
+ sessionType: 'terminal',
356
+ sessionId: input.sessionId,
357
+ nativeSessionId: live.controller.nativeSessionId,
358
+ workingDirectory: input.cwd,
359
+ worktreeId: input.run?.worktreeId ?? null,
360
+ goal: text,
361
+ attachmentCount: 0,
362
+ startedAt: now(),
363
+ endedAt: null,
364
+ status: 'queued',
365
+ exitCode: null,
366
+ handoffId: null,
367
+ accountId: live.account.id
368
+ };
369
+ }
370
+ /** The run a native turn reports into: the one reserved by `send`, or a new one for what the person typed. */
371
+ begin(live, reservedRunId, text) {
372
+ const { root } = this.options.env;
373
+ const { sessionId } = live.input;
374
+ if (this.options.runs.activeForSession(sessionId))
375
+ throw new HarnessError('session_busy', 'A native turn already owns this session.');
376
+ let runId = reservedRunId;
377
+ if (runId) {
378
+ const reserved = loadRun(root, runId);
379
+ if (reserved.sessionId !== sessionId || reserved.status !== 'queued')
380
+ throw invalid('Delivery does not own this queued run.');
381
+ }
382
+ else {
383
+ runId = newId();
384
+ saveRun(root, this.runRecord(live, runId, text || null));
385
+ copyToRun(root, live.input.sessionFolder, runId);
386
+ }
387
+ return this.options.runs.start(sessionId, runId);
388
+ }
389
+ async decide(live, run, tool, args) {
390
+ const record = loadRun(this.options.env.root, run.runId);
391
+ if (!isActiveStatus(record.status))
392
+ throw invalid(`The run is no longer active (its status is ${record.status}).`);
393
+ const call = { run: record, caller: { ...live.caller, runId: run.runId }, tool, args };
394
+ const { policy } = this.options;
395
+ if (policy.scope) {
396
+ const scope = await policy.scope(call);
397
+ if (!scope.allowed && (scope.automatic || !scope.requiresApproval))
398
+ return { allowed: false, reason: scope.reason ?? 'Outside what this session may do.' };
399
+ try {
400
+ await policy.authorize?.(call);
401
+ }
402
+ catch (error) {
403
+ return { allowed: false, reason: error instanceof Error ? error.message : 'Tool unavailable in the settings.' };
404
+ }
405
+ const requiresApproval = !!scope.requiresApproval || (scope.allowed && !!scope.humanOnly);
406
+ return {
407
+ allowed: scope.allowed,
408
+ requiresApproval,
409
+ reason: scope.reason ?? null,
410
+ rememberable: scope.allowed && !scope.humanOnly,
411
+ ...(scope.humanOnly ? { standing: scope.allowGlobalApproval ? 'switch' : 'none' } : {})
412
+ };
413
+ }
414
+ // With no application policy: reads run, a read-only session refuses the rest, and anything else asks.
415
+ const name = tool.toLowerCase();
416
+ if (name === SESSION_NAME || name === SPAWN_SUBAGENT || name === WAIT_SUBAGENTS || READ_ONLY_TOOLS.has(name) || this.worldReadOnly.has(name) || this.options.apps.toolNames.includes(name))
417
+ return { allowed: true };
418
+ if (live.input.readOnly)
419
+ return { allowed: false, reason: 'This session is read-only.' };
420
+ return { allowed: false, requiresApproval: true, rememberable: true, reason: 'This native action requires approval.' };
421
+ }
422
+ async subagentsCall(live, call, params) {
423
+ const service = this.options.subagents;
424
+ if (!service || live.input.subagents === null) {
425
+ if (call === 'terminal.subagents.tools')
426
+ return { tools: [] };
427
+ throw invalid('Subagents are disabled for this terminal.');
428
+ }
429
+ if (call === 'terminal.subagents.tools')
430
+ return { tools: subagentTools(service, '').map(tool => ({ name: tool.name, label: tool.label, description: tool.description, parameters: tool.parameters(Type) })) };
431
+ const run = live.controller.activeRun;
432
+ if (!run)
433
+ throw new HarnessError('run_not_active', 'This terminal has no active parent run.');
434
+ if (call === 'terminal.subagents.register') {
435
+ if (!Array.isArray(params.tools) || params.tools.some((name) => typeof name !== 'string'))
436
+ throw invalid('Native tool names are required.');
437
+ const readOnly = live.input.readOnly === true;
438
+ const readTools = new Set([...READ_ONLY_TOOLS, SESSION_NAME, SPAWN_SUBAGENT, WAIT_SUBAGENTS, 'ask_user', 'mcp_list_tools', 'mcp_call_tool', 'history_search', 'history_read', 'wiki_search', 'wiki_read', 'wiki_list', 'memory_facts', 'skill_load']);
439
+ const tools = params.tools.filter((name) => !readOnly || readTools.has(name));
440
+ const capabilities = this.options.resolveCapabilities ? await this.options.resolveCapabilities(live.caller, tools, live.input.cwd) : { version: 1, tools, connectors: [], contributions: [] };
441
+ freezeRun(this.options.env.root, run.runId, live.caller, capabilities);
442
+ service.register({
443
+ run: { id: run.runId, sessionId: live.input.sessionId, mode: live.input.run?.mode ?? 'code', projectId: live.input.projectId, worktreeId: live.input.run?.worktreeId },
444
+ cwd: live.input.cwd, sessionDir: this.historyDir(live.input), text: '', caller: live.caller,
445
+ model: typeof params.model === 'string' ? params.model : live.input.model,
446
+ effort: typeof params.effort === 'string' ? params.effort : null,
447
+ launch: live.input.launch, tools: { allow: capabilities.tools, gated: capabilities.tools.filter(name => !readTools.has(name)) },
448
+ connections: live.input.connections === false ? false : { readOnly }, subagents: live.input.subagents,
449
+ capabilities
450
+ }, live.account.id, capabilities);
451
+ service.restore(run.runId, params.history ?? { owners: [], receipts: [] });
452
+ return { runId: run.runId };
453
+ }
454
+ if (call === 'terminal.subagents.verify') {
455
+ await service.verify(run.runId, params.history);
456
+ return {};
457
+ }
458
+ if (call === 'terminal.subagents.delivery')
459
+ return service.delivery(run.runId, params.history, params.settle === true);
460
+ if (call === 'terminal.subagents.call') {
461
+ const tool = subagentTools(service, run.runId).find(tool => tool.name === params.name);
462
+ if (!tool)
463
+ throw invalid('Unknown subagent tool.');
464
+ const reason = await this.decide(live, run, tool.name, params.input ?? {});
465
+ if (!reason.allowed)
466
+ throw new HarnessError('tool_denied', reason.reason ?? 'Subagents are unavailable.');
467
+ const result = await tool.execute(params.input ?? {});
468
+ return typeof result === 'string' ? { text: result } : result;
469
+ }
470
+ throw invalid('Unknown subagent operation.');
471
+ }
472
+ componentsCall(live, call, params) {
473
+ const root = this.options.env.root;
474
+ const choice = live.input.variant;
475
+ const scope = choice && 'scope' in choice ? choice.scope ?? null : null;
476
+ const head = scope ? variantStore.headVariant(root, scope) : null;
477
+ const items = componentLibrary.list(root);
478
+ if (call === 'terminal.components.list') {
479
+ return {
480
+ items,
481
+ addedIds: head ? items.filter(item => componentLibrary.isInVariant(root, head.variant, item.id)).map(item => item.id) : [],
482
+ writable: Boolean(scope && head),
483
+ fingerprint: head?.fingerprint ?? null
484
+ };
485
+ }
486
+ if (call === 'terminal.components.add') {
487
+ if (typeof params.id !== 'string' || !params.id)
488
+ throw invalid('A component id is required.');
489
+ if (!scope || !head)
490
+ throw invalid('This terminal has no writable Harness scope.');
491
+ const item = items.find(candidate => candidate.id === params.id);
492
+ if (!item)
493
+ throw invalid('That component is no longer in the library.');
494
+ if (item.kind === 'prompts')
495
+ throw invalid('Prompts stay in the library and cannot be added to a Variant.');
496
+ if (componentLibrary.isInVariant(root, head.variant, item.id)) {
497
+ return { fingerprint: head.fingerprint, alreadyPresent: true };
498
+ }
499
+ const variant = componentLibrary.addToVariant(root, head.variant, item.id);
500
+ const record = variantStore.commit(root, scope, variant, {
501
+ kind: 'edit', note: 'Added library component ' + item.id, components: [item.id]
502
+ });
503
+ this.options.bus.emit({ type: 'variants.changed', scope });
504
+ return { fingerprint: record.fingerprint, alreadyPresent: false };
505
+ }
506
+ throw new HarnessError('unknown_method', 'Unknown terminal component operation.');
507
+ }
508
+ trajectoryCall(live, call, params) {
509
+ if (call === 'terminal.trajectory.list') {
510
+ return { runs: listTerminalTrajectoryRuns(this.options.env.root, live.input.sessionId, live.controller.nativeSessionId) };
511
+ }
512
+ if (call === 'terminal.trajectory.events') {
513
+ if (typeof params.runId !== 'string' || !params.runId)
514
+ throw invalid('A run id is required.');
515
+ const afterSequence = params.afterSequence;
516
+ if (afterSequence !== undefined && typeof afterSequence !== 'number')
517
+ throw invalid('The event sequence must be a number.');
518
+ return readTerminalTrajectory(this.options.env.root, live.input.sessionId, live.controller.nativeSessionId, params.runId, afterSequence);
519
+ }
520
+ throw new HarnessError('unknown_method', `Unknown call ${call}.`);
521
+ }
522
+ /** The only terminal frontend: the Bun-run OpenTUI application. */
523
+ frontendCommand() {
524
+ return {
525
+ program: process.env.XINGULAR_HARNESS_BUN || 'bun',
526
+ // Solid must resolve to its client build for OpenTUI's effects, wherever it is imported.
527
+ argsPrefix: ['--conditions=browser', this.assets.openTui]
528
+ };
529
+ }
530
+ /**
531
+ * Prepares an OpenTUI terminal session and returns what to spawn. The caller must report the
532
+ * process's end with `dispose`, also when it never starts.
533
+ */
534
+ async prepare(input) {
535
+ input = structuredClone(input);
536
+ const { env, accounts, apps, bus } = this.options;
537
+ const { root } = env;
538
+ if (!input?.sessionId || !input.cwd || !input.sessionFolder)
539
+ throw invalid('A terminal session needs an id, a working folder, and its own folder.');
540
+ await this.dispose(input.sessionId);
541
+ const command = this.frontendCommand();
542
+ // A pinned account is used as it is; it is never exchanged for another one.
543
+ const account = input.accountId ? accounts.find(input.accountId) : accounts.resolve(null, null);
544
+ const launch = launchEnv(accounts.dir, account);
545
+ const loading = (await this.options.plugins?.loading({ cwd: input.cwd, agentDir: configDir(accounts.dir, account), install: true, caller: { projectId: input.projectId ?? null } })) ?? null;
546
+ await this.socket.listen();
547
+ await accounts.terminalBegin(account);
548
+ const sessionId = input.sessionId;
549
+ const caller = { sessionId, projectId: input.projectId ?? null, actor: 'Code', surface: 'cli' };
550
+ let token = null;
551
+ try {
552
+ const broker = input.connections === false ? null : apps.grant({ sessionId, runId: null, caller, readOnly: !!input.readOnly, depth: 0 });
553
+ // The session keeps these instructions; each of its runs records a copy, and a memory
554
+ // block that changes later is sent along as a note.
555
+ const variant = input.variant ? materialise(root, input.variant, { trust: this.options.trust ?? null }) : null;
556
+ if (variant)
557
+ this.variantDirs.set(sessionId, variant.dir);
558
+ const worldTools = await this.worldToolNames(input, account);
559
+ const launchTools = [...new Set([...(input.launch?.tools ?? []), SESSION_NAME, ...worldTools])];
560
+ const pack = compile(env, caller, { ...input.launch, tools: launchTools }, variant);
561
+ record(root, pack);
562
+ mkdirSync(this.historyDir(input), { recursive: true });
563
+ saveForSession(input.sessionFolder, pack);
564
+ const live = {
565
+ input,
566
+ account,
567
+ broker,
568
+ caller,
569
+ token: '',
570
+ controller: new TerminalController({
571
+ sessionId,
572
+ nativeSessionId: input.nativeSessionId ?? null,
573
+ begin: ({ reservedRunId, text }) => this.begin(live, reservedRunId, text),
574
+ policy: (run, tool, args) => this.decide(live, run, tool, args),
575
+ allowToolGlobally: target => { this.options.approvals.allowTool('pi', target); },
576
+ native: (nativeSessionId) => bus.emit({ type: 'terminal.native', sessionId, nativeSessionId }),
577
+ telemetry: (event) => bus.emit({ type: 'terminal.telemetry', sessionId, event }),
578
+ interrupt: runId => this.options.runs.interrupt(runId),
579
+ resolveApproval: (runId, id, decision) => this.options.runs.resolveApproval(runId, id, decision),
580
+ answerQuestion: (runId, id, answer) => this.options.runs.answerQuestion(runId, id, answer),
581
+ answerQuestions: (runId, batchId, answers) => this.options.runs.answerQuestions(runId, batchId, answers)
582
+ })
583
+ };
584
+ token = this.socket.issue({
585
+ sessionId,
586
+ caller: () => ({ ...caller, runId: live.controller.activeRun?.runId ?? null }),
587
+ broker,
588
+ terminal: { accept: (event, data) => live.controller.accept(event, data), disconnected: () => live.controller.disconnected(), control: async (call, params) => {
589
+ if (call.startsWith('terminal.doctor.')) {
590
+ const doctor = this.options.doctor;
591
+ if (!doctor)
592
+ throw invalid('Diagnostics are unavailable in this host.');
593
+ if (call === 'terminal.doctor.start') {
594
+ const model = typeof params.model === 'string' ? params.model : live.input.model ?? null;
595
+ const tools = [...new Set([
596
+ ...(Array.isArray(params.tools) ? params.tools.filter((name) => typeof name === 'string') : []),
597
+ ...await this.worldToolNames(live.input, live.account)
598
+ ])];
599
+ const variantDir = this.variantDirs.get(sessionId);
600
+ const report = doctor.start({
601
+ context: { caller: live.caller, cwd: live.input.cwd, accountId: live.account.id, model, tools,
602
+ variant: variantDir ? { dir: variantDir, scope: live.input.variant?.scope } : null },
603
+ mode: params.mode === 'live' ? 'live' : 'local',
604
+ checks: Array.isArray(params.checks) ? params.checks.filter((id) => typeof id === 'string') : [],
605
+ confirmed: params.confirmed === true
606
+ });
607
+ this.diagnosticOwners.set(report.id, sessionId);
608
+ return report;
609
+ }
610
+ const id = typeof params.id === 'string' ? params.id : '';
611
+ if (this.diagnosticOwners.get(id) !== sessionId)
612
+ throw invalid('This diagnostic job belongs to another terminal.');
613
+ if (call === 'terminal.doctor.read')
614
+ return doctor.read(id);
615
+ if (call === 'terminal.doctor.cancel')
616
+ return doctor.cancel(id);
617
+ throw invalid('Unknown diagnostic operation.');
618
+ }
619
+ if (call.startsWith('terminal.subagents.'))
620
+ return this.subagentsCall(live, call, params);
621
+ if (call === 'terminal.logs.info')
622
+ return harnessLogInfo(this.options.stateDir);
623
+ if (call === 'terminal.logs.read') {
624
+ const { snapshotSize, offset } = params;
625
+ if (typeof snapshotSize !== 'number' || !Number.isSafeInteger(snapshotSize) || snapshotSize < 0 || typeof offset !== 'number' || !Number.isSafeInteger(offset) || offset < 0 || offset >= snapshotSize) {
626
+ throw invalid('A valid diagnostics snapshot size and byte offset are required.');
627
+ }
628
+ const current = harnessLogInfo(this.options.stateDir).size;
629
+ if (current === null || snapshotSize > current)
630
+ throw invalid('The diagnostics snapshot is no longer available.');
631
+ return readHarnessLogChunk(this.options.stateDir, snapshotSize, offset);
632
+ }
633
+ if (call.startsWith('terminal.components.'))
634
+ return this.componentsCall(live, call, params);
635
+ if (call.startsWith('terminal.trajectory.'))
636
+ return this.trajectoryCall(live, call, params);
637
+ if (call === 'terminal.permissions.get') {
638
+ const policy = this.options.approvals.read();
639
+ return { full: this.options.approvals.isAuto('pi'), globalTools: policy.globalTools.pi ?? [] };
640
+ }
641
+ if (call === 'terminal.permissions.setFull') {
642
+ if (typeof params.enabled !== 'boolean')
643
+ throw invalid('A boolean permission state is required.');
644
+ return { full: this.options.approvals.setAuto('pi', params.enabled).auto.pi === true };
645
+ }
646
+ if (call === 'terminal.permissions.setTool') {
647
+ if (typeof params.tool !== 'string' || !params.tool.trim() || typeof params.allowed !== 'boolean')
648
+ throw invalid('A tool name and boolean permission state are required.');
649
+ const policy = params.allowed
650
+ ? this.options.approvals.allowTool('pi', params.tool)
651
+ : this.options.approvals.revokeTool('pi', params.tool);
652
+ return { globalTools: policy.globalTools.pi ?? [] };
653
+ }
654
+ if (call !== 'terminal.resources')
655
+ return live.controller.control(call, params);
656
+ const current = await this.options.plugins?.loading({ cwd: input.cwd, agentDir: configDir(accounts.dir, account), install: false, caller: { projectId: input.projectId ?? null } }) ?? null;
657
+ if (resourceIdentity(current) !== resourceIdentity(loading))
658
+ throw new HarnessError('terminal_resources_changed', 'Trusted resources changed since this terminal was prepared. Review /plugins and reopen the terminal to load the new selection.');
659
+ return {};
660
+ } }
661
+ });
662
+ live.token = token;
663
+ this.sessions.set(sessionId, live);
664
+ const args = [...command.argsPrefix, '--append-system-prompt', render(env, pack)];
665
+ if (input.model)
666
+ args.push('--model', input.model);
667
+ if (loading) {
668
+ // Pi's own discovery is off: the terminal loads what the harness found and nothing else.
669
+ args.push('--no-extensions', '--no-skills', '--no-prompt-templates', '--no-themes');
670
+ for (const path of [...loading.extensionPaths, ...loading.builtins, ...(variant?.extensionPaths ?? [])])
671
+ args.push('--extension', path);
672
+ for (const path of [...(variant?.skillPaths ?? []), ...loading.skillPaths])
673
+ args.push('--skill', path);
674
+ for (const path of loading.promptPaths)
675
+ args.push('--prompt-template', path);
676
+ for (const path of loading.themePaths)
677
+ args.push('--theme', path);
678
+ }
679
+ // Last, so its gate sees a tool call as every other extension left it.
680
+ args.push('--extension', this.assets.piExtension, '--session-dir', this.historyDir(input));
681
+ if (input.nativeSessionId)
682
+ args.push('--session', input.nativeSessionId);
683
+ return {
684
+ program: command.program,
685
+ args,
686
+ env: {
687
+ ...launch,
688
+ XINGULAR_HARNESS_NAME: env.productName,
689
+ ...(process.platform === 'win32' ? { XINGULAR_HARNESS_NODE: this.assets.node, XINGULAR_HARNESS_CLI: this.assets.cli } : {}),
690
+ ...prependSearchPath(this.ensureCommands(), searchPath()),
691
+ [SOCKET_ENV]: this.socket.path,
692
+ [TOKEN_ENV]: token
693
+ },
694
+ accountId: account.id,
695
+ nativeSessionId: input.nativeSessionId ?? null
696
+ };
697
+ }
698
+ catch (error) {
699
+ if (token)
700
+ this.socket.revoke(token);
701
+ this.sessions.delete(sessionId);
702
+ apps.revokeSession(sessionId);
703
+ await accounts.terminalEnd(account).catch(() => undefined);
704
+ throw error;
705
+ }
706
+ }
707
+ /** Hands the terminal an instruction as a new run. Resolves once the native session has taken it. */
708
+ async send(input) {
709
+ const { env } = this.options;
710
+ const { root } = env;
711
+ if (!input.text?.trim())
712
+ throw invalid('Message is empty.');
713
+ const live = this.live(input.sessionId);
714
+ if (this.options.runs.activeForSession(input.sessionId) || live.controller.state().active)
715
+ throw new HarnessError('session_busy', 'This session is still working.');
716
+ const runId = input.runId || newId();
717
+ if (findRun(root, runId))
718
+ throw invalid('This run already exists.');
719
+ saveRun(root, this.runRecord(live, runId, input.text));
720
+ copyToRun(root, live.input.sessionFolder, runId);
721
+ try {
722
+ await live.controller.send(runId, input.text);
723
+ }
724
+ catch (error) {
725
+ updateRun(root, runId, (run) => {
726
+ if (!isActiveStatus(run.status))
727
+ return;
728
+ run.status = 'failed';
729
+ run.endedAt = now();
730
+ });
731
+ throw error;
732
+ }
733
+ return { runId };
734
+ }
735
+ /** What the person typed into the terminal. */
736
+ input(sessionId, data) {
737
+ this.sessions.get(sessionId)?.controller.onInput(data);
738
+ }
739
+ state(sessionId) {
740
+ return this.live(sessionId).controller.state();
741
+ }
742
+ has(sessionId) {
743
+ return this.sessions.has(sessionId);
744
+ }
745
+ /** The terminal process ended (or never started): its turn, tokens, and written credentials go with it. */
746
+ async dispose(sessionId) {
747
+ const live = this.sessions.get(sessionId);
748
+ if (!live)
749
+ return;
750
+ for (const [id, owner] of this.diagnosticOwners)
751
+ if (owner === sessionId) {
752
+ this.options.doctor?.cancel(id);
753
+ this.diagnosticOwners.delete(id);
754
+ }
755
+ this.sessions.delete(sessionId);
756
+ this.worldNames.delete(sessionId);
757
+ void this.options.world?.release(sessionId).catch(() => undefined);
758
+ live.controller.dispose();
759
+ this.socket.revoke(live.token);
760
+ this.options.apps.revokeSession(sessionId);
761
+ await this.options.accounts.terminalEnd(live.account).catch((error) => log('terminal credentials', error instanceof Error ? error.message : String(error)));
762
+ }
763
+ async close() {
764
+ await Promise.allSettled([...this.sessions.keys()].map((sessionId) => this.dispose(sessionId)));
765
+ await this.socket.close();
766
+ }
767
+ }