p-spore 0.1.3 → 0.1.42

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 (396) hide show
  1. package/README.md +110 -15
  2. package/dist/agents/agent-manager.d.ts +3 -3
  3. package/dist/agents/agent-manager.d.ts.map +1 -1
  4. package/dist/agents/agent-manager.js +3 -2
  5. package/dist/agents/agent-manager.js.map +1 -1
  6. package/dist/application/agent-application.d.ts +29 -5
  7. package/dist/application/agent-application.d.ts.map +1 -1
  8. package/dist/application/agent-application.js +444 -14
  9. package/dist/application/agent-application.js.map +1 -1
  10. package/dist/articles/diff.d.ts +70 -0
  11. package/dist/articles/diff.d.ts.map +1 -0
  12. package/dist/articles/diff.js +330 -0
  13. package/dist/articles/diff.js.map +1 -0
  14. package/dist/articles/docx.d.ts +10 -0
  15. package/dist/articles/docx.d.ts.map +1 -0
  16. package/dist/articles/docx.js +219 -0
  17. package/dist/articles/docx.js.map +1 -0
  18. package/dist/articles/draft.d.ts +18 -0
  19. package/dist/articles/draft.d.ts.map +1 -0
  20. package/dist/articles/draft.js +88 -0
  21. package/dist/articles/draft.js.map +1 -0
  22. package/dist/articles/edits.d.ts +24 -0
  23. package/dist/articles/edits.d.ts.map +1 -0
  24. package/dist/articles/edits.js +54 -0
  25. package/dist/articles/edits.js.map +1 -0
  26. package/dist/articles/html.d.ts +10 -0
  27. package/dist/articles/html.d.ts.map +1 -0
  28. package/dist/articles/html.js +122 -0
  29. package/dist/articles/html.js.map +1 -0
  30. package/dist/articles/plain.d.ts +8 -0
  31. package/dist/articles/plain.d.ts.map +1 -0
  32. package/dist/articles/plain.js +69 -0
  33. package/dist/articles/plain.js.map +1 -0
  34. package/dist/articles/preview.d.ts +43 -0
  35. package/dist/articles/preview.d.ts.map +1 -0
  36. package/dist/articles/preview.js +90 -0
  37. package/dist/articles/preview.js.map +1 -0
  38. package/dist/articles/publish.d.ts +10 -0
  39. package/dist/articles/publish.d.ts.map +1 -0
  40. package/dist/articles/publish.js +54 -0
  41. package/dist/articles/publish.js.map +1 -0
  42. package/dist/articles/receipt.d.ts +16 -0
  43. package/dist/articles/receipt.d.ts.map +1 -0
  44. package/dist/articles/receipt.js +27 -0
  45. package/dist/articles/receipt.js.map +1 -0
  46. package/dist/articles/store.d.ts +78 -0
  47. package/dist/articles/store.d.ts.map +1 -0
  48. package/dist/articles/store.js +308 -0
  49. package/dist/articles/store.js.map +1 -0
  50. package/dist/articles/tool.d.ts +14 -0
  51. package/dist/articles/tool.d.ts.map +1 -0
  52. package/dist/articles/tool.js +175 -0
  53. package/dist/articles/tool.js.map +1 -0
  54. package/dist/articles/writer-context.d.ts +5 -0
  55. package/dist/articles/writer-context.d.ts.map +1 -0
  56. package/dist/articles/writer-context.js +56 -0
  57. package/dist/articles/writer-context.js.map +1 -0
  58. package/dist/articles/writer.d.ts +18 -0
  59. package/dist/articles/writer.d.ts.map +1 -0
  60. package/dist/articles/writer.js +79 -0
  61. package/dist/articles/writer.js.map +1 -0
  62. package/dist/articles/zip-write.d.ts +11 -0
  63. package/dist/articles/zip-write.d.ts.map +1 -0
  64. package/dist/articles/zip-write.js +63 -0
  65. package/dist/articles/zip-write.js.map +1 -0
  66. package/dist/bundled-skills/README.md +17 -0
  67. package/dist/bundled-skills/aegis-search/SKILL.md +59 -0
  68. package/dist/bundled-skills/aegis-search/bin/.gitkeep +0 -0
  69. package/dist/bundled-skills/article-canvas/SKILL.md +28 -0
  70. package/dist/bundled-skills/binaries.json +23 -0
  71. package/dist/bundled-skills/doc-extract/SKILL.md +56 -0
  72. package/dist/cli/main.d.ts.map +1 -1
  73. package/dist/cli/main.js +407 -54
  74. package/dist/cli/main.js.map +1 -1
  75. package/dist/config/config.d.ts +43 -0
  76. package/dist/config/config.d.ts.map +1 -1
  77. package/dist/config/config.js +150 -6
  78. package/dist/config/config.js.map +1 -1
  79. package/dist/daemon/daemon.d.ts.map +1 -1
  80. package/dist/daemon/daemon.js +80 -11
  81. package/dist/daemon/daemon.js.map +1 -1
  82. package/dist/desktop/application.d.ts +4 -0
  83. package/dist/desktop/application.d.ts.map +1 -0
  84. package/dist/desktop/application.js +1688 -0
  85. package/dist/desktop/application.js.map +1 -0
  86. package/dist/desktop/article-export.d.ts +12 -0
  87. package/dist/desktop/article-export.d.ts.map +1 -0
  88. package/dist/desktop/article-export.js +87 -0
  89. package/dist/desktop/article-export.js.map +1 -0
  90. package/dist/desktop/assets/pspore.png +0 -0
  91. package/dist/desktop/assets/pspore.svg +24 -0
  92. package/dist/desktop/conversation-smoke.d.ts +5 -0
  93. package/dist/desktop/conversation-smoke.d.ts.map +1 -0
  94. package/dist/desktop/conversation-smoke.js +93 -0
  95. package/dist/desktop/conversation-smoke.js.map +1 -0
  96. package/dist/desktop/daemon-bridge.d.ts.map +1 -1
  97. package/dist/desktop/daemon-bridge.js +62 -17
  98. package/dist/desktop/daemon-bridge.js.map +1 -1
  99. package/dist/desktop/ipc-contract.d.ts +124 -0
  100. package/dist/desktop/ipc-contract.d.ts.map +1 -1
  101. package/dist/desktop/ipc-contract.js +191 -12
  102. package/dist/desktop/ipc-contract.js.map +1 -1
  103. package/dist/desktop/local-path.d.ts +15 -0
  104. package/dist/desktop/local-path.d.ts.map +1 -0
  105. package/dist/desktop/local-path.js +59 -0
  106. package/dist/desktop/local-path.js.map +1 -0
  107. package/dist/desktop/main.d.ts +10 -1
  108. package/dist/desktop/main.d.ts.map +1 -1
  109. package/dist/desktop/main.js +122 -530
  110. package/dist/desktop/main.js.map +1 -1
  111. package/dist/desktop/native-startup.d.ts +4 -0
  112. package/dist/desktop/native-startup.d.ts.map +1 -0
  113. package/dist/desktop/native-startup.js +57 -0
  114. package/dist/desktop/native-startup.js.map +1 -0
  115. package/dist/desktop/preload.cjs +28 -1
  116. package/dist/desktop/renderer/article-panel.d.ts +45 -0
  117. package/dist/desktop/renderer/article-panel.d.ts.map +1 -0
  118. package/dist/desktop/renderer/article-panel.js +1126 -0
  119. package/dist/desktop/renderer/article-panel.js.map +1 -0
  120. package/dist/desktop/renderer/article-split.d.ts +32 -0
  121. package/dist/desktop/renderer/article-split.d.ts.map +1 -0
  122. package/dist/desktop/renderer/article-split.js +48 -0
  123. package/dist/desktop/renderer/article-split.js.map +1 -0
  124. package/dist/desktop/renderer/composer-file-references.d.ts +23 -0
  125. package/dist/desktop/renderer/composer-file-references.d.ts.map +1 -0
  126. package/dist/desktop/renderer/composer-file-references.js +51 -0
  127. package/dist/desktop/renderer/composer-file-references.js.map +1 -0
  128. package/dist/desktop/renderer/conversation.d.ts +23 -0
  129. package/dist/desktop/renderer/conversation.d.ts.map +1 -0
  130. package/dist/desktop/renderer/conversation.js +66 -0
  131. package/dist/desktop/renderer/conversation.js.map +1 -0
  132. package/dist/desktop/renderer/dom-reconcile.d.ts +15 -0
  133. package/dist/desktop/renderer/dom-reconcile.d.ts.map +1 -0
  134. package/dist/desktop/renderer/dom-reconcile.js +33 -0
  135. package/dist/desktop/renderer/dom-reconcile.js.map +1 -0
  136. package/dist/desktop/renderer/index.html +211 -34
  137. package/dist/desktop/renderer/indexing-view.d.ts +22 -0
  138. package/dist/desktop/renderer/indexing-view.d.ts.map +1 -0
  139. package/dist/desktop/renderer/indexing-view.js +115 -0
  140. package/dist/desktop/renderer/indexing-view.js.map +1 -0
  141. package/dist/desktop/renderer/markdown-view.d.ts +23 -0
  142. package/dist/desktop/renderer/markdown-view.d.ts.map +1 -0
  143. package/dist/desktop/renderer/markdown-view.js +436 -0
  144. package/dist/desktop/renderer/markdown-view.js.map +1 -0
  145. package/dist/desktop/renderer/motion.d.ts +67 -0
  146. package/dist/desktop/renderer/motion.d.ts.map +1 -0
  147. package/dist/desktop/renderer/motion.js +296 -0
  148. package/dist/desktop/renderer/motion.js.map +1 -0
  149. package/dist/desktop/renderer/renderer.js +1793 -155
  150. package/dist/desktop/renderer/renderer.js.map +1 -1
  151. package/dist/desktop/renderer/session-find.d.ts +18 -0
  152. package/dist/desktop/renderer/session-find.d.ts.map +1 -0
  153. package/dist/desktop/renderer/session-find.js +29 -0
  154. package/dist/desktop/renderer/session-find.js.map +1 -0
  155. package/dist/desktop/renderer/session-search.d.ts +30 -0
  156. package/dist/desktop/renderer/session-search.d.ts.map +1 -0
  157. package/dist/desktop/renderer/session-search.js +296 -0
  158. package/dist/desktop/renderer/session-search.js.map +1 -0
  159. package/dist/desktop/renderer/store.d.ts +35 -8
  160. package/dist/desktop/renderer/store.d.ts.map +1 -1
  161. package/dist/desktop/renderer/store.js +95 -78
  162. package/dist/desktop/renderer/store.js.map +1 -1
  163. package/dist/desktop/renderer/styles.css +910 -268
  164. package/dist/desktop/renderer/vendor/gsap.min.js +11 -0
  165. package/dist/desktop/renderer-diagnostics.d.ts +5 -0
  166. package/dist/desktop/renderer-diagnostics.d.ts.map +1 -0
  167. package/dist/desktop/renderer-diagnostics.js +47 -0
  168. package/dist/desktop/renderer-diagnostics.js.map +1 -0
  169. package/dist/desktop/security.d.ts +26 -1
  170. package/dist/desktop/security.d.ts.map +1 -1
  171. package/dist/desktop/security.js +26 -6
  172. package/dist/desktop/security.js.map +1 -1
  173. package/dist/desktop/smoke-fixture.d.ts.map +1 -1
  174. package/dist/desktop/smoke-fixture.js +77 -3
  175. package/dist/desktop/smoke-fixture.js.map +1 -1
  176. package/dist/desktop/splash/index.html +25 -0
  177. package/dist/desktop/splash/splash.d.ts +2 -0
  178. package/dist/desktop/splash/splash.d.ts.map +1 -0
  179. package/dist/desktop/splash/splash.js +8 -0
  180. package/dist/desktop/splash/splash.js.map +1 -0
  181. package/dist/desktop/splash/styles.css +24 -0
  182. package/dist/desktop/system-open.d.ts +16 -0
  183. package/dist/desktop/system-open.d.ts.map +1 -0
  184. package/dist/desktop/system-open.js +90 -0
  185. package/dist/desktop/system-open.js.map +1 -0
  186. package/dist/desktop/validation.d.ts.map +1 -1
  187. package/dist/desktop/validation.js +99 -21
  188. package/dist/desktop/validation.js.map +1 -1
  189. package/dist/desktop/window-security.d.ts +4 -0
  190. package/dist/desktop/window-security.d.ts.map +1 -0
  191. package/dist/desktop/window-security.js +26 -0
  192. package/dist/desktop/window-security.js.map +1 -0
  193. package/dist/documents/errors.d.ts +12 -0
  194. package/dist/documents/errors.d.ts.map +1 -0
  195. package/dist/documents/errors.js +12 -0
  196. package/dist/documents/errors.js.map +1 -0
  197. package/dist/documents/extract.d.ts +37 -0
  198. package/dist/documents/extract.d.ts.map +1 -0
  199. package/dist/documents/extract.js +90 -0
  200. package/dist/documents/extract.js.map +1 -0
  201. package/dist/documents/legacy-office.d.ts +23 -0
  202. package/dist/documents/legacy-office.d.ts.map +1 -0
  203. package/dist/documents/legacy-office.js +439 -0
  204. package/dist/documents/legacy-office.js.map +1 -0
  205. package/dist/documents/ole.d.ts +20 -0
  206. package/dist/documents/ole.d.ts.map +1 -0
  207. package/dist/documents/ole.js +189 -0
  208. package/dist/documents/ole.js.map +1 -0
  209. package/dist/documents/ooxml.d.ts +23 -0
  210. package/dist/documents/ooxml.d.ts.map +1 -0
  211. package/dist/documents/ooxml.js +197 -0
  212. package/dist/documents/ooxml.js.map +1 -0
  213. package/dist/documents/pdf.d.ts +20 -0
  214. package/dist/documents/pdf.d.ts.map +1 -0
  215. package/dist/documents/pdf.js +95 -0
  216. package/dist/documents/pdf.js.map +1 -0
  217. package/dist/documents/plain-text.d.ts +22 -0
  218. package/dist/documents/plain-text.d.ts.map +1 -0
  219. package/dist/documents/plain-text.js +57 -0
  220. package/dist/documents/plain-text.js.map +1 -0
  221. package/dist/documents/zip.d.ts +15 -0
  222. package/dist/documents/zip.d.ts.map +1 -0
  223. package/dist/documents/zip.js +137 -0
  224. package/dist/documents/zip.js.map +1 -0
  225. package/dist/domain/indexing.d.ts +60 -0
  226. package/dist/domain/indexing.d.ts.map +1 -0
  227. package/dist/domain/indexing.js +13 -0
  228. package/dist/domain/indexing.js.map +1 -0
  229. package/dist/domain/runtime.d.ts +133 -5
  230. package/dist/domain/runtime.d.ts.map +1 -1
  231. package/dist/gateway/local-gateway.d.ts +8 -0
  232. package/dist/gateway/local-gateway.d.ts.map +1 -1
  233. package/dist/gateway/local-gateway.js +105 -21
  234. package/dist/gateway/local-gateway.js.map +1 -1
  235. package/dist/indexing/index-service.d.ts +56 -0
  236. package/dist/indexing/index-service.d.ts.map +1 -0
  237. package/dist/indexing/index-service.js +262 -0
  238. package/dist/indexing/index-service.js.map +1 -0
  239. package/dist/kernel/loop.d.ts +10 -0
  240. package/dist/kernel/loop.d.ts.map +1 -1
  241. package/dist/kernel/loop.js +6 -2
  242. package/dist/kernel/loop.js.map +1 -1
  243. package/dist/kernel/reducer.d.ts.map +1 -1
  244. package/dist/kernel/reducer.js +17 -1
  245. package/dist/kernel/reducer.js.map +1 -1
  246. package/dist/kernel/state.d.ts +17 -4
  247. package/dist/kernel/state.d.ts.map +1 -1
  248. package/dist/kernel/state.js +2 -0
  249. package/dist/kernel/state.js.map +1 -1
  250. package/dist/memory/memory-tools.d.ts.map +1 -1
  251. package/dist/memory/memory-tools.js +25 -5
  252. package/dist/memory/memory-tools.js.map +1 -1
  253. package/dist/pi/context-budget.d.ts +8 -0
  254. package/dist/pi/context-budget.d.ts.map +1 -0
  255. package/dist/pi/context-budget.js +62 -0
  256. package/dist/pi/context-budget.js.map +1 -0
  257. package/dist/pi/pi-runtime-adapter.d.ts +38 -3
  258. package/dist/pi/pi-runtime-adapter.d.ts.map +1 -1
  259. package/dist/pi/pi-runtime-adapter.js +551 -56
  260. package/dist/pi/pi-runtime-adapter.js.map +1 -1
  261. package/dist/plugins/bundled-skills.d.ts +56 -0
  262. package/dist/plugins/bundled-skills.d.ts.map +1 -0
  263. package/dist/plugins/bundled-skills.js +243 -0
  264. package/dist/plugins/bundled-skills.js.map +1 -0
  265. package/dist/plugins/extension-manager.d.ts +23 -1
  266. package/dist/plugins/extension-manager.d.ts.map +1 -1
  267. package/dist/plugins/extension-manager.js +117 -0
  268. package/dist/plugins/extension-manager.js.map +1 -1
  269. package/dist/plugins/types.d.ts +29 -0
  270. package/dist/plugins/types.d.ts.map +1 -1
  271. package/dist/plugins/workspace-skills.d.ts +36 -0
  272. package/dist/plugins/workspace-skills.d.ts.map +1 -0
  273. package/dist/plugins/workspace-skills.js +309 -0
  274. package/dist/plugins/workspace-skills.js.map +1 -0
  275. package/dist/policy/policy.d.ts.map +1 -1
  276. package/dist/policy/policy.js +26 -4
  277. package/dist/policy/policy.js.map +1 -1
  278. package/dist/protocol/client.d.ts +1 -0
  279. package/dist/protocol/client.d.ts.map +1 -1
  280. package/dist/protocol/client.js +49 -24
  281. package/dist/protocol/client.js.map +1 -1
  282. package/dist/protocol/limits.d.ts +69 -0
  283. package/dist/protocol/limits.d.ts.map +1 -0
  284. package/dist/protocol/limits.js +166 -0
  285. package/dist/protocol/limits.js.map +1 -0
  286. package/dist/protocol/schema.d.ts +6 -0
  287. package/dist/protocol/schema.d.ts.map +1 -1
  288. package/dist/protocol/schema.js.map +1 -1
  289. package/dist/protocol/server-frame-codec.d.ts +18 -0
  290. package/dist/protocol/server-frame-codec.d.ts.map +1 -0
  291. package/dist/protocol/server-frame-codec.js +211 -0
  292. package/dist/protocol/server-frame-codec.js.map +1 -0
  293. package/dist/service/legacy-daemon.d.ts +6 -0
  294. package/dist/service/legacy-daemon.d.ts.map +1 -0
  295. package/dist/service/legacy-daemon.js +42 -0
  296. package/dist/service/legacy-daemon.js.map +1 -0
  297. package/dist/service/service-launch.d.ts +10 -0
  298. package/dist/service/service-launch.d.ts.map +1 -0
  299. package/dist/service/service-launch.js +56 -0
  300. package/dist/service/service-launch.js.map +1 -0
  301. package/dist/service/system-service.d.ts +57 -0
  302. package/dist/service/system-service.d.ts.map +1 -0
  303. package/dist/service/system-service.js +263 -0
  304. package/dist/service/system-service.js.map +1 -0
  305. package/dist/sessions/session-catalog.d.ts +45 -0
  306. package/dist/sessions/session-catalog.d.ts.map +1 -0
  307. package/dist/sessions/session-catalog.js +270 -0
  308. package/dist/sessions/session-catalog.js.map +1 -0
  309. package/dist/sessions/session-file.d.ts +12 -0
  310. package/dist/sessions/session-file.d.ts.map +1 -0
  311. package/dist/sessions/session-file.js +47 -0
  312. package/dist/sessions/session-file.js.map +1 -0
  313. package/dist/settings/compaction-settings.d.ts +10 -0
  314. package/dist/settings/compaction-settings.d.ts.map +1 -0
  315. package/dist/settings/compaction-settings.js +8 -0
  316. package/dist/settings/compaction-settings.js.map +1 -0
  317. package/dist/settings/indexing-settings-service.d.ts +16 -0
  318. package/dist/settings/indexing-settings-service.d.ts.map +1 -0
  319. package/dist/settings/indexing-settings-service.js +57 -0
  320. package/dist/settings/indexing-settings-service.js.map +1 -0
  321. package/dist/settings/indexing-settings.d.ts +30 -0
  322. package/dist/settings/indexing-settings.d.ts.map +1 -0
  323. package/dist/settings/indexing-settings.js +58 -0
  324. package/dist/settings/indexing-settings.js.map +1 -0
  325. package/dist/settings/llm-settings-service.d.ts +6 -0
  326. package/dist/settings/llm-settings-service.d.ts.map +1 -1
  327. package/dist/settings/llm-settings-service.js +137 -12
  328. package/dist/settings/llm-settings-service.js.map +1 -1
  329. package/dist/settings/llm-settings.d.ts +68 -2
  330. package/dist/settings/llm-settings.d.ts.map +1 -1
  331. package/dist/settings/llm-settings.js +119 -17
  332. package/dist/settings/llm-settings.js.map +1 -1
  333. package/dist/settings/model-api.d.ts +10 -0
  334. package/dist/settings/model-api.d.ts.map +1 -0
  335. package/dist/settings/model-api.js +10 -0
  336. package/dist/settings/model-api.js.map +1 -0
  337. package/dist/storage/home.d.ts +1 -0
  338. package/dist/storage/home.d.ts.map +1 -1
  339. package/dist/storage/home.js +37 -2
  340. package/dist/storage/home.js.map +1 -1
  341. package/dist/tools/core-tools.d.ts +2 -0
  342. package/dist/tools/core-tools.d.ts.map +1 -1
  343. package/dist/tools/core-tools.js +91 -1
  344. package/dist/tools/core-tools.js.map +1 -1
  345. package/dist/ui/shared/activity.d.ts +27 -0
  346. package/dist/ui/shared/activity.d.ts.map +1 -0
  347. package/dist/ui/shared/activity.js +384 -0
  348. package/dist/ui/shared/activity.js.map +1 -0
  349. package/dist/ui/shared/full-message.d.ts +22 -0
  350. package/dist/ui/shared/full-message.d.ts.map +1 -0
  351. package/dist/ui/shared/full-message.js +40 -0
  352. package/dist/ui/shared/full-message.js.map +1 -0
  353. package/dist/ui/shared/local-links.d.ts +7 -0
  354. package/dist/ui/shared/local-links.d.ts.map +1 -0
  355. package/dist/ui/shared/local-links.js +24 -0
  356. package/dist/ui/shared/local-links.js.map +1 -0
  357. package/dist/ui/shared/markdown-stream.d.ts +25 -0
  358. package/dist/ui/shared/markdown-stream.d.ts.map +1 -0
  359. package/dist/ui/shared/markdown-stream.js +35 -0
  360. package/dist/ui/shared/markdown-stream.js.map +1 -0
  361. package/dist/ui/shared/markdown.d.ts +70 -0
  362. package/dist/ui/shared/markdown.d.ts.map +1 -0
  363. package/dist/ui/shared/markdown.js +434 -0
  364. package/dist/ui/shared/markdown.js.map +1 -0
  365. package/dist/ui/shared/presentation.d.ts +10 -2
  366. package/dist/ui/shared/presentation.d.ts.map +1 -1
  367. package/dist/ui/shared/presentation.js +83 -22
  368. package/dist/ui/shared/presentation.js.map +1 -1
  369. package/dist/ui/shared/protocol-state.d.ts +19 -0
  370. package/dist/ui/shared/protocol-state.d.ts.map +1 -1
  371. package/dist/ui/shared/protocol-state.js +188 -26
  372. package/dist/ui/shared/protocol-state.js.map +1 -1
  373. package/dist/ui/shared/virtual-list.d.ts +34 -0
  374. package/dist/ui/shared/virtual-list.d.ts.map +1 -0
  375. package/dist/ui/shared/virtual-list.js +143 -0
  376. package/dist/ui/shared/virtual-list.js.map +1 -0
  377. package/dist/ui/tui/commands.d.ts +1 -1
  378. package/dist/ui/tui/commands.d.ts.map +1 -1
  379. package/dist/ui/tui/commands.js +9 -3
  380. package/dist/ui/tui/commands.js.map +1 -1
  381. package/dist/ui/tui/store.d.ts +26 -0
  382. package/dist/ui/tui/store.d.ts.map +1 -1
  383. package/dist/ui/tui/store.js +67 -3
  384. package/dist/ui/tui/store.js.map +1 -1
  385. package/dist/ui/tui/tui-app.d.ts.map +1 -1
  386. package/dist/ui/tui/tui-app.js +316 -38
  387. package/dist/ui/tui/tui-app.js.map +1 -1
  388. package/dist/ui/tui/view.d.ts +10 -0
  389. package/dist/ui/tui/view.d.ts.map +1 -1
  390. package/dist/ui/tui/view.js +253 -49
  391. package/dist/ui/tui/view.js.map +1 -1
  392. package/dist/version.d.ts +1 -1
  393. package/dist/version.d.ts.map +1 -1
  394. package/dist/version.js +1 -1
  395. package/dist/version.js.map +1 -1
  396. package/package.json +13 -2
