@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,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
+ }