@xingular/harness 0.1.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (593) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +60 -0
  4. package/README.md +265 -71
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +14842 -9445
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +1170 -62
  373. package/docs/README.md +34 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0001-owned-terminal.md +87 -0
  403. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  404. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  405. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  406. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  407. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  408. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  409. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  410. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  411. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  412. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  413. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  414. package/docs/decisions/ADR-0013-doctor.md +27 -0
  415. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  416. package/docs/doctor.md +74 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  418. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  420. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  421. package/docs/features/README.md +20 -0
  422. package/docs/features/automations/README.md +41 -0
  423. package/docs/features/cores/README.md +39 -0
  424. package/docs/features/google-harness2/README.md +52 -0
  425. package/docs/features/integrations/README.md +40 -0
  426. package/docs/features/interfaces/README.md +29 -0
  427. package/docs/features/memory/README.md +28 -0
  428. package/docs/releases/1.0.0.md +40 -0
  429. package/docs/releases/README.md +36 -0
  430. package/docs/study/00-index.md +78 -0
  431. package/docs/study/arms/00-matrix.md +20 -0
  432. package/docs/study/arms/01-system-prompt.md +211 -0
  433. package/docs/study/arms/02-tools.md +79 -0
  434. package/docs/study/arms/03-subagents.md +90 -0
  435. package/docs/study/arms/04-skills.md +75 -0
  436. package/docs/study/arms/05-context-management.md +90 -0
  437. package/docs/study/arms/06-memory.md +90 -0
  438. package/docs/study/arms/07-governance.md +71 -0
  439. package/docs/study/arms/08-execution.md +69 -0
  440. package/docs/study/arms/09-observability.md +60 -0
  441. package/docs/study/arms/10-refinement.md +110 -0
  442. package/docs/study/btw-comparison.md +37 -0
  443. package/docs/study/feature-gap-review.md +42 -0
  444. package/docs/study/insights.md +123 -0
  445. package/docs/study/roadmap.md +72 -0
  446. package/docs/study/sources/claude-code.md +44 -0
  447. package/docs/study/sources/deepseek-harness.md +102 -0
  448. package/docs/study/sources/harness2.md +50 -0
  449. package/docs/study/sources/kimi-cli.md +42 -0
  450. package/docs/study/sources/omp.md +93 -0
  451. package/docs/study/sources/opencode.md +43 -0
  452. package/docs/study/sources/openhands.md +46 -0
  453. package/docs/study/sources/smolagents.md +40 -0
  454. package/docs/study/sources/swe-agent.md +34 -0
  455. package/docs/system-prompt-design.md +196 -0
  456. package/docs/terminal-tui.md +671 -0
  457. package/package.json +48 -12
  458. package/src/accounts/accounts.test.ts +0 -223
  459. package/src/accounts/accounts.ts +0 -522
  460. package/src/accounts/env.test.ts +0 -95
  461. package/src/accounts/env.ts +0 -338
  462. package/src/accounts/secrets.ts +0 -50
  463. package/src/accounts/store.ts +0 -338
  464. package/src/capabilities/api.ts +0 -75
  465. package/src/capabilities/runSnapshot.ts +0 -59
  466. package/src/capabilities/types.ts +0 -34
  467. package/src/cli.ts +0 -114
  468. package/src/core/bus.ts +0 -34
  469. package/src/core/changes.ts +0 -33
  470. package/src/core/env.ts +0 -27
  471. package/src/core/errors.ts +0 -32
  472. package/src/core/frontmatter.ts +0 -47
  473. package/src/core/fs.test.ts +0 -38
  474. package/src/core/fs.ts +0 -92
  475. package/src/core/index.ts +0 -193
  476. package/src/core/path.test.ts +0 -14
  477. package/src/core/path.ts +0 -79
  478. package/src/core/projects.ts +0 -90
  479. package/src/core/text.ts +0 -39
  480. package/src/harness.ts +0 -299
  481. package/src/index.ts +0 -70
  482. package/src/mcp/connections.ts +0 -614
  483. package/src/mcp/manager.ts +0 -130
  484. package/src/mcp/oauth.ts +0 -195
  485. package/src/mcp/scopeMigration.test.ts +0 -79
  486. package/src/mcp/scopeMigration.ts +0 -204
  487. package/src/mcp/service.test.ts +0 -376
  488. package/src/mcp/service.ts +0 -549
  489. package/src/mcp/types.ts +0 -108
  490. package/src/memory/api.test.ts +0 -82
  491. package/src/memory/api.ts +0 -289
  492. package/src/memory/blocks.test.ts +0 -78
  493. package/src/memory/blocks.ts +0 -406
  494. package/src/memory/caller.ts +0 -57
  495. package/src/memory/dispatch.ts +0 -59
  496. package/src/memory/facts.test.ts +0 -41
  497. package/src/memory/facts.ts +0 -248
  498. package/src/memory/graph.ts +0 -103
  499. package/src/memory/health.test.ts +0 -130
  500. package/src/memory/health.ts +0 -74
  501. package/src/memory/maintainer.ts +0 -272
  502. package/src/memory/maintenance.test.ts +0 -176
  503. package/src/memory/maintenance.ts +0 -330
  504. package/src/memory/migrate.ts +0 -79
  505. package/src/memory/operations.ts +0 -138
  506. package/src/memory/proposals.test.ts +0 -168
  507. package/src/memory/proposals.ts +0 -576
  508. package/src/memory/recall.test.ts +0 -104
  509. package/src/memory/recall.ts +0 -271
  510. package/src/memory/references.ts +0 -77
  511. package/src/memory/runContext.ts +0 -93
  512. package/src/memory/secrets.ts +0 -6
  513. package/src/memory/store.test.ts +0 -66
  514. package/src/memory/store.ts +0 -385
  515. package/src/memory/wiki.test.ts +0 -47
  516. package/src/memory/wiki.ts +0 -422
  517. package/src/memory/wikiIndex.test.ts +0 -88
  518. package/src/memory/wikiIndex.ts +0 -116
  519. package/src/plugins/api.ts +0 -181
  520. package/src/plugins/attachments.test.ts +0 -84
  521. package/src/plugins/attachments.ts +0 -141
  522. package/src/plugins/builtin.ts +0 -82
  523. package/src/plugins/catalogue.test.ts +0 -254
  524. package/src/plugins/catalogue.ts +0 -251
  525. package/src/plugins/cli.ts +0 -184
  526. package/src/plugins/discover.ts +0 -151
  527. package/src/plugins/firstParty.test.ts +0 -143
  528. package/src/plugins/firstParty.ts +0 -129
  529. package/src/plugins/hooks.test.ts +0 -250
  530. package/src/plugins/hooks.ts +0 -239
  531. package/src/plugins/identity.ts +0 -37
  532. package/src/plugins/install.test.ts +0 -107
  533. package/src/plugins/install.ts +0 -106
  534. package/src/plugins/inventory.ts +0 -123
  535. package/src/plugins/manifest.ts +0 -76
  536. package/src/plugins/plugins.test.ts +0 -205
  537. package/src/plugins/plugins.ts +0 -189
  538. package/src/plugins/proposal.ts +0 -121
  539. package/src/plugins/runtime.test.ts +0 -40
  540. package/src/plugins/runtime.ts +0 -82
  541. package/src/plugins/trust.ts +0 -142
  542. package/src/plugins/types.ts +0 -149
  543. package/src/prompt/compile.test.ts +0 -261
  544. package/src/prompt/compile.ts +0 -732
  545. package/src/server/methods.ts +0 -314
  546. package/src/server/remote.ts +0 -77
  547. package/src/server/rpc.ts +0 -116
  548. package/src/server/serve.ts +0 -28
  549. package/src/server/server.test.ts +0 -174
  550. package/src/sessions/approvals.ts +0 -118
  551. package/src/sessions/contracts.ts +0 -310
  552. package/src/sessions/conversation.test.ts +0 -150
  553. package/src/sessions/extensionSession.test.ts +0 -74
  554. package/src/sessions/extensionUi.test.ts +0 -65
  555. package/src/sessions/extensionUi.ts +0 -102
  556. package/src/sessions/history.ts +0 -51
  557. package/src/sessions/lineageJoin.ts +0 -75
  558. package/src/sessions/policy.ts +0 -32
  559. package/src/sessions/pricing.ts +0 -60
  560. package/src/sessions/reasoningSummaries.ts +0 -59
  561. package/src/sessions/registry.ts +0 -294
  562. package/src/sessions/runIndex.ts +0 -99
  563. package/src/sessions/runStore.test.ts +0 -152
  564. package/src/sessions/runStore.ts +0 -332
  565. package/src/sessions/runner.ts +0 -569
  566. package/src/sessions/runtimeResources.test.ts +0 -61
  567. package/src/sessions/sessions.test.ts +0 -455
  568. package/src/sessions/sessions.ts +0 -295
  569. package/src/skills/registry.test.ts +0 -104
  570. package/src/skills/registry.ts +0 -407
  571. package/src/terminal/cli.ts +0 -149
  572. package/src/terminal/client.ts +0 -74
  573. package/src/terminal/controller.ts +0 -227
  574. package/src/terminal/launch.test.ts +0 -34
  575. package/src/terminal/launch.ts +0 -88
  576. package/src/terminal/piExtension.ts +0 -210
  577. package/src/terminal/pluginControl.test.ts +0 -146
  578. package/src/terminal/pluginMenu.ts +0 -112
  579. package/src/terminal/socket.test.ts +0 -71
  580. package/src/terminal/socket.ts +0 -221
  581. package/src/terminal/standalone.test.ts +0 -130
  582. package/src/terminal/standalone.ts +0 -144
  583. package/src/terminal/terminal.test.ts +0 -330
  584. package/src/terminal/terminals.ts +0 -443
  585. package/src/tools/askUser.ts +0 -45
  586. package/src/tools/definitions.ts +0 -187
  587. package/src/tools/memoryTools.ts +0 -22
  588. package/src/tools/pluginPropose.ts +0 -41
  589. package/src/tools/types.ts +0 -39
  590. package/src/web/safeRequest.ts +0 -171
  591. package/src/web/text.ts +0 -53
  592. package/src/web/tools.ts +0 -134
  593. package/src/web/web.test.ts +0 -141