@@ -1,17 +1,18 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { ProcessTerminal, TuiAltScreen } from "@earendil-works/pi-tui";
3
3
  import { ProtocolClient } from "../../protocol/client.js";
4
- import { decodeLlmSettingsUpdate, defaultModelFor, MODEL_APIS, PROVIDER_OPTIONS, THINKING_LEVELS, } from "../../settings/llm-settings.js";
4
+ import { BYPASS_PERMISSION_MODE, decodeLlmSettingsUpdate, defaultModelFor, MODEL_APIS, PERMISSION_MODES, permissionModeSummary, PROVIDER_OPTIONS, THINKING_LEVELS, } from "../../settings/llm-settings.js";
5
5
  import { TuiStore } from "./store.js";
6
6
  import { TUI_HELP_LINES } from "./commands.js";
7
7
  import { PsporeTuiView } from "./view.js";
8
+ import { activityDetailLines } from "../shared/activity.js";
8
9
  import { conversationIntent, selectedAgent } from "../shared/presentation.js";
9
10
  export const MODEL_SETUP_OFFER_PROMPT = "Run the model setup wizard now? [Y/n]";
10
11
  export const MODEL_SETUP_OFFER_LINES = [
11
12
  "No model is configured yet, so prompts would fail with model_not_configured.",
12
13
  "",
13
- "The wizard walks through provider, model, thinking level and API key.",
14
- "The key is stored in a private 0600 file and is never shown in the TUI.",
14
+ "The wizard walks through provider, model, thinking, API key and optional proxy cookie.",
15
+ "The key and cookie are stored in private 0600 files and are never shown in the TUI.",
15
16
  "",
16
17
  "Answer n to skip; you can run /config wizard at any time.",
17
18
  ];