@@ -0,0 +1,60 @@
1
+ import { Input, matchesKey, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
2
+ export const SEARCH_GLYPH = '⌕';
3
+ export const SEARCH_PLACEHOLDER = 'Type to search';
4
+ export const SEARCH_FIELD_ROWS = 5;
5
+ export function searchFieldRowsFor(availableRows) {
6
+ const fieldRoom = Math.max(0, Math.floor(availableRows) - 1);
7
+ if (fieldRoom >= SEARCH_FIELD_ROWS)
8
+ return SEARCH_FIELD_ROWS;
9
+ return fieldRoom >= 3 ? 3 : 1;
10
+ }
11
+ const SCREEN_KEYS = ['left', 'right', 'up', 'down', 'enter', 'tab', 'shift+tab', 'escape', 'pageUp', 'pageDown', 'home', 'end'];
12
+ export class SearchField {
13
+ theme;
14
+ input;
15
+ constructor(theme, placeholder = SEARCH_PLACEHOLDER) {
16
+ this.theme = theme;
17
+ this.input = new Input({ prompt: '', placeholder, placeholderStyle: text => this.theme().fg('dim', text) });
18
+ }
19
+ get value() { return this.input.getValue(); }
20
+ set focused(value) { this.input.focused = value; }
21
+ /** Presets the text, for a command that was given something to search for. */
22
+ setValue(text) { this.input.setValue(text); }
23
+ /** Empties the field; says whether there was anything to empty. */
24
+ clear() {
25
+ if (!this.value)
26
+ return false;
27
+ this.input.setValue('');
28
+ return true;
29
+ }
30
+ /** Takes typed text, paste, Backspace and Ctrl+U. Says whether the text changed. */
31
+ handleInput(data) {
32
+ if (SCREEN_KEYS.some(key => matchesKey(data, key)))
33
+ return false;
34
+ const before = this.value;
35
+ this.input.handleInput(data);
36
+ return this.value !== before;
37
+ }
38
+ invalidate() { this.input.invalidate(); }
39
+ /** One row, `width` cells: the glyph, the text or placeholder, and `note` at the right edge. */
40
+ render(width, note = '') {
41
+ if (width < 1)
42
+ return '';
43
+ const theme = this.theme();
44
+ const glyph = theme.fg('text', `${SEARCH_GLYPH} `);
45
+ const room = Math.max(0, width - visibleWidth(glyph));
46
+ const shownNote = note && room > visibleWidth(note) + 8 ? note : '';
47
+ const field = this.input.render(Math.max(1, room - (shownNote ? visibleWidth(shownNote) + 1 : 0)))[0] ?? '';
48
+ return truncateToWidth(glyph + field + (shownNote ? ' ' + theme.fg('muted', shownNote) : ''), width, '');
49
+ }
50
+ renderLines(width, note = '', rows = SEARCH_FIELD_ROWS) {
51
+ if (width < 1)
52
+ return [];
53
+ if (rows < 3)
54
+ return [this.render(width, note)];
55
+ const rule = this.theme().fg('border', '─'.repeat(width));
56
+ return rows >= SEARCH_FIELD_ROWS
57
+ ? ['', rule, this.render(width, note), rule, '']
58
+ : [rule, this.render(width, note), rule];
59
+ }
60
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * One selection palette for every terminal surface. A selected row is a muted blue field with
3
+ * explicit near-white text, so the accent colour never sits on the selection background.
4
+ */
5
+ export declare const SELECTION_COLORS: {
6
+ readonly dark: {
7
+ readonly background: "#1b314d";
8
+ readonly text: "#f4f8ff";
9
+ readonly muted: "#c4d3e6";
10
+ };
11
+ readonly light: {
12
+ readonly background: "#dbe8fa";
13
+ readonly text: "#10233a";
14
+ readonly muted: "#455a72";
15
+ };
16
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * One selection palette for every terminal surface. A selected row is a muted blue field with
3
+ * explicit near-white text, so the accent colour never sits on the selection background.
4
+ */
5
+ export const SELECTION_COLORS = {
6
+ dark: {
7
+ background: '#1b314d',
8
+ text: '#f4f8ff',
9
+ muted: '#c4d3e6'
10
+ },
11
+ light: {
12
+ background: '#dbe8fa',
13
+ text: '#10233a',
14
+ muted: '#455a72'
15
+ }
16
+ };
@@ -0,0 +1,3 @@
1
+ import type { ExtensionUIContext } from '@earendil-works/pi-coding-agent';
2
+ /** Retained UI methods belong to the resource generation that received them. */
3
+ export declare function sessionUiContext(ui: ExtensionUIContext, current: () => boolean): ExtensionUIContext;
@@ -0,0 +1,30 @@
1
+ const dialogs = new Set(['select', 'input', 'editor', 'custom']);
2
+ /** Retained UI methods belong to the resource generation that received them. */
3
+ export function sessionUiContext(ui, current) {
4
+ return new Proxy(ui, {
5
+ get(target, key, receiver) {
6
+ const value = Reflect.get(target, key, receiver);
7
+ if (typeof value !== 'function')
8
+ return value;
9
+ return (...args) => {
10
+ if (current())
11
+ return Reflect.apply(value, target, args);
12
+ if (key === 'confirm')
13
+ return Promise.resolve(false);
14
+ if (dialogs.has(String(key)))
15
+ return Promise.resolve(undefined);
16
+ if (key === 'onTerminalInput')
17
+ return () => { };
18
+ if (key === 'setTheme')
19
+ return { success: false, error: 'This terminal session has ended.' };
20
+ if (key === 'getEditorText')
21
+ return '';
22
+ if (key === 'getToolsExpanded')
23
+ return false;
24
+ if (key === 'getAllThemes')
25
+ return [];
26
+ return undefined;
27
+ };
28
+ }
29
+ });
30
+ }
@@ -0,0 +1,12 @@
1
+ import type { AgentSession, ExtensionUIContext } from '@earendil-works/pi-coding-agent';
2
+ import type { TerminalSettingItem } from "./pages/settingsPage.js";
3
+ export interface SettingsModelHost {
4
+ session(): AgentSession;
5
+ ui: ExtensionUIContext;
6
+ hotkeys?(): string;
7
+ refresh(): void;
8
+ }
9
+ export declare function createSettingsModel(host: SettingsModelHost): {
10
+ items: () => TerminalSettingItem[];
11
+ apply: (id: string) => Promise<void>;
12
+ };
@@ -0,0 +1,84 @@
1
+ const GROUP_ORDER = ['Theme', 'Display', 'Images', 'Thinking', 'Recovery', 'Editor', 'Queues', 'Commands', 'Terminal', 'Keyboard', 'Compaction'];
2
+ export function createSettingsModel(host) {
3
+ const booleans = (session) => {
4
+ const settings = session.settingsManager;
5
+ return [
6
+ ['Auto compaction', () => session.autoCompactionEnabled, (value) => session.setAutoCompactionEnabled(value)],
7
+ ['Auto retry', () => session.autoRetryEnabled, (value) => session.setAutoRetryEnabled(value)],
8
+ ['Show images', () => settings.getShowImages(), (value) => settings.setShowImages(value)],
9
+ ['Resize images', () => settings.getImageAutoResize(), (value) => settings.setImageAutoResize(value)],
10
+ ['Block images', () => settings.getBlockImages(), (value) => settings.setBlockImages(value)],
11
+ ['Skill commands', () => settings.getEnableSkillCommands(), (value) => settings.setEnableSkillCommands(value)],
12
+ ['Hide thinking', () => settings.getHideThinkingBlock(), (value) => settings.setHideThinkingBlock(value)],
13
+ ['Hardware cursor', () => settings.getShowHardwareCursor(), (value) => settings.setShowHardwareCursor(value)],
14
+ ['Terminal progress', () => settings.getShowTerminalProgress(), (value) => settings.setShowTerminalProgress(value)]
15
+ ];
16
+ };
17
+ const locations = [
18
+ ['Context', 'Compaction'], ['Model', 'Recovery'], ['Appearance', 'Images'], ['Appearance', 'Images'],
19
+ ['Context', 'Images'], ['Interaction', 'Commands'], ['Appearance', 'Display'], ['Interaction', 'Editor'],
20
+ ['Interaction', 'Terminal'], ['Model', 'Thinking'], ['Interaction', 'Queues'], ['Interaction', 'Queues'],
21
+ ['Appearance', 'Theme'], ['Interaction', 'Keyboard']
22
+ ];
23
+ const descriptions = [
24
+ 'Compact the context automatically when the session approaches its limit.', 'Retry eligible provider failures automatically.',
25
+ 'Display actual image content returned by tools.', 'Resize image attachments before provider requests.',
26
+ 'Block image attachments in provider requests.', 'Expose commands for the skills loaded in this session.',
27
+ 'Collapse assistant thinking blocks in the transcript.', 'Display the terminal hardware cursor for editing and input methods.',
28
+ 'Report active work through supported terminal progress controls.', 'Reasoning effort for the current model.',
29
+ 'Delivery mode for messages that steer an active run.', 'Delivery mode for messages queued after a run.',
30
+ 'Theme loaded from the trusted resource catalog.', 'View the current application keyboard bindings.'
31
+ ];
32
+ /** One line per setting, `Label: value`; its position is the setting's id. */
33
+ const options = (session) => [
34
+ ...booleans(session).map(([label, get]) => `${label}: ${get() ? 'on' : 'off'}`),
35
+ `Thinking: ${session.thinkingLevel}`, `Steering: ${session.steeringMode}`, `Follow-up: ${session.followUpMode}`,
36
+ `Theme: ${host.ui.theme.name}`, 'Keyboard controls'
37
+ ];
38
+ function items() {
39
+ const result = options(host.session()).map((option, index) => {
40
+ const split = option.indexOf(':');
41
+ return { id: String(index), tab: locations[index][0], group: locations[index][1], label: split < 0 ? option : option.slice(0, split), value: split < 0 ? '' : option.slice(split + 1).trim(), description: descriptions[index] };
42
+ });
43
+ return result.sort((a, b) => GROUP_ORDER.indexOf(a.group) - GROUP_ORDER.indexOf(b.group));
44
+ }
45
+ async function apply(id) {
46
+ const session = host.session();
47
+ const index = Number(id);
48
+ const switches = booleans(session);
49
+ const selected = options(session)[index];
50
+ if (selected === undefined)
51
+ return;
52
+ if (index < switches.length) {
53
+ const [, get, set] = switches[index];
54
+ set(!get());
55
+ }
56
+ else if (selected.startsWith('Thinking:')) {
57
+ const level = await host.ui.select('Thinking effort', session.getAvailableThinkingLevels());
58
+ if (level)
59
+ session.setThinkingLevel(level, { persist: true });
60
+ }
61
+ else if (selected.startsWith('Steering:') || selected.startsWith('Follow-up:')) {
62
+ const mode = await host.ui.select('Queue delivery', ['all', 'one-at-a-time']);
63
+ if (mode === 'all' || mode === 'one-at-a-time') {
64
+ if (selected.startsWith('Steering:'))
65
+ session.setSteeringMode(mode);
66
+ else
67
+ session.setFollowUpMode(mode);
68
+ }
69
+ }
70
+ else if (selected.startsWith('Theme:')) {
71
+ const theme = await host.ui.select('Theme', host.ui.getAllThemes().map(item => item.name));
72
+ if (theme) {
73
+ const result = host.ui.setTheme(theme);
74
+ if (!result.success)
75
+ throw new Error(result.error);
76
+ session.settingsManager.setTheme(theme);
77
+ }
78
+ }
79
+ else
80
+ host.ui.notify(host.hotkeys?.() ?? 'Use /help for commands. Keyboard bindings are managed by the terminal application.', 'info');
81
+ host.refresh();
82
+ }
83
+ return { items, apply };
84
+ }
@@ -0,0 +1,53 @@
1
+ import { type AgentSession, type AgentSessionServices, type Theme } from '@earendil-works/pi-coding-agent';
2
+ import { type Component } from '@earendil-works/pi-tui';
3
+ export declare const SIDE_PROMPT: string;
4
+ export declare const ANSWER_ROWS = 8;
5
+ /**
6
+ * A bounded plain-text excerpt of the main conversation: the last few user and assistant turns, the
7
+ * tools an assistant turn called by name, and whether the reply is still running. Hidden reasoning,
8
+ * tool inputs and results, and images are left out.
9
+ */
10
+ export declare function sideQuestionSnapshot(messages: readonly unknown[], running: boolean): string;
11
+ /** What the controller needs from a session; a Pi `AgentSession` satisfies it through `createSideSession`. */
12
+ export interface SideSession {
13
+ prompt(text: string): Promise<void>;
14
+ abort(): Promise<void>;
15
+ subscribe(listener: () => void): () => void;
16
+ answer(): string;
17
+ /** Why the provider ended the turn in error, if it did. */
18
+ failure(): string | undefined;
19
+ dispose(): void;
20
+ }
21
+ /** A separate in-memory session on the same account and model, with no tools, extensions, skills or project files. */
22
+ export declare function createSideSession(services: AgentSessionServices, main: AgentSession): Promise<SideSession>;
23
+ export type SideState = 'thinking' | 'answered' | 'failed';
24
+ export interface SideQuestionOptions {
25
+ create(): Promise<SideSession>;
26
+ snapshot(): string;
27
+ theme(): Theme;
28
+ /** Puts the dock above the composer, or takes it away. */
29
+ mount(dock: Component | undefined): void;
30
+ changed(): void;
31
+ }
32
+ export declare class SideQuestion {
33
+ private readonly options;
34
+ private session;
35
+ private unsubscribe;
36
+ private generation;
37
+ private question;
38
+ private answerText;
39
+ private error;
40
+ private current;
41
+ private startedAt;
42
+ private readonly dock;
43
+ constructor(options: SideQuestionOptions);
44
+ get visible(): boolean;
45
+ get state(): SideState | undefined;
46
+ /** Asks one question, replacing any earlier one. Empty text dismisses. */
47
+ ask(question: string): Promise<void>;
48
+ /** Interrupts a running side question and removes the dock. */
49
+ dismiss(): Promise<void>;
50
+ private release;
51
+ /** The dock: a neutral rule, the inline question, its answer, and a hint, separated by blank rows. */
52
+ private render;
53
+ }
@@ -0,0 +1,197 @@
1
+ // `/btw <question>`: a side question answered by a separate, tool-free session while the main
2
+ // conversation carries on. It lives in a dock above the composer, never enters the transcript, the
3
+ // queue or the run history, and is gone on dismiss, on a session change, or when a new one replaces it.
4
+ import { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager } from '@earendil-works/pi-coding-agent';
5
+ import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
6
+ import { contentWidth, footerRow, neutralRule, padded, safeText } from "./chrome.js";
7
+ import { getWorkingSpinnerFrames, SPINNER_INTERVAL_MS, spinnerFrameAt } from "./workingStatus.js";
8
+ export const SIDE_PROMPT = [
9
+ 'You answer one short side question from a person whose main task is still running in another session.',
10
+ 'You have no tools: you cannot read or change files, run commands, browse, or call anything, and you must not say you did.',
11
+ 'Use the conversation excerpt for context and do not invent what it does not show. Answer briefly and plainly.'
12
+ ].join(' ');
13
+ const TURNS = 6;
14
+ const TURN_CHARS = 1_200;
15
+ const TOTAL_CHARS = 6_000;
16
+ const QUESTION_ROWS = 2;
17
+ export const ANSWER_ROWS = 8;
18
+ function blocks(content) {
19
+ if (typeof content === 'string')
20
+ return [{ type: 'text', text: content }];
21
+ return Array.isArray(content) ? content.filter((block) => typeof block === 'object' && block !== null) : [];
22
+ }
23
+ const clip = (text, limit) => text.length > limit ? `${text.slice(0, limit)}…` : text;
24
+ /**
25
+ * A bounded plain-text excerpt of the main conversation: the last few user and assistant turns, the
26
+ * tools an assistant turn called by name, and whether the reply is still running. Hidden reasoning,
27
+ * tool inputs and results, and images are left out.
28
+ */
29
+ export function sideQuestionSnapshot(messages, running) {
30
+ const turns = [];
31
+ for (const message of messages) {
32
+ const { role, content } = (message ?? {});
33
+ if (role !== 'user' && role !== 'assistant')
34
+ continue;
35
+ const parts = blocks(content);
36
+ const text = parts.filter(block => block.type === 'text' && typeof block.text === 'string').map(block => String(block.text)).join('\n').trim();
37
+ const tools = [...new Set(parts.filter(block => block.type === 'toolCall' && typeof block.name === 'string').map(block => String(block.name)))];
38
+ if (!text && !tools.length)
39
+ continue;
40
+ turns.push(`${role === 'user' ? 'User' : 'Assistant'}: ${clip(safeText(text).replace(/\s+/g, ' ').trim(), TURN_CHARS)}${tools.length ? ` [used tools: ${tools.join(', ')}]` : ''}`);
41
+ }
42
+ let recent = turns.slice(-TURNS);
43
+ while (recent.length > 1 && recent.join('\n').length > TOTAL_CHARS)
44
+ recent = recent.slice(1);
45
+ const lines = ['Conversation excerpt, oldest first:', ...(recent.length ? recent : ['(nothing yet)'])];
46
+ if (running)
47
+ lines.push('', 'The main reply is still running; its latest turn above may be unfinished.');
48
+ return lines.join('\n');
49
+ }
50
+ /** A separate in-memory session on the same account and model, with no tools, extensions, skills or project files. */
51
+ export async function createSideSession(services, main) {
52
+ const model = main.model;
53
+ if (!model || model.id === 'unknown')
54
+ throw new Error('Choose a model before asking a side question.');
55
+ const settingsManager = SettingsManager.inMemory({});
56
+ const resourceLoader = new DefaultResourceLoader({
57
+ cwd: services.cwd, agentDir: services.agentDir, settingsManager,
58
+ noExtensions: true, noSkills: true, noPromptTemplates: true, noThemes: true, noContextFiles: true, systemPrompt: SIDE_PROMPT
59
+ });
60
+ await resourceLoader.reload();
61
+ const { session } = await createAgentSession({
62
+ cwd: services.cwd, agentDir: services.agentDir, modelRuntime: services.modelRuntime, settingsManager, resourceLoader,
63
+ sessionManager: SessionManager.inMemory(services.cwd), model, thinkingLevel: 'off', noTools: 'all'
64
+ });
65
+ return {
66
+ prompt: text => session.prompt(text),
67
+ abort: () => session.abort(),
68
+ subscribe: listener => session.subscribe(() => listener()),
69
+ answer: () => session.getLastAssistantText() ?? '',
70
+ failure: () => {
71
+ const last = session.messages.at(-1);
72
+ return last?.role === 'assistant' && last.stopReason === 'error' ? last.errorMessage ?? 'The provider returned an error.' : undefined;
73
+ },
74
+ dispose: () => session.dispose()
75
+ };
76
+ }
77
+ export class SideQuestion {
78
+ options;
79
+ session;
80
+ unsubscribe;
81
+ generation = 0;
82
+ question = '';
83
+ answerText = '';
84
+ error;
85
+ current;
86
+ startedAt = 0;
87
+ dock;
88
+ constructor(options) {
89
+ this.options = options;
90
+ this.dock = { invalidate: () => { }, render: width => this.render(width) };
91
+ }
92
+ get visible() { return this.current !== undefined; }
93
+ get state() { return this.current; }
94
+ /** Asks one question, replacing any earlier one. Empty text dismisses. */
95
+ async ask(question) {
96
+ const text = question.trim();
97
+ if (!text) {
98
+ await this.dismiss();
99
+ return;
100
+ }
101
+ await this.release();
102
+ const generation = ++this.generation;
103
+ this.question = text;
104
+ this.startedAt = Date.now();
105
+ this.answerText = '';
106
+ this.error = undefined;
107
+ this.current = 'thinking';
108
+ this.options.mount(this.dock);
109
+ this.options.changed();
110
+ try {
111
+ const session = await this.options.create();
112
+ if (generation !== this.generation) {
113
+ session.dispose();
114
+ return;
115
+ }
116
+ this.session = session;
117
+ this.unsubscribe = session.subscribe(() => {
118
+ if (generation !== this.generation)
119
+ return;
120
+ this.answerText = session.answer();
121
+ this.options.changed();
122
+ });
123
+ await session.prompt(`${this.options.snapshot()}\n\nSide question: ${text}`);
124
+ if (generation !== this.generation)
125
+ return;
126
+ this.answerText = session.answer();
127
+ const failure = session.failure();
128
+ if (failure) {
129
+ this.current = 'failed';
130
+ this.error = failure;
131
+ }
132
+ else
133
+ this.current = 'answered';
134
+ }
135
+ catch (error) {
136
+ if (generation !== this.generation)
137
+ return;
138
+ this.current = 'failed';
139
+ this.error = error instanceof Error ? error.message : String(error);
140
+ }
141
+ this.options.changed();
142
+ }
143
+ /** Interrupts a running side question and removes the dock. */
144
+ async dismiss() {
145
+ this.generation++;
146
+ this.current = undefined;
147
+ await this.release();
148
+ this.options.mount(undefined);
149
+ this.options.changed();
150
+ }
151
+ async release() {
152
+ const session = this.session;
153
+ this.session = undefined;
154
+ this.unsubscribe?.();
155
+ this.unsubscribe = undefined;
156
+ if (!session)
157
+ return;
158
+ try {
159
+ await session.abort();
160
+ }
161
+ catch { /* A side run that cannot be stopped is still dropped. */ }
162
+ try {
163
+ session.dispose();
164
+ }
165
+ catch { /* Cleanup cannot keep the dock open. */ }
166
+ }
167
+ /** The dock: a neutral rule, the inline question, its answer, and a hint, separated by blank rows. */
168
+ render(width) {
169
+ if (width < 1 || !this.current)
170
+ return [];
171
+ const theme = this.options.theme();
172
+ const inner = contentWidth(width);
173
+ const spinner = this.current === 'thinking'
174
+ ? spinnerFrameAt(Date.now() - this.startedAt, getWorkingSpinnerFrames(process.env.TERM), SPINNER_INTERVAL_MS)
175
+ : '';
176
+ const marker = `${spinner ? `${spinner} ` : ''}/btw`;
177
+ const markerWidth = visibleWidth(marker) + 1;
178
+ const asked = wrapTextWithAnsi(safeText(this.question), Math.max(1, inner - markerWidth));
179
+ const question = asked.slice(0, QUESTION_ROWS).map((line, index) => {
180
+ const prefix = index === 0 ? `${theme.bold(theme.fg('accent', marker))} ` : ' '.repeat(markerWidth);
181
+ return prefix + theme.fg('muted', line);
182
+ });
183
+ if (asked.length > QUESTION_ROWS)
184
+ question[QUESTION_ROWS - 1] = truncateToWidth(question[QUESTION_ROWS - 1], inner - 1, '') + theme.fg('muted', '…');
185
+ const text = this.current === 'failed' ? `${this.answerText ? `${this.answerText}\n` : ''}${this.error ?? 'The side question failed.'}` : this.answerText;
186
+ const wrapped = text ? text.split('\n').flatMap(line => line ? wrapTextWithAnsi(safeText(line), inner) : ['']) : [];
187
+ const shown = wrapped.slice(0, ANSWER_ROWS).map(line => this.current === 'failed' ? theme.fg('error', line) : line);
188
+ const more = wrapped.length - shown.length;
189
+ return [
190
+ neutralRule(width, theme),
191
+ ...question.map(line => padded(line, width)),
192
+ ...(shown.length ? ['', ...shown.map(line => padded(line, width))] : []),
193
+ '',
194
+ footerRow(`${more > 0 ? `+${more} more lines · ` : ''}/btw or Esc to dismiss`, width, theme)
195
+ ].map(line => truncateToWidth(line, width, ''));
196
+ }
197
+ }
@@ -0,0 +1,9 @@
1
+ import type { AutocompleteProvider } from '@earendil-works/pi-tui';
2
+ export interface SkillEntry {
3
+ name: string;
4
+ description: string;
5
+ }
6
+ /** Rewrites a leading `$name` of a loaded skill into `/skill:name`. Anything else passes through, so `$5` stays text. */
7
+ export declare function expandSkillInvocation(text: string, skills: ReadonlySet<string>): string;
8
+ /** Offers the loaded skills at a `$` that starts a word. Every other completion is `base`'s. */
9
+ export declare function skillCompletions(base: AutocompleteProvider, skills: () => readonly SkillEntry[]): AutocompleteProvider;
@@ -0,0 +1,43 @@
1
+ /** Rewrites a leading `$name` of a loaded skill into `/skill:name`. Anything else passes through, so `$5` stays text. */
2
+ export function expandSkillInvocation(text, skills) {
3
+ const trimmed = text.trimStart();
4
+ const match = /^\$(\S+)(?=\s|$)/.exec(trimmed);
5
+ if (!match || !skills.has(match[1]))
6
+ return text;
7
+ return `/skill:${match[1]}${trimmed.slice(match[0].length)}`;
8
+ }
9
+ /** A `$` that starts a word, and the partial name after it, at the cursor. */
10
+ const SKILL_TOKEN = /(?:^|\s)\$([^\s$]*)$/;
11
+ /** A line whose first word is a skill invocation. */
12
+ const SKILL_LINE = /^\s*\$\S/;
13
+ /** Offers the loaded skills at a `$` that starts a word. Every other completion is `base`'s. */
14
+ export function skillCompletions(base, skills) {
15
+ return {
16
+ triggerCharacters: [...(base.triggerCharacters ?? []), '$'],
17
+ async getSuggestions(lines, cursorLine, cursorCol, options) {
18
+ const line = lines[cursorLine] ?? '';
19
+ const token = SKILL_TOKEN.exec(line.slice(0, cursorCol));
20
+ if (token) {
21
+ const partial = token[1];
22
+ const items = skills()
23
+ .filter((skill) => skill.name.startsWith(partial))
24
+ .map((skill) => ({ value: skill.name, label: `$${skill.name}`, description: skill.description }));
25
+ return items.length ? { items, prefix: `$${partial}` } : null;
26
+ }
27
+ // The arguments of a line that starts with a skill invocation are free text, not file paths.
28
+ if (SKILL_LINE.test(line))
29
+ return null;
30
+ return base.getSuggestions(lines, cursorLine, cursorCol, options);
31
+ },
32
+ applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
33
+ if (!prefix.startsWith('$'))
34
+ return base.applyCompletion(lines, cursorLine, cursorCol, item, prefix);
35
+ const line = lines[cursorLine] ?? '';
36
+ const start = cursorCol - prefix.length;
37
+ const inserted = `$${item.value} `;
38
+ const newLines = [...lines];
39
+ newLines[cursorLine] = `${line.slice(0, start)}${inserted}${line.slice(cursorCol)}`;
40
+ return { lines: newLines, cursorLine, cursorCol: start + inserted.length };
41
+ }
42
+ };
43
+ }
@@ -0,0 +1,18 @@
1
+ import type { Theme } from '@earendil-works/pi-coding-agent';
2
+ export interface BandState {
3
+ cwd: string;
4
+ model?: {
5
+ name: string;
6
+ reasoning: boolean;
7
+ contextWindow: number;
8
+ };
9
+ thinkingLevel: string;
10
+ branch: string | null;
11
+ account?: string;
12
+ inputTokens: number;
13
+ outputTokens: number;
14
+ }
15
+ export declare function singleLine(text: string): string;
16
+ export declare function displayProjectName(cwd: string): string;
17
+ export declare function formatTokenCount(value: number): string;
18
+ export declare function renderStatusBand(state: BandState, width: number, theme: Theme): string;
@@ -0,0 +1,67 @@
1
+ // Presentation adapted from Oh My Pi 18.11.3's status line; it sits in the footer below the prompt frame.
2
+ // Upstream MIT license and evidence are recorded in NOTICE.md and docs/terminal-tui.md.
3
+ import { basename, sep } from 'node:path';
4
+ import { parseColor, stripTerminalSequences, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
5
+ import { TITANIUM } from "./theme.js";
6
+ // OMP's shipped light theme supplies status colors separately from transcript colors.
7
+ const LIGHT_STATUS = {
8
+ ...TITANIUM, darkTitanium: '#e0e0e0', electricBlue: '#875f87', subtleGray: '#808080',
9
+ brightAluminum: '#005f87', readoutGreen: '#005f00', titaniumGold: '#005f5f'
10
+ };
11
+ const palette = (theme) => theme.appearance === 'light' ? LIGHT_STATUS : TITANIUM;
12
+ export function singleLine(text) {
13
+ return stripTerminalSequences(text).replace(/[\x00-\x1f\x7f-\x9f]/g, ' ').replace(/ +/g, ' ').trim();
14
+ }
15
+ export function displayProjectName(cwd) {
16
+ return singleLine(basename(cwd) || cwd || sep);
17
+ }
18
+ export function formatTokenCount(value) {
19
+ const count = Math.max(0, Number.isFinite(value) ? Math.floor(value) : 0);
20
+ if (count >= 1_000_000_000)
21
+ return `${Math.floor(count / 1_000_000_000)}B`;
22
+ if (count >= 1_000_000)
23
+ return `${Math.floor(count / 1_000_000)}M`;
24
+ if (count >= 1_000)
25
+ return `${Math.floor(count / 1_000)}K`;
26
+ return count.toLocaleString('en-US');
27
+ }
28
+ function fitParts(parts, width) {
29
+ const fitted = parts.map(part => ({ ...part }));
30
+ const separator = ' | ';
31
+ const plain = () => fitted.map(part => part.text).join(separator);
32
+ while (fitted.length > 1 && visibleWidth(plain()) > width) {
33
+ const last = fitted[fitted.length - 1];
34
+ const otherWidth = visibleWidth(plain()) - visibleWidth(separator) - visibleWidth(last.text);
35
+ const available = width - otherWidth - visibleWidth(separator);
36
+ if (available > 0 && available < visibleWidth(last.text)) {
37
+ last.text = truncateToWidth(last.text, available, '', false);
38
+ if (visibleWidth(plain()) <= width)
39
+ return fitted;
40
+ }
41
+ fitted.pop();
42
+ }
43
+ if (fitted.length && visibleWidth(plain()) > width) {
44
+ fitted[0].text = truncateToWidth(fitted[0].text, width, '', false);
45
+ }
46
+ return fitted;
47
+ }
48
+ function color(theme, hex, text) {
49
+ return theme.style(text, { fg: parseColor(hex) });
50
+ }
51
+ export function renderStatusBand(state, width, theme) {
52
+ const size = Math.max(0, Math.floor(width));
53
+ if (!size)
54
+ return '';
55
+ const colors = palette(theme);
56
+ const model = state.model ? singleLine(state.model.name).replace(/^Claude /, '') || 'no-model' : 'no-model';
57
+ const account = singleLine(state.account ?? '') || 'account unknown';
58
+ const effort = singleLine(state.thinkingLevel) || 'off';
59
+ const parts = fitParts([
60
+ { text: displayProjectName(state.cwd), color: colors.brightAluminum },
61
+ { text: singleLine(state.branch ?? '') || '—', color: colors.readoutGreen },
62
+ { text: `${account} · ${model} · ${effort}`, color: colors.electricBlue },
63
+ { text: `↑ ${formatTokenCount(state.inputTokens)} ↓ ${formatTokenCount(state.outputTokens)}`, color: colors.titaniumGold }
64
+ ], size);
65
+ const separator = color(theme, colors.subtleGray, ' | ');
66
+ return parts.map(part => color(theme, part.color, part.text)).join(separator);
67
+ }