@@ -22,6 +23,8 @@ export function acceptsModelSetupOffer(answer) {
22
23
  const normalized = answer.trim().toLowerCase();
23
24
  return normalized === "" || normalized === "y" || normalized === "yes";
24
25
  }
26
+ /** How many older messages one scrollback request asks for. */
27
+ const HISTORY_PAGE_SIZE = 200;
25
28
  export class PsporeTuiApp {
26
29
  #options;
27
30
  #store = new TuiStore();
@@ -31,8 +34,10 @@ export class PsporeTuiApp {
31
34
  #client;
32
35
  #stopping = false;
33
36
  #retryTimer;
37
+ #settleTimer;
34
38
  #retryMs = 250;
35
39
  #lastInterruptAt = 0;
40
+ #loadingHistory = false;
36
41
  #resolveExit;
37
42
  #view;
38
43
  constructor(options) {
@@ -47,12 +52,14 @@ export class PsporeTuiApp {
47
52
  onSubmit: (input) => void this.#submit(input),
48
53
  onInterrupt: () => void this.#interrupt(),
49
54
  onBack: () => this.#store.clearPanel(),
55
+ onScrollBack: () => void this.#loadOlderHistory(),
50
56
  });
51
57
  this.#view = view;
52
58
  this.#tui.setLayoutRoot(view);
53
59
  this.#tui.setFocus(view);
54
60
  this.#tui.start();
55
61
  void this.#connect();
62
+ void this.#refreshConfiguredModel();
56
63
  void this.#offerModelSetup();
57
64
  try {
58
65
  await new Promise((resolve) => {
@@ -63,7 +70,10 @@ export class PsporeTuiApp {
63
70
  this.#stopping = true;
64
71
  if (this.#retryTimer)
65
72
  clearTimeout(this.#retryTimer);
73
+ if (this.#settleTimer)
74
+ clearTimeout(this.#settleTimer);
66
75
  await this.#client?.close().catch(() => undefined);
76
+ this.#view?.dispose();
67
77
  this.#tui.stop();
68
78
  this.#view = undefined;
69
79
  await this.#terminal.drainInput(250, 25);
@@ -90,6 +100,7 @@ export class PsporeTuiApp {
90
100
  if (connected)
91
101
  return;
92
102
  this.#store.disconnected(error?.message ?? "Disconnected");
103
+ this.#scheduleSettle();
93
104
  this.#tui.requestRender();
94
105
  this.#scheduleReconnect();
95
106
  });
@@ -105,10 +116,50 @@ export class PsporeTuiApp {
105
116
  }
106
117
  catch (error) {
107
118
  this.#store.disconnected(`Daemon unavailable: ${toError(error).message}`);
119
+ this.#scheduleSettle();
108
120
  this.#tui.requestRender();
109
121
  this.#scheduleReconnect();
110
122
  }
111
123
  }
124
+ /**
125
+ * Fetches the page of history before the oldest message this client holds.
126
+ * The daemon broadcasts only a bounded tail, so scrollback is a request.
127
+ */
128
+ async #loadOlderHistory() {
129
+ if (this.#loadingHistory)
130
+ return;
131
+ const state = this.#store.snapshot();
132
+ const sessionId = state.selectedSessionId;
133
+ const session = state.kernel.sessions[sessionId];
134
+ if (!session || session.messageOffset === 0)
135
+ return;
136
+ const from = Math.max(0, session.messageOffset - HISTORY_PAGE_SIZE);
137
+ this.#loadingHistory = true;
138
+ try {
139
+ const page = await this.#command("session.transcript", { from, limit: session.messageOffset - from }, sessionId);
140
+ if (this.#store.applyTranscriptPage(page))
141
+ this.#tui.requestRender();
142
+ }
143
+ catch (error) {
144
+ this.#store.setNotice(`Could not load older history: ${toError(error).message}`);
145
+ }
146
+ finally {
147
+ this.#loadingHistory = false;
148
+ }
149
+ }
150
+ /** Surfaces a genuine outage once the store's masking window expires. */
151
+ #scheduleSettle() {
152
+ if (this.#stopping || this.#settleTimer)
153
+ return;
154
+ this.#settleTimer = setTimeout(() => {
155
+ this.#settleTimer = undefined;
156
+ if (this.#store.settleConnection())
157
+ this.#tui.requestRender();
158
+ else if (this.#store.snapshot().reconnecting)
159
+ this.#scheduleSettle();
160
+ }, 250);
161
+ this.#settleTimer.unref();
162
+ }
112
163
  #scheduleReconnect() {
113
164
  if (this.#stopping || this.#retryTimer)
114
165
  return;
@@ -130,6 +181,10 @@ export class PsporeTuiApp {
130
181
  this.#store.setPanel("Command palette", TUI_HELP_LINES);
131
182
  return;
132
183
  }
184
+ if (input === "/work" || input.startsWith("/work ")) {
185
+ this.#showWork(input.slice(5).trim());
186
+ return;
187
+ }
133
188
  if (input === "/back") {
134
189
  this.#store.clearPanel();
135
190
  return;
@@ -138,22 +193,54 @@ export class PsporeTuiApp {
138
193
  await this.#config(input);
139
194
  return;
140
195
  }
196
+ if (input === "/new" || input.startsWith("/new ")) {
197
+ const title = input.slice(4).trim();
198
+ const session = await this.#command("session.create", title ? { title } : {});
199
+ this.#store.selectSession(session.sessionId);
200
+ this.#store.setNotice(`New session ${session.sessionId}`);
201
+ return;
202
+ }
203
+ if (input === "/delete" || input.startsWith("/delete ")) {
204
+ const requested = input.slice(7).trim();
205
+ const sessionId = requested || this.#store.snapshot().selectedSessionId;
206
+ if (this.#selectedAgent() && !requested) {
207
+ throw new Error("Only a root session can be deleted; use /agent-cancel for a child agent");
208
+ }
209
+ // Deleting also removes the transcript, so the id is echoed back rather
210
+ // than silently acting on whatever happened to be selected.
211
+ const deleted = await this.#command("session.delete", {}, sessionId);
212
+ this.#store.setNotice(`Deleted session ${deleted.sessionId}${deleted.title ? ` (${deleted.title})` : ""}`
213
+ + `${deleted.transcriptRemoved ? " and its transcript" : ""}`);
214
+ return;
215
+ }
141
216
  if (input === "/abort") {
217
+ const selectedSessionId = this.#store.snapshot().selectedSessionId;
142
218
  const child = this.#selectedAgent();
143
219
  if (child)
144
220
  await this.#command("agent.cancel", { agentId: child.id, reason: "cancelled from TUI" });
145
221
  else
146
- await this.#command("session.abort", { reason: "TUI user requested abort" }, "main");
222
+ await this.#command("session.abort", { reason: "TUI user requested abort" }, selectedSessionId);
147
223
  this.#store.setNotice(child ? `Agent ${child.id} cancelled` : "Abort requested");
148
224
  return;
149
225
  }
150
226
  if (input === "/compact") {
151
227
  if (this.#selectedAgent())
152
- throw new Error("Compaction is available only for the main session");
153
- await this.#command("session.compact", {}, "main");
228
+ throw new Error("Compaction is available only for a root session");
229
+ await this.#command("session.compact", {}, this.#store.snapshot().selectedSessionId);
154
230
  this.#store.setNotice("Compaction requested");
155
231
  return;
156
232
  }
233
+ if (input.startsWith("/send-now ")) {
234
+ if (this.#selectedAgent())
235
+ throw new Error("Queued root-session messages are unavailable for a child agent");
236
+ const displayIndex = Number(input.slice(10).trim());
237
+ if (!Number.isSafeInteger(displayIndex) || displayIndex < 1)
238
+ throw new Error("Usage: /send-now QUEUE_NUMBER");
239
+ const sessionId = this.#store.snapshot().selectedSessionId;
240
+ await this.#command("session.queue.send-now", { index: displayIndex - 1 }, sessionId);
241
+ this.#store.setNotice("直接发送消息");
242
+ return;
243
+ }
157
244
  if (input === "/jobs") {
158
245
  const jobs = await this.#command("jobs.list", {});
159
246
  this.#store.setPanel("Automation jobs", jobs.map((job) => (`• ${job.id} · ${job.enabled ? "enabled" : "disabled"}${job.schedule?.cron ? ` · ${job.schedule.cron} ${job.schedule.timezone ?? ""}` : ""}`)));
@@ -204,10 +291,18 @@ export class PsporeTuiApp {
204
291
  ]);
205
292
  return;
206
293
  }
207
- if (input === "/resources" || input === "/skills" || input === "/plugins") {
208
- const command = input === "/skills" ? "skills.list" : input === "/plugins" ? "plugins.list" : "resources.list";
294
+ if (input === "/skills") {
295
+ const skills = await this.#command("skills.catalog", {});
296
+ this.#store.setPanel("Skills", skills.length === 0 ? ["No skills found"] : skills.flatMap((skill) => [
297
+ `• ${skill.name} · ${skill.source} · ${skill.status}`,
298
+ ...(skill.message ? [` ${skill.message}`] : []),
299
+ ]));
300
+ return;
301
+ }
302
+ if (input === "/resources" || input === "/plugins") {
303
+ const command = input === "/plugins" ? "plugins.list" : "resources.list";
209
304
  const resources = await this.#command(command, {});
210
- this.#store.setPanel(input === "/skills" ? "Skills" : input === "/plugins" ? "Host plugins" : "Trusted resources", resources.map((resource) => (`• ${resource.record.kind} · ${resource.record.name} · ${resource.health.status}`)));
305
+ this.#store.setPanel(input === "/plugins" ? "Host plugins" : "Trusted resources", resources.map((resource) => (`• ${resource.record.kind} · ${resource.record.name} · ${resource.health.status}`)));
211
306
  return;
212
307
  }
213
308
  if (input.startsWith("/resource-inspect ")) {
@@ -252,8 +347,10 @@ export class PsporeTuiApp {
252
347
  const objective = input.slice(13).trim();
253
348
  if (!objective)
254
349
  throw new Error("Usage: /agent-spawn OBJECTIVE");
350
+ const snapshot = this.#store.snapshot();
351
+ const parentId = selectedAgent(snapshot.kernel, snapshot.selectedSessionId)?.rootId ?? snapshot.selectedSessionId;
255
352
  const agent = await this.#command("agent.spawn", {
256
- parentId: "main",
353
+ parentId,
257
354
  objective,
258
355
  workspaceMode: "shared-read",
259
356
  budget: {
@@ -314,13 +411,7 @@ export class PsporeTuiApp {
314
411
  await this.#approval(input);
315
412
  return;
316
413
  }
317
- const child = this.#selectedAgent();
318
- const main = this.#store.snapshot().kernel.sessions["main"];
319
- if (!child && main?.status === "running") {
320
- this.#store.setNotice("Session is running; use /steer TEXT or /follow TEXT explicitly");
321
- return;
322
- }
323
- await this.#prompt(input, "prompt");
414
+ await this.#prompt(input, "auto");
324
415
  }
325
416
  catch (error) {
326
417
  this.#store.setNotice(`Error: ${toError(error).message}`);
@@ -342,7 +433,8 @@ export class PsporeTuiApp {
342
433
  return;
343
434
  }
344
435
  await this.#command("session.prompt", { text: intent.text, mode: intent.mode }, intent.sessionId);
345
- this.#store.setNotice(`${mode} accepted for main`);
436
+ const queued = this.#store.snapshot().kernel.sessions[intent.sessionId]?.status === "running" && mode === "auto";
437
+ this.#store.setNotice(queued ? "继续排队" : `Message accepted for ${intent.sessionId}`);
346
438
  }
347
439
  async #approval(input) {
348
440
  const parts = input.split(/\s+/);
@@ -446,6 +538,38 @@ export class PsporeTuiApp {
446
538
  await this.#saveSettings(updateFrom(current, { thinking: parseThinking(parts[2]) }));
447
539
  return;
448
540
  }
541
+ if (action === "permissions") {
542
+ if (parts.length !== 3)
543
+ throw new Error(`Usage: /config permissions ${PERMISSION_MODES.join("|")}|bypass`);
544
+ const permissionMode = parsePermissionMode(parts[2]);
545
+ await this.#saveSettings(updateFrom(current, { permissionMode }));
546
+ if (permissionMode === BYPASS_PERMISSION_MODE) {
547
+ this.#store.setNotice("Permissions bypassed: tools now run with your own privileges and no confirmation");
548
+ }
549
+ return;
550
+ }
551
+ if (action === "compact") {
552
+ if (parts.length < 3 || parts.length > 6) {
553
+ throw new Error("Usage: /config compact on|off [RESERVE_TOKENS] [KEEP_RECENT_TOKENS] [TRIGGER_TOKENS]");
554
+ }
555
+ const enabled = parseOnOff(parts[2], "/config compact");
556
+ const reserveTokens = parts[3] === undefined
557
+ ? current.autoCompactionReserveTokens
558
+ : parseCompactionTokens(parts[3], "reserve tokens");
559
+ const keepRecentTokens = parts[4] === undefined
560
+ ? current.autoCompactionKeepRecentTokens
561
+ : parseCompactionTokens(parts[4], "keep recent tokens");
562
+ const triggerTokens = parts[5] === undefined
563
+ ? current.autoCompactionTriggerTokens
564
+ : parseCompactionTokens(parts[5], "trigger tokens");
565
+ await this.#saveSettings(updateFrom(current, {
566
+ autoCompactionEnabled: enabled,
567
+ autoCompactionTriggerTokens: triggerTokens,
568
+ autoCompactionReserveTokens: reserveTokens,
569
+ autoCompactionKeepRecentTokens: keepRecentTokens,
570
+ }));
571
+ return;
572
+ }
449
573
  if (action === "key") {
450
574
  if (parts.length !== 2)
451
575
  throw new Error("API keys are never accepted as command arguments; use /config key");
@@ -465,6 +589,25 @@ export class PsporeTuiApp {
465
589
  await this.#saveSettings(updateFrom(current, { clearApiKey: true }));
466
590
  return;
467
591
  }
592
+ if (action === "cookie") {
593
+ if (parts.length !== 2)
594
+ throw new Error("Cookies are never accepted as command arguments; use /config cookie");
595
+ const cookie = await this.#view?.requestValue("Cookie (hidden; Esc cancels)", { secret: true });
596
+ if (cookie === undefined) {
597
+ this.#store.setNotice("Cookie update cancelled");
598
+ return;
599
+ }
600
+ if (!cookie)
601
+ throw new Error("Cookie cannot be empty");
602
+ await this.#saveSettings(updateFrom(current, { cookie }));
603
+ return;
604
+ }
605
+ if (action === "clear-cookie") {
606
+ if (parts.length !== 2)
607
+ throw new Error("Usage: /config clear-cookie");
608
+ await this.#saveSettings(updateFrom(current, { clearCookie: true }));
609
+ return;
610
+ }
468
611
  throw new Error("Unknown config action; use /config, /config wizard, or /help");
469
612
  }
470
613
  /**
@@ -505,44 +648,61 @@ export class PsporeTuiApp {
505
648
  if (!settingsPort || !view)
506
649
  throw new Error("Settings wizard is unavailable");
507
650
  const current = await settingsPort.get();
508
- this.#store.setPanel("Model setup wizard", [
509
- "1 Provider — DeepSeek, OpenAI, or custom OpenAI",
510
- "2 Model",
511
- "3 Endpoint/API when custom",
512
- "4 Thinking level",
513
- "5 API key action",
514
- "6 Review and apply",
515
- "",
516
- "Press Esc at any prompt to cancel without saving.",
651
+ this.#showWizardStep(1, "Choose a provider", [
652
+ `1 DeepSeek ${current.provider === "deepseek" ? "← current" : ""}`,
653
+ `2 OpenAI ${current.provider === "openai" ? "← current" : ""}`,
654
+ `3 Custom OpenAI ${current.provider === "custom-openai" ? "← current" : ""}`,
517
655
  ]);
518
- const providerValue = await view.requestValue(`1/6 provider [${current.provider}] (1 deepseek · 2 openai · 3 custom)`);
656
+ const providerValue = await view.requestValue(`1/7 provider [${current.provider}] (1 deepseek · 2 openai · 3 custom)`);
519
657
  if (providerValue === undefined)
520
658
  return this.#cancelWizard();
521
659
  const provider = providerValue.trim() ? parseProvider(providerValue) : current.provider;
522
660
  const suggestedModel = provider === current.provider ? current.model : defaultModelFor(provider);
523
- const modelValue = await view.requestValue(`2/6 model [${suggestedModel}]`);
661
+ this.#showWizardStep(2, "Choose a model", [
662
+ `Provider ${provider}`,
663
+ `Suggested ${suggestedModel}`,
664
+ "Press Enter to accept the suggestion, or type another model ID.",
665
+ ]);
666
+ const modelValue = await view.requestValue(`2/7 model [${suggestedModel}]`);
524
667
  if (modelValue === undefined)
525
668
  return this.#cancelWizard();
526
669
  const model = modelValue.trim() || suggestedModel;
527
670
  let baseUrl = "";
528
671
  let api = "provider-default";
529
672
  if (provider === "custom-openai") {
530
- const baseUrlValue = await view.requestValue(`3/6 Base URL [${current.provider === provider ? current.baseUrl : "required"}]`);
673
+ this.#showWizardStep(3, "Connect an OpenAI-compatible endpoint", [
674
+ `Current URL ${current.provider === provider ? current.baseUrl || "not set" : "not set"}`,
675
+ "The URL must use HTTP(S) and cannot contain credentials.",
676
+ "API compatibility can be Chat Completions or Responses.",
677
+ ]);
678
+ const baseUrlValue = await view.requestValue(`3/7 Base URL [${current.provider === provider ? current.baseUrl : "required"}]`);
531
679
  if (baseUrlValue === undefined)
532
680
  return this.#cancelWizard();
533
681
  baseUrl = baseUrlValue.trim() || (current.provider === provider ? current.baseUrl : "");
534
682
  if (!baseUrl)
535
683
  throw new Error("A Base URL is required for custom OpenAI");
536
- const apiValue = await view.requestValue("3/6 API [chat] (chat · responses)");
684
+ const apiValue = await view.requestValue("3/7 API [chat] (chat · responses)");
537
685
  if (apiValue === undefined)
538
686
  return this.#cancelWizard();
539
687
  api = parseOpenAiApi(apiValue.trim() || (current.provider === provider ? current.api : "chat"));
540
688
  }
541
- const thinkingValue = await view.requestValue(`4/6 thinking [${current.thinking}] (${THINKING_LEVELS.join(" · ")})`);
689
+ this.#showWizardStep(4, "Choose thinking effort", [
690
+ `Current ${current.thinking}`,
691
+ `Options ${THINKING_LEVELS.join(" · ")}`,
692
+ "Higher effort can increase latency and token use when the provider supports it.",
693
+ ]);
694
+ const thinkingValue = await view.requestValue(`4/7 thinking [${current.thinking}] (${THINKING_LEVELS.join(" · ")})`);
542
695
  if (thinkingValue === undefined)
543
696
  return this.#cancelWizard();
544
697
  const thinking = parseThinking(thinkingValue.trim() || current.thinking);
545
- const keyActionValue = await view.requestValue(`5/6 key [keep] (keep · set · clear)`);
698
+ this.#showWizardStep(5, "Manage the API key", [
699
+ `Status ${current.hasApiKey ? "configured (hidden)" : "not configured"}`,
700
+ `File ${current.apiKeyPath}`,
701
+ "keep Leave the managed key unchanged",
702
+ "set Enter a new key through hidden input",
703
+ "clear Remove the managed key",
704
+ ]);
705
+ const keyActionValue = await view.requestValue(`5/7 key [keep] (keep · set · clear)`);
546
706
  if (keyActionValue === undefined)
547
707
  return this.#cancelWizard();
548
708
  const keyAction = keyActionValue.trim().toLowerCase() || "keep";
@@ -551,23 +711,46 @@ export class PsporeTuiApp {
551
711
  }
552
712
  let apiKey;
553
713
  if (keyAction === "set") {
554
- apiKey = await view.requestValue("5/6 API key (hidden; Esc cancels)", { secret: true });
714
+ apiKey = await view.requestValue("5/7 API key (hidden; Esc cancels)", { secret: true });
555
715
  if (apiKey === undefined)
556
716
  return this.#cancelWizard();
557
717
  if (!apiKey)
558
718
  throw new Error("API key cannot be empty");
559
719
  }
560
- this.#store.setPanel("Review model settings", [
720
+ this.#showWizardStep(6, "Optional LLM proxy cookie", [
721
+ `Status ${current.hasCookie ? "configured (hidden)" : "not configured"}`,
722
+ `File ${current.cookiePath}`,
723
+ "keep Leave the managed cookie unchanged",
724
+ "set Enter a Cookie header through hidden input",
725
+ "clear Remove the managed cookie",
726
+ ]);
727
+ const cookieActionValue = await view.requestValue(`6/7 cookie [keep] (keep · set · clear)`);
728
+ if (cookieActionValue === undefined)
729
+ return this.#cancelWizard();
730
+ const cookieAction = cookieActionValue.trim().toLowerCase() || "keep";
731
+ if (!["keep", "set", "clear"].includes(cookieAction)) {
732
+ throw new Error("Cookie action must be keep, set, or clear");
733
+ }
734
+ let cookie;
735
+ if (cookieAction === "set") {
736
+ cookie = await view.requestValue("6/7 Cookie (hidden; Esc cancels)", { secret: true });
737
+ if (cookie === undefined)
738
+ return this.#cancelWizard();
739
+ if (!cookie)
740
+ throw new Error("Cookie cannot be empty");
741
+ }
742
+ this.#showWizardStep(7, "Review and apply", [
561
743
  `Provider ${provider}`,
562
744
  `Model ${model}`,
563
745
  `Base URL ${baseUrl || "provider default"}`,
564
746
  `API ${api}`,
565
747
  `Thinking ${thinking}`,
566
748
  `API key ${keyAction === "keep" ? current.hasApiKey ? "keep configured key" : "not configured" : keyAction}`,
749
+ `Cookie ${cookieAction === "keep" ? current.hasCookie ? "keep configured cookie" : "not configured" : cookieAction}`,
567
750
  "",
568
- "The key value is never displayed or stored in the TUI state.",
751
+ "The key and cookie values are never displayed or stored in the TUI state.",
569
752
  ]);
570
- const confirmation = await view.requestValue("6/6 save and apply? [y/N]");
753
+ const confirmation = await view.requestValue("7/7 save and apply? [y/N]");
571
754
  if (confirmation === undefined || !/^(y|yes)$/i.test(confirmation.trim()))
572
755
  return this.#cancelWizard();
573
756
  await this.#saveSettings(updateFrom(current, {
@@ -578,7 +761,9 @@ export class PsporeTuiApp {
578
761
  thinking,
579
762
  customModel: provider === "custom-openai",
580
763
  ...(apiKey ? { apiKey } : {}),
764
+ ...(cookie ? { cookie } : {}),
581
765
  clearApiKey: keyAction === "clear",
766
+ clearCookie: cookieAction === "clear",
582
767
  }));
583
768
  }
584
769
  async #saveSettings(update) {
@@ -587,6 +772,7 @@ export class PsporeTuiApp {
587
772
  throw new Error("Model settings are unavailable");
588
773
  this.#store.setNotice("Validating model settings…");
589
774
  const saved = await settingsPort.save(decodeLlmSettingsUpdate(update, "TUI LLM settings"));
775
+ this.#store.setConfiguredModel({ provider: saved.provider, model: saved.model });
590
776
  const applied = await this.#options.onSettingsSaved?.();
591
777
  this.#showSettings(saved, applied?.message ?? "Settings saved; restart the daemon to apply them");
592
778
  }
@@ -594,6 +780,60 @@ export class PsporeTuiApp {
594
780
  this.#store.setPanel("Model settings", settingsLines(settings));
595
781
  this.#store.setNotice(message);
596
782
  }
783
+ #showWizardStep(step, title, lines) {
784
+ const progress = Array.from({ length: 7 }, (_, index) => index + 1 < step ? "●" : index + 1 === step ? "◉" : "○").join("─");
785
+ this.#store.setPanel(`Model setup · ${step}/7`, [
786
+ `${progress} ${title}`,
787
+ "",
788
+ ...lines,
789
+ "",
790
+ "Esc cancels without saving.",
791
+ ]);
792
+ }
793
+ #showWork(query) {
794
+ const activities = this.#store.snapshot().activities;
795
+ if (!query) {
796
+ this.#store.setPanel("Work history", activities.length === 0
797
+ ? ["No work steps have been recorded in this daemon session yet."]
798
+ : activities.slice(-30).map((activity) => {
799
+ const status = activity.status === "running" ? "RUN" : activity.status === "failed" ? "FAIL" : "DONE";
800
+ const result = activity.resultSummary ? ` · ${activity.resultSummary}` : "";
801
+ return `${status.padEnd(4)} ${activity.id.slice(0, 8)} · ${activity.label} · ${activity.summary}${result}`;
802
+ }));
803
+ return;
804
+ }
805
+ const matches = activities.filter((activity) => activity.id === query || activity.id.startsWith(query));
806
+ if (matches.length === 0)
807
+ throw new Error(`No work step matches ${query}`);
808
+ if (matches.length > 1)
809
+ throw new Error(`Work step ID is ambiguous: ${query}`);
810
+ const activity = matches[0];
811
+ if (!activity)
812
+ throw new Error(`No work step matches ${query}`);
813
+ this.#store.setPanel(`Work step ${activity.id.slice(0, 8)}`, activityDetailLines(activity));
814
+ }
815
+ async #refreshConfiguredModel() {
816
+ const settings = this.#options.settings;
817
+ if (!settings)
818
+ return;
819
+ try {
820
+ const configured = settings.isModelConfigured ? await settings.isModelConfigured() : true;
821
+ if (!configured || this.#stopping) {
822
+ this.#store.setConfiguredModel(undefined);
823
+ return;
824
+ }
825
+ const value = await settings.get();
826
+ if (!this.#stopping)
827
+ this.#store.setConfiguredModel({ provider: value.provider, model: value.model });
828
+ }
829
+ catch {
830
+ // The settings panel reports actionable errors on demand; header refresh stays non-blocking.
831
+ }
832
+ finally {
833
+ if (!this.#stopping)
834
+ this.#tui.requestRender();
835
+ }
836
+ }
597
837
  #cancelWizard() {
598
838
  this.#store.clearPanel();
599
839
  this.#store.setNotice("Settings wizard cancelled; nothing was changed");
@@ -609,7 +849,8 @@ export class PsporeTuiApp {
609
849
  return client.command(type, payload, sessionId === undefined ? {} : { sessionId });
610
850
  }
611
851
  async #interrupt() {
612
- const running = this.#store.snapshot().kernel.sessions["main"]?.status === "running";
852
+ const snapshot = this.#store.snapshot();
853
+ const running = snapshot.kernel.sessions[snapshot.selectedSessionId]?.status === "running";
613
854
  if (running) {
614
855
  await this.#submit("/abort");
615
856
  this.#lastInterruptAt = Date.now();
@@ -650,6 +891,15 @@ function parseProvider(value) {
650
891
  }
651
892
  return provider;
652
893
  }
894
+ function parsePermissionMode(value) {
895
+ const normalized = value?.trim().toLowerCase();
896
+ // `bypass` is the name users reach for; it maps onto the existing allow_all policy.
897
+ const mode = normalized === "bypass" ? "allow_all" : normalized;
898
+ if (!mode || !PERMISSION_MODES.includes(mode)) {
899
+ throw new Error(`Permission mode must be one of: ${PERMISSION_MODES.join(", ")} (or bypass)`);
900
+ }
901
+ return mode;
902
+ }
653
903
  function parseThinking(value) {
654
904
  const normalized = value?.trim().toLowerCase();
655
905
  if (!normalized || !THINKING_LEVELS.includes(normalized)) {
@@ -673,8 +923,15 @@ function updateFrom(settings, changes) {
673
923
  api: changes.api ?? settings.api,
674
924
  thinking: changes.thinking ?? settings.thinking,
675
925
  customModel: changes.customModel ?? settings.customModel,
926
+ permissionMode: changes.permissionMode ?? settings.permissionMode,
927
+ autoCompactionEnabled: changes.autoCompactionEnabled ?? settings.autoCompactionEnabled,
928
+ autoCompactionTriggerTokens: changes.autoCompactionTriggerTokens ?? settings.autoCompactionTriggerTokens,
929
+ autoCompactionReserveTokens: changes.autoCompactionReserveTokens ?? settings.autoCompactionReserveTokens,
930
+ autoCompactionKeepRecentTokens: changes.autoCompactionKeepRecentTokens ?? settings.autoCompactionKeepRecentTokens,
676
931
  ...(changes.apiKey ? { apiKey: changes.apiKey } : {}),
932
+ ...(changes.cookie ? { cookie: changes.cookie } : {}),
677
933
  clearApiKey: changes.clearApiKey ?? false,
934
+ clearCookie: changes.clearCookie ?? false,
678
935
  };
679
936
  }
680
937
  function settingsLines(settings) {
@@ -684,9 +941,30 @@ function settingsLines(settings) {
684
941
  `Base URL ${settings.baseUrl || "provider default"}`,
685
942
  `API ${settings.api}`,
686
943
  `Thinking ${settings.thinking}`,
944
+ `Approvals ${settings.permissionMode} — ${permissionModeSummary(settings.permissionMode)}`,
945
+ `Compact ${settings.autoCompactionEnabled ? "on" : "off"} · trigger ${settings.autoCompactionTriggerTokens} · reserve ${settings.autoCompactionReserveTokens} · keep ${settings.autoCompactionKeepRecentTokens}`,
687
946
  `API key ${settings.hasApiKey ? "configured (hidden)" : "not configured"}`,
947
+ ` file ${settings.apiKeyPath}`,
948
+ `Cookie ${settings.hasCookie ? "configured (hidden)" : "not configured"}`,
949
+ ` file ${settings.cookiePath}`,
950
+ `Config ${settings.configPath}`,
951
+ `Catalog ${settings.modelsPath}`,
688
952
  "",
689
953
  "Use /config wizard for guided setup, or /help for direct commands.",
690
954
  ];
691
955
  }
956
+ function parseOnOff(value, label) {
957
+ if (value === "on")
958
+ return true;
959
+ if (value === "off")
960
+ return false;
961
+ throw new Error(`${label} expects on or off`);
962
+ }
963
+ function parseCompactionTokens(value, label) {
964
+ const parsed = Number(value);
965
+ if (!Number.isSafeInteger(parsed) || parsed <= 0 || parsed > 1_000_000) {
966
+ throw new Error(`${label} must be an integer from 1 to 1000000`);
967
+ }
968
+ return parsed;
969
+ }
692
970
  //# sourceMappingURL=tui-app.js.map