@pi-unipi/unipi 3.0.0-alpha.2 → 3.0.0-alpha.21

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 (359) hide show
  1. package/CHANGELOG.md +292 -0
  2. package/README.md +8 -11
  3. package/docs/prefix-cache-architecture.md +14 -0
  4. package/package.json +22 -24
  5. package/packages/ask-user/README.md +55 -107
  6. package/packages/ask-user/ask-ui.ts +306 -732
  7. package/packages/ask-user/clipboard.ts +50 -0
  8. package/packages/ask-user/config.ts +74 -78
  9. package/packages/ask-user/package.json +2 -2
  10. package/packages/ask-user/questions.ts +151 -0
  11. package/packages/ask-user/skills/ask-user/SKILL.md +59 -133
  12. package/packages/ask-user/tools.ts +198 -432
  13. package/packages/autocomplete/package.json +1 -1
  14. package/packages/autocomplete/src/constants.ts +38 -43
  15. package/packages/autocomplete/src/sorting.ts +8 -0
  16. package/packages/background-tasks/package.json +2 -2
  17. package/packages/background-tasks/src/config.ts +0 -73
  18. package/packages/background-tasks/src/index.ts +20 -16
  19. package/packages/background-tasks/src/registry.ts +1 -171
  20. package/packages/background-tasks/src/types.ts +0 -32
  21. package/packages/btw/README.md +13 -56
  22. package/packages/btw/extensions/btw.ts +403 -1796
  23. package/packages/btw/package.json +5 -2
  24. package/packages/btw/skills/btw/SKILL.md +7 -143
  25. package/packages/compactor/README.md +56 -287
  26. package/packages/compactor/package.json +5 -9
  27. package/packages/compactor/skills/compactor/SKILL.md +13 -20
  28. package/packages/compactor/src/card.ts +90 -0
  29. package/packages/compactor/src/commands/index.ts +73 -130
  30. package/packages/compactor/src/compaction/compact-args.ts +5 -3
  31. package/packages/compactor/src/compaction/filter-noise.ts +1 -1
  32. package/packages/compactor/src/compaction/hooks.ts +487 -311
  33. package/packages/compactor/src/compaction/source.ts +178 -0
  34. package/packages/compactor/src/compaction/summarize.ts +586 -52
  35. package/packages/compactor/src/config/manager.ts +130 -127
  36. package/packages/compactor/src/config/schema.ts +32 -48
  37. package/packages/compactor/src/index.ts +40 -431
  38. package/packages/compactor/src/info-screen.ts +44 -190
  39. package/packages/compactor/src/session/recall-blocks.ts +1 -1
  40. package/packages/compactor/src/stats.ts +76 -0
  41. package/packages/compactor/src/tools/context-budget.ts +17 -34
  42. package/packages/compactor/src/tools/ctx-doctor.ts +45 -36
  43. package/packages/compactor/src/tools/register.ts +29 -269
  44. package/packages/compactor/src/types.ts +47 -186
  45. package/packages/core/README.md +25 -0
  46. package/packages/core/child-agent.ts +1 -0
  47. package/packages/core/command-echo.ts +63 -0
  48. package/packages/core/compaction-context.ts +41 -0
  49. package/packages/core/constants.ts +8 -38
  50. package/packages/core/events.ts +0 -53
  51. package/packages/core/fusion-status.ts +4 -0
  52. package/packages/core/global.d.ts +10 -0
  53. package/packages/core/harness-messages.ts +392 -0
  54. package/packages/core/index.ts +14 -0
  55. package/packages/core/kanboard-status.ts +49 -0
  56. package/packages/core/long-horizon-owner-status.ts +46 -0
  57. package/packages/core/model-cache.ts +81 -7
  58. package/packages/core/package.json +6 -3
  59. package/packages/core/src/attach/detect.ts +163 -0
  60. package/packages/core/src/child-agent/child-args.ts +31 -0
  61. package/packages/core/src/child-agent/delivery.ts +41 -0
  62. package/packages/core/src/child-agent/index.ts +5 -0
  63. package/packages/core/src/child-agent/readers.ts +203 -0
  64. package/packages/core/src/child-agent/runtime.ts +584 -0
  65. package/packages/core/src/evidence.ts +78 -0
  66. package/packages/core/src/hints/browser.ts +278 -0
  67. package/packages/core/src/hints/crab-data.ts +19 -0
  68. package/packages/core/src/hints/index.ts +865 -0
  69. package/packages/core/src/hints/lines.ts +607 -0
  70. package/packages/core/src/hints/store.ts +120 -0
  71. package/packages/core/src/jev/chatter.ts +24 -0
  72. package/packages/core/src/jev/settings.ts +177 -14
  73. package/packages/core/src/package-colors.ts +2 -0
  74. package/packages/core/src/settings/catalog.ts +39 -15
  75. package/packages/core/src/settings/engine.ts +48 -2
  76. package/packages/core/src/settings/hub.ts +83 -20
  77. package/packages/core/src/settings/open.ts +49 -0
  78. package/packages/core/src/settings/schema.ts +27 -7
  79. package/packages/core/src/tui/hub-kit.ts +18 -5
  80. package/packages/core/src/tui/kit.ts +198 -0
  81. package/packages/core/src/tui/progress.ts +73 -0
  82. package/packages/core/src/turn/arbiter.ts +290 -0
  83. package/packages/footer/README.md +4 -6
  84. package/packages/footer/package.json +3 -3
  85. package/packages/footer/src/glance-editor.ts +19 -11
  86. package/packages/footer/src/help.ts +1 -1
  87. package/packages/footer/src/index.ts +36 -3
  88. package/packages/footer/src/presets.ts +3 -4
  89. package/packages/footer/src/rendering/icons.ts +0 -20
  90. package/packages/footer/src/segments/compactor.ts +52 -142
  91. package/packages/footer/src/segments/status-ext.ts +0 -1
  92. package/packages/fusion/README.md +14 -4
  93. package/packages/fusion/package.json +4 -3
  94. package/packages/fusion/src/child-args.ts +1 -0
  95. package/packages/fusion/src/index.ts +161 -8
  96. package/packages/fusion/src/pi-settings.ts +57 -0
  97. package/packages/fusion/src/picker.ts +186 -51
  98. package/packages/fusion/src/preset.ts +56 -2
  99. package/packages/fusion/src/prompts.ts +1 -1
  100. package/packages/fusion/src/sidekick-runtime.ts +1 -420
  101. package/packages/fusion/src/tools.ts +107 -128
  102. package/packages/fusion/src/transcript.ts +27 -85
  103. package/packages/info-screen/package.json +2 -2
  104. package/packages/input-shortcuts/README.md +18 -30
  105. package/packages/input-shortcuts/package.json +2 -2
  106. package/packages/input-shortcuts/src/burst.ts +88 -0
  107. package/packages/input-shortcuts/src/chord-overlay.ts +20 -70
  108. package/packages/input-shortcuts/src/cleared-input.ts +97 -0
  109. package/packages/input-shortcuts/src/index.ts +99 -193
  110. package/packages/input-shortcuts/src/last-response.ts +40 -0
  111. package/packages/input-shortcuts/src/registers.ts +8 -23
  112. package/packages/input-shortcuts/src/types.ts +4 -16
  113. package/packages/input-shortcuts/src/undo-redo.ts +59 -47
  114. package/packages/kanboard/README.md +51 -47
  115. package/packages/kanboard/index.ts +293 -55
  116. package/packages/kanboard/package.json +8 -8
  117. package/packages/kanboard/skills/kanboard/SKILL.md +61 -27
  118. package/packages/kanboard/src/badges.ts +93 -0
  119. package/packages/kanboard/src/bin.ts +4 -2
  120. package/packages/kanboard/src/commands.ts +218 -84
  121. package/packages/kanboard/src/debug.ts +20 -0
  122. package/packages/kanboard/src/guard.ts +267 -109
  123. package/packages/kanboard/src/monitor.ts +330 -0
  124. package/packages/kanboard/src/notice-buffer.ts +74 -0
  125. package/packages/kanboard/src/progress.ts +27 -0
  126. package/packages/kanboard/src/reminders.ts +234 -0
  127. package/packages/kanboard/src/settings.ts +69 -15
  128. package/packages/kanboard/src/shapes.ts +5 -0
  129. package/packages/long-horizon/index.ts +190 -13
  130. package/packages/long-horizon/package.json +3 -3
  131. package/packages/long-horizon/src/commands.ts +103 -7
  132. package/packages/long-horizon/src/compaction-brief.ts +35 -0
  133. package/packages/long-horizon/src/engine/continuation.ts +84 -15
  134. package/packages/long-horizon/src/engine/goal-state.ts +64 -13
  135. package/packages/long-horizon/src/engine/nudge-stash.ts +71 -0
  136. package/packages/long-horizon/src/engine/ralph.ts +3 -2
  137. package/packages/long-horizon/src/engine/runaway.ts +68 -11
  138. package/packages/long-horizon/src/engine/verifier.ts +19 -0
  139. package/packages/long-horizon/src/gate.ts +37 -12
  140. package/packages/long-horizon/src/judge/resolve.ts +1 -0
  141. package/packages/long-horizon/src/owner.ts +35 -2
  142. package/packages/long-horizon/src/progress.ts +87 -0
  143. package/packages/long-horizon/src/prompts/goal.ts +1 -1
  144. package/packages/long-horizon/src/runtime.ts +172 -18
  145. package/packages/long-horizon/src/settings.ts +54 -39
  146. package/packages/long-horizon/src/tools/goal.ts +6 -0
  147. package/packages/long-horizon/src/tools/graph.ts +1 -1
  148. package/packages/long-horizon/src/tools/swarm.ts +3 -3
  149. package/packages/mcp/package.json +2 -2
  150. package/packages/memory/commands.ts +7 -2
  151. package/packages/memory/index.ts +210 -32
  152. package/packages/memory/package.json +3 -3
  153. package/packages/memory/save-session.ts +264 -0
  154. package/packages/memory/settings.ts +17 -0
  155. package/packages/memory/tools.ts +253 -203
  156. package/packages/notify/package.json +2 -2
  157. package/packages/skill-registry/README.md +53 -16
  158. package/packages/skill-registry/index.ts +230 -0
  159. package/packages/skill-registry/package.json +19 -8
  160. package/packages/skill-registry/src/editor.ts +206 -0
  161. package/packages/skill-registry/src/judge.ts +289 -0
  162. package/packages/skill-registry/src/registry.ts +87 -0
  163. package/packages/skill-registry/src/settings.ts +259 -0
  164. package/packages/skill-registry/src/vault.ts +80 -0
  165. package/packages/subagents/README.md +39 -119
  166. package/packages/subagents/package.json +6 -13
  167. package/packages/subagents/skills/subagents/SKILL.md +18 -42
  168. package/packages/subagents/src/agents.ts +213 -0
  169. package/packages/subagents/src/cards.ts +182 -0
  170. package/packages/subagents/src/index.ts +609 -1084
  171. package/packages/subagents/src/manager.ts +429 -0
  172. package/packages/subagents/src/profiles.ts +130 -0
  173. package/packages/subagents/src/transcript.ts +154 -0
  174. package/packages/subagents/src/ui.ts +389 -0
  175. package/packages/unipi/bundled.js +39756 -45569
  176. package/packages/unipi/index.ts +55 -10
  177. package/packages/updater/package.json +2 -2
  178. package/packages/utility/README.md +76 -69
  179. package/packages/utility/package.json +2 -2
  180. package/packages/utility/skills/image/SKILL.md +37 -0
  181. package/packages/utility/skills/utility/SKILL.md +17 -60
  182. package/packages/utility/src/answer/extract.ts +128 -0
  183. package/packages/utility/src/answer/index.ts +213 -0
  184. package/packages/utility/src/answer/reply.ts +133 -0
  185. package/packages/utility/src/answer/web.ts +167 -0
  186. package/packages/utility/src/attach/index.ts +205 -0
  187. package/packages/utility/src/commands.ts +38 -142
  188. package/packages/utility/src/diagnostics/engine.ts +50 -5
  189. package/packages/utility/src/image/index.ts +33 -0
  190. package/packages/utility/src/image/models.ts +221 -0
  191. package/packages/{image/src → utility/src/image}/recognize.ts +2 -2
  192. package/packages/utility/src/image/settings.ts +178 -0
  193. package/packages/{image/src/image-source.ts → utility/src/image/source.ts} +1 -1
  194. package/packages/utility/src/image/tools.ts +168 -0
  195. package/packages/utility/src/image/transports.ts +186 -0
  196. package/packages/utility/src/index.ts +68 -389
  197. package/packages/utility/src/lifecycle/cleanup.ts +116 -311
  198. package/packages/utility/src/rename/gate.ts +102 -0
  199. package/packages/utility/src/rename/index.ts +191 -0
  200. package/packages/utility/src/rename/session.ts +170 -0
  201. package/packages/utility/src/render/delegated.ts +285 -0
  202. package/packages/utility/src/render/harness.ts +683 -0
  203. package/packages/utility/src/render/parse.ts +156 -0
  204. package/packages/utility/src/render/pi-settings.ts +38 -0
  205. package/packages/utility/src/render/reply-bg.ts +307 -0
  206. package/packages/utility/src/render/simple.ts +724 -0
  207. package/packages/utility/src/render/spacing.ts +235 -0
  208. package/packages/utility/src/render/styled.ts +251 -0
  209. package/packages/utility/src/render/tools.ts +353 -0
  210. package/packages/utility/src/settings.ts +166 -233
  211. package/packages/utility/src/types.ts +1 -222
  212. package/packages/watchdog/index.ts +17 -6
  213. package/packages/watchdog/package.json +3 -3
  214. package/packages/watchdog/src/config.ts +3 -2
  215. package/packages/web-api/package.json +2 -2
  216. package/packages/workflow/README.md +3 -0
  217. package/packages/workflow/index.ts +0 -2
  218. package/packages/workflow/package.json +2 -2
  219. package/packages/workflow/src/permission/decide.ts +6 -4
  220. package/packages/workflow/src/permission/index.ts +17 -7
  221. package/packages/workflow/src/permission/settings.ts +39 -4
  222. package/packages/workflow/src/plan/index.ts +19 -4
  223. package/packages/background-tasks/extensions/delegate-child.ts +0 -1
  224. package/packages/background-tasks/src/context-parent-snapshot.ts +0 -142
  225. package/packages/background-tasks/src/context-token-budget.ts +0 -903
  226. package/packages/background-tasks/src/context-visible-conversation-v2.ts +0 -551
  227. package/packages/background-tasks/src/delegate/artifacts.ts +0 -487
  228. package/packages/background-tasks/src/delegate/budget.ts +0 -415
  229. package/packages/background-tasks/src/delegate/hook-contract-evidence.json +0 -18
  230. package/packages/background-tasks/src/delegate/hook-contract.ts +0 -154
  231. package/packages/background-tasks/src/delegate/launch.ts +0 -484
  232. package/packages/background-tasks/src/delegate/result-package.ts +0 -459
  233. package/packages/background-tasks/src/delegate/runner.ts +0 -430
  234. package/packages/background-tasks/src/delegate/seed.ts +0 -423
  235. package/packages/background-tasks/src/delegate/types.ts +0 -323
  236. package/packages/background-tasks/src/delegate-child-extension.ts +0 -978
  237. package/packages/background-tasks/src/delegate-extension.ts +0 -654
  238. package/packages/background-tasks/src/fixtures/delegate-context-incident.json +0 -17
  239. package/packages/compactor/skills/compactor-detail/SKILL.md +0 -116
  240. package/packages/compactor/skills/compactor-doctor/SKILL.md +0 -71
  241. package/packages/compactor/skills/compactor-stats/SKILL.md +0 -51
  242. package/packages/compactor/src/compaction/build-sections.ts +0 -76
  243. package/packages/compactor/src/compaction/extract/goals.ts +0 -36
  244. package/packages/compactor/src/compaction/extract/preferences.ts +0 -40
  245. package/packages/compactor/src/compaction/format.ts +0 -53
  246. package/packages/compactor/src/compaction/merge.ts +0 -143
  247. package/packages/compactor/src/config/presets.ts +0 -160
  248. package/packages/compactor/src/executor/executor.ts +0 -233
  249. package/packages/compactor/src/executor/runtime.ts +0 -115
  250. package/packages/compactor/src/security/evaluator.ts +0 -89
  251. package/packages/compactor/src/security/policy.ts +0 -96
  252. package/packages/compactor/src/security/scanner.ts +0 -65
  253. package/packages/compactor/src/session/auto-inject.ts +0 -60
  254. package/packages/compactor/src/session/db.ts +0 -325
  255. package/packages/compactor/src/session/extract.ts +0 -144
  256. package/packages/compactor/src/session/resume-inject.ts +0 -64
  257. package/packages/compactor/src/session/snapshot.ts +0 -327
  258. package/packages/compactor/src/tools/ctx-batch-execute.ts +0 -41
  259. package/packages/compactor/src/tools/ctx-execute-file.ts +0 -23
  260. package/packages/compactor/src/tools/ctx-execute.ts +0 -23
  261. package/packages/compactor/src/tools/ctx-stats.ts +0 -96
  262. package/packages/image/README.md +0 -99
  263. package/packages/image/package.json +0 -61
  264. package/packages/image/skills/image/SKILL.md +0 -76
  265. package/packages/image/src/generate.ts +0 -256
  266. package/packages/image/src/index.ts +0 -135
  267. package/packages/image/src/models.ts +0 -519
  268. package/packages/image/src/openai-images-api.ts +0 -282
  269. package/packages/image/src/register-providers.ts +0 -209
  270. package/packages/image/src/settings.ts +0 -173
  271. package/packages/image/src/tools.ts +0 -326
  272. package/packages/input-shortcuts/src/clipboard.ts +0 -119
  273. package/packages/kanboard/src/runner.ts +0 -817
  274. package/packages/skill-registry/skills/auto/SKILL.md +0 -465
  275. package/packages/skill-registry/skills/brainstorm/SKILL.md +0 -219
  276. package/packages/skill-registry/skills/chore-create/SKILL.md +0 -315
  277. package/packages/skill-registry/skills/chore-execute/SKILL.md +0 -314
  278. package/packages/skill-registry/skills/consolidate/SKILL.md +0 -142
  279. package/packages/skill-registry/skills/consultant/SKILL.md +0 -97
  280. package/packages/skill-registry/skills/debug/SKILL.md +0 -228
  281. package/packages/skill-registry/skills/document/SKILL.md +0 -120
  282. package/packages/skill-registry/skills/fix/SKILL.md +0 -212
  283. package/packages/skill-registry/skills/gather-context/SKILL.md +0 -145
  284. package/packages/skill-registry/skills/plan/SKILL.md +0 -231
  285. package/packages/skill-registry/skills/quick-fix/SKILL.md +0 -135
  286. package/packages/skill-registry/skills/quick-work/SKILL.md +0 -110
  287. package/packages/skill-registry/skills/research/SKILL.md +0 -251
  288. package/packages/skill-registry/skills/review-work/SKILL.md +0 -187
  289. package/packages/skill-registry/skills/scan-issues/SKILL.md +0 -195
  290. package/packages/skill-registry/skills/work/SKILL.md +0 -218
  291. package/packages/skill-registry/skills/worktree-create/SKILL.md +0 -69
  292. package/packages/skill-registry/skills/worktree-list/SKILL.md +0 -78
  293. package/packages/skill-registry/skills/worktree-merge/SKILL.md +0 -89
  294. package/packages/subagents/agents/delegate.md +0 -14
  295. package/packages/subagents/agents/oracle.md +0 -78
  296. package/packages/subagents/agents/researcher.md +0 -52
  297. package/packages/subagents/agents/reviewer.md +0 -80
  298. package/packages/subagents/agents/scout.md +0 -50
  299. package/packages/subagents/agents/worker.md +0 -59
  300. package/packages/subagents/prompts/council.md +0 -48
  301. package/packages/subagents/prompts/gather-context-and-clarify.md +0 -13
  302. package/packages/subagents/prompts/parallel-cleanup.md +0 -59
  303. package/packages/subagents/prompts/parallel-research.md +0 -50
  304. package/packages/subagents/prompts/parallel-review.md +0 -54
  305. package/packages/subagents/prompts/review-loop.md +0 -43
  306. package/packages/subagents/skills/council-mode/SKILL.md +0 -230
  307. package/packages/subagents/skills/subagents/references/constraints-and-recipes.md +0 -259
  308. package/packages/subagents/skills/subagents/references/execution-controls.md +0 -454
  309. package/packages/subagents/skills/subagents/references/management-authoring-rpc.md +0 -161
  310. package/packages/subagents/skills/subagents/references/multi-lane-orchestration.md +0 -39
  311. package/packages/subagents/skills/subagents/references/prompting-and-roles.md +0 -267
  312. package/packages/subagents/src/acceptance.ts +0 -331
  313. package/packages/subagents/src/agent-manager.ts +0 -405
  314. package/packages/subagents/src/agent-memory.ts +0 -300
  315. package/packages/subagents/src/agent-overrides.ts +0 -183
  316. package/packages/subagents/src/agent-runner.ts +0 -271
  317. package/packages/subagents/src/async-runner.ts +0 -422
  318. package/packages/subagents/src/authority-policy.ts +0 -47
  319. package/packages/subagents/src/budgets.ts +0 -285
  320. package/packages/subagents/src/child-safety.ts +0 -140
  321. package/packages/subagents/src/config.ts +0 -249
  322. package/packages/subagents/src/conversation-viewer.ts +0 -281
  323. package/packages/subagents/src/core-compat.ts +0 -94
  324. package/packages/subagents/src/custom-agents.ts +0 -343
  325. package/packages/subagents/src/file-system-retry.ts +0 -50
  326. package/packages/subagents/src/fleet-data.ts +0 -105
  327. package/packages/subagents/src/fleet-view.ts +0 -322
  328. package/packages/subagents/src/foreground-detach.ts +0 -59
  329. package/packages/subagents/src/fork-context.ts +0 -285
  330. package/packages/subagents/src/global.d.ts +0 -7
  331. package/packages/subagents/src/guide.ts +0 -129
  332. package/packages/subagents/src/mission-state.ts +0 -133
  333. package/packages/subagents/src/mission-store.ts +0 -436
  334. package/packages/subagents/src/output-limits.ts +0 -142
  335. package/packages/subagents/src/parity-types.ts +0 -315
  336. package/packages/subagents/src/pi-args.ts +0 -167
  337. package/packages/subagents/src/result-files.ts +0 -232
  338. package/packages/subagents/src/result-watcher.ts +0 -221
  339. package/packages/subagents/src/retained-children.ts +0 -176
  340. package/packages/subagents/src/run-fanout-budget.ts +0 -356
  341. package/packages/subagents/src/scheduled-runs.ts +0 -349
  342. package/packages/subagents/src/schemas.ts +0 -263
  343. package/packages/subagents/src/slash-commands.ts +0 -80
  344. package/packages/subagents/src/supervisor-channel.ts +0 -249
  345. package/packages/subagents/src/tool-handler.ts +0 -1144
  346. package/packages/subagents/src/types.ts +0 -238
  347. package/packages/subagents/src/widget.ts +0 -457
  348. package/packages/subagents/src/workflow-script.ts +0 -737
  349. package/packages/subagents/src/workflow-worker.ts +0 -384
  350. package/packages/subagents/src/worktree.ts +0 -614
  351. package/packages/utility/src/analytics/collector.ts +0 -293
  352. package/packages/utility/src/info-screen.ts +0 -80
  353. package/packages/utility/src/lifecycle/process.ts +0 -162
  354. package/packages/utility/src/prefix-cache.ts +0 -263
  355. package/packages/utility/src/skill-discovery.ts +0 -542
  356. package/packages/utility/src/tools/env.ts +0 -113
  357. package/packages/utility/src/tui/name-badge-state.ts +0 -315
  358. package/packages/utility/src/tui/name-badge.ts +0 -109
  359. /package/packages/{subagents/src → core/src/child-agent}/pi-spawn.ts +0 -0
@@ -1,322 +0,0 @@
1
- /**
2
- * @pi-unipi/subagents — FleetView (persistent fleet panel)
3
- *
4
- * pi-subagents parity built on OUR panel system: a persistent setWidget slot
5
- * (belowEditor/aboveEditor placement from config) summarizing active work —
6
- * in-process agents from the AgentManager plus async process runs from the
7
- * run dirs. Collapsed by default; ↓/← activates selection, j/k navigate,
8
- * enter opens the inspector, esc deactivates.
9
- */
10
-
11
- import type { ExtensionUIContext } from "@earendil-works/pi-coding-agent";
12
- import { matchesKey, Key, truncateToWidth } from "@earendil-works/pi-tui";
13
- import type { AgentManager } from "./agent-manager.js";
14
- import type { AgentActivity } from "./types.js";
15
- import { listAsyncRunSummaries, type AsyncRunSummary } from "./fleet-data.js";
16
-
17
- const REFRESH_MS = 500;
18
- const MAX_AGENT_ROWS = 6;
19
-
20
- export interface FleetEntry {
21
- key: string;
22
- source: "inprocess" | "async";
23
- agent: string;
24
- description?: string;
25
- startedAt: number;
26
- state: string;
27
- /** Run dir for async entries (inspector target). */
28
- runDir?: string;
29
- }
30
-
31
- export interface FleetViewOptions {
32
- refreshMs?: number;
33
- maxAgentRows?: number;
34
- placement?: "belowEditor" | "aboveEditor";
35
- /**
36
- * Current session id. The dock only shows async runs stamped with it, so a
37
- * crashed sibling session's orphans never leak into this project's footer.
38
- */
39
- sessionId?: string;
40
- /** Open the inspector for an entry (wired to ConversationViewer overlay). */
41
- openInspector?: (entry: FleetEntry) => Promise<void> | void;
42
- }
43
-
44
- function isActiveState(state: string): boolean {
45
- return state === "running" || state === "queued" || state === "pending";
46
- }
47
-
48
- /** Collect active entries across both transports. */
49
- export function collectFleetEntries(
50
- manager: AgentManager,
51
- activity: Map<string, AgentActivity>,
52
- asyncDirRoot: string,
53
- sessionId?: string,
54
- ): FleetEntry[] {
55
- const entries: FleetEntry[] = [];
56
-
57
- for (const record of manager.listAgents()) {
58
- if (!isActiveState(record.status)) continue;
59
- const act = activity.get(record.id);
60
- entries.push({
61
- key: `inprocess:${record.id}`,
62
- source: "inprocess",
63
- agent: record.type,
64
- description: record.description,
65
- startedAt: record.startedAt,
66
- state: record.status,
67
- });
68
- void act;
69
- }
70
-
71
- for (const run of listAsyncRunSummaries(asyncDirRoot, sessionId ? { sessionId } : {})) {
72
- if (!isActiveState(run.state)) continue;
73
- entries.push({
74
- key: `async:${run.runId}`,
75
- source: "async",
76
- agent: run.agent,
77
- description: run.taskSummary,
78
- startedAt: run.startedAt,
79
- state: run.state,
80
- runDir: run.runDir,
81
- });
82
- }
83
-
84
- return entries.sort((left, right) => left.startedAt - right.startedAt || left.key.localeCompare(right.key));
85
- }
86
-
87
- export class FleetView {
88
- private uiCtx: ExtensionUIContext | undefined;
89
- private tui: { requestRender(): void } | undefined;
90
- private timer: ReturnType<typeof setInterval> | undefined;
91
- private widgetRegistered = false;
92
- private lastRenderKey = "";
93
- private entries: FleetEntry[] = [];
94
- private active = false;
95
- private selectedKey = "main";
96
- private inspectorOpen = false;
97
-
98
- constructor(
99
- private manager: AgentManager,
100
- private activity: Map<string, AgentActivity>,
101
- private asyncDirRoot: string,
102
- private options: FleetViewOptions = {},
103
- ) {}
104
-
105
- setUICtx(ctx: ExtensionUIContext): void {
106
- if (ctx === this.uiCtx) return;
107
- this.clearRegistration();
108
- this.uiCtx = ctx;
109
- this.ensureTimer();
110
- this.refresh();
111
- }
112
-
113
- dispose(): void {
114
- if (this.timer) clearInterval(this.timer);
115
- this.timer = undefined;
116
- this.clearRegistration();
117
- this.uiCtx = undefined;
118
- this.entries = [];
119
- this.active = false;
120
- this.selectedKey = "main";
121
- }
122
-
123
- /** Called when work starts/finishes to trigger a refresh. */
124
- refresh(): void {
125
- const ctx = this.uiCtx;
126
- if (!ctx) return;
127
- this.entries = collectFleetEntries(this.manager, this.activity, this.asyncDirRoot, this.options.sessionId);
128
- this.clampSelection();
129
-
130
- if (this.inspectorOpen) {
131
- this.lastRenderKey = "";
132
- this.clearWidget();
133
- return;
134
- }
135
- if (this.entries.length === 0) {
136
- this.active = false;
137
- this.selectedKey = "main";
138
- this.lastRenderKey = "";
139
- this.clearWidget();
140
- return;
141
- }
142
-
143
- const renderKey = JSON.stringify({
144
- active: this.active,
145
- selected: this.selectedKey,
146
- entries: this.entries.map((e) => [e.key, e.state]),
147
- });
148
- if (!this.widgetRegistered) {
149
- ctx.setWidget(
150
- "unipi-fleet-status",
151
- (tui: unknown, _theme: unknown) => {
152
- this.tui = tui as { requestRender(): void };
153
- return {
154
- render: (width: number) => this.render(width),
155
- invalidate: () => {
156
- this.lastRenderKey = "";
157
- },
158
- dispose: () => {
159
- this.widgetRegistered = false;
160
- this.tui = undefined;
161
- },
162
- };
163
- },
164
- { placement: this.options.placement ?? "belowEditor" },
165
- );
166
- this.widgetRegistered = true;
167
- this.lastRenderKey = renderKey;
168
- return;
169
- }
170
- if (renderKey === this.lastRenderKey) return;
171
- this.lastRenderKey = renderKey;
172
- this.tui?.requestRender();
173
- }
174
-
175
- /**
176
- * Key handling for the collapsed/active roster. Returns consume intent.
177
- * Wired from index.ts's terminal input hook.
178
- */
179
- handleKey(data: string, editorHasFocus: () => boolean): { consume?: boolean } | undefined {
180
- const ctx = this.uiCtx;
181
- if (!ctx || this.entries.length === 0) return undefined;
182
- if (this.inspectorOpen) return undefined;
183
- if (!editorHasFocus()) {
184
- if (this.active) this.deactivate();
185
- return undefined;
186
- }
187
-
188
- if (!this.active) {
189
- const activates = matchesKey(data, "down") || matchesKey(data, "left");
190
- if (!activates || ctx.getEditorText?.() !== "") return undefined;
191
- this.active = true;
192
- this.selectedKey = "main";
193
- this.refresh();
194
- return { consume: true };
195
- }
196
-
197
- const roster = this.rosterKeys();
198
- const selectedIndex = Math.max(0, roster.indexOf(this.selectedKey));
199
- if (matchesKey(data, "down") || matchesKey(data, "j")) {
200
- this.selectedKey = roster[Math.min(roster.length - 1, selectedIndex + 1)] ?? "main";
201
- this.refresh();
202
- return { consume: true };
203
- }
204
- if (matchesKey(data, "up") || matchesKey(data, "k")) {
205
- if (selectedIndex === 0) {
206
- this.deactivate();
207
- return { consume: true };
208
- }
209
- this.selectedKey = roster[selectedIndex - 1] ?? "main";
210
- this.refresh();
211
- return { consume: true };
212
- }
213
- if (matchesKey(data, "escape")) {
214
- this.deactivate();
215
- return { consume: true };
216
- }
217
- if (matchesKey(data, Key.enter)) {
218
- if (this.selectedKey === "main") {
219
- this.deactivate();
220
- return { consume: true };
221
- }
222
- const entry = this.entries.find((e) => e.key === this.selectedKey);
223
- if (!entry) return undefined;
224
- this.inspectorOpen = true;
225
- this.refresh();
226
- void Promise.resolve()
227
- .then(() => this.options.openInspector?.(entry))
228
- .catch(() => {})
229
- .finally(() => {
230
- this.inspectorOpen = false;
231
- this.refresh();
232
- });
233
- return { consume: true };
234
- }
235
- return undefined;
236
- }
237
-
238
- render(width: number): string[] {
239
- if (this.entries.length === 0) return [];
240
- if (!this.active) {
241
- // Collapsed summary row.
242
- const count = this.entries.length;
243
- const noun = count === 1 ? "agent" : "agents";
244
- const states = new Map<string, number>();
245
- for (const entry of this.entries) states.set(entry.state, (states.get(entry.state) ?? 0) + 1);
246
- const breakdown = [...states.entries()].map(([state, n]) => `${n} ${state}`).join(", ");
247
- return [
248
- truncateToWidth(` ${count} active ${noun} (${breakdown}) · ↓ to inspect`, width),
249
- ];
250
- }
251
-
252
- const roster = this.rosterKeys();
253
- const selectedIndex = Math.max(0, roster.indexOf(this.selectedKey));
254
- const lines = [truncateToWidth(` ↑↓/jk select · enter inspect · esc back`, width), ""];
255
- lines.push(truncateToWidth(` ${this.bullet(0, selectedIndex)} main`, width));
256
-
257
- const visibleCount = Math.min(this.options.maxAgentRows ?? MAX_AGENT_ROWS, this.entries.length);
258
- const start = selectedIndex < visibleCount ? 0 : selectedIndex - visibleCount + 1;
259
- const hiddenBelow = this.entries.length - (start + visibleCount);
260
- if (start > 0) lines.push(truncateToWidth(` ↑ ${start} more`, width));
261
- for (let index = start; index < start + visibleCount; index++) {
262
- const entry = this.entries[index];
263
- if (!entry) break;
264
- lines.push(...this.renderEntry(index + 1, selectedIndex, entry, width));
265
- }
266
- if (hiddenBelow > 0) lines.push(truncateToWidth(` ↓ ${hiddenBelow} more`, width));
267
- return lines;
268
- }
269
-
270
- private renderEntry(rosterIndex: number, selectedIndex: number, entry: FleetEntry, width: number): string[] {
271
- void rosterIndex;
272
- const elapsed = formatElapsed(Date.now() - entry.startedAt);
273
- const sourceTag = entry.source === "async" ? "proc" : "local";
274
- const left = ` ${this.bullet(-1, selectedIndex)} ${entry.agent} · ${entry.state}`;
275
- const right = `${sourceTag} · ${elapsed}`;
276
- return [truncateToWidth(`${left} ${right}`, width)];
277
- }
278
-
279
- private bullet(_index: number, selectedIndex: number): string {
280
- return selectedIndex > 0 ? ">" : " ";
281
- }
282
-
283
- private rosterKeys(): string[] {
284
- return ["main", ...this.entries.map((entry) => entry.key)];
285
- }
286
-
287
- private clampSelection(): void {
288
- if (!this.rosterKeys().includes(this.selectedKey)) this.selectedKey = "main";
289
- }
290
-
291
- private deactivate(): void {
292
- this.active = false;
293
- this.selectedKey = "main";
294
- this.refresh();
295
- }
296
-
297
- private clearWidget(): void {
298
- if (this.widgetRegistered && this.uiCtx) {
299
- this.uiCtx.setWidget("unipi-fleet-status", undefined);
300
- this.widgetRegistered = false;
301
- this.tui = undefined;
302
- }
303
- }
304
-
305
- private clearRegistration(): void {
306
- this.clearWidget();
307
- }
308
-
309
- private ensureTimer(): void {
310
- if (this.timer) return;
311
- this.timer = setInterval(() => this.refresh(), this.options.refreshMs ?? REFRESH_MS);
312
- this.timer.unref?.();
313
- }
314
- }
315
-
316
- function formatElapsed(ms: number): string {
317
- const seconds = Math.floor(ms / 1000);
318
- if (seconds < 60) return `${seconds}s`;
319
- const minutes = Math.floor(seconds / 60);
320
- if (minutes < 60) return `${minutes}m${seconds % 60}s`;
321
- return `${Math.floor(minutes / 60)}h${minutes % 60}m`;
322
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * @pi-unipi/subagents — Foreground detach shortcut
3
- *
4
- * Ported from pi-subagents foregroundDetachShortcut (config) +
5
- * foregroundSingleHintText (render.ts). Optionally binds a shortcut that
6
- * detaches the active foreground single-agent run WITHOUT terminating it:
7
- * the parent stops waiting, the child keeps running, and the completion
8
- * arrives later as a normal task-notification.
9
- */
10
-
11
- export interface DetachShortcutConfig {
12
- /** Shortcut string like "ctrl+b". Empty/unset disables the feature. */
13
- shortcut?: string;
14
- }
15
-
16
- /** Parse a shortcut string into normalized parts ("ctrl+b" → ["ctrl","b"]). */
17
- export function parseDetachShortcut(raw: string | undefined): string[] | undefined {
18
- const trimmed = raw?.trim().toLowerCase();
19
- if (!trimmed) return undefined;
20
- const parts = trimmed.split("+").map((part) => part.trim()).filter(Boolean);
21
- if (parts.length === 0 || parts.some((part) => !part)) return undefined;
22
- // Must include at least one modifier to avoid stealing plain keys.
23
- const modifiers = new Set(["ctrl", "alt", "shift", "meta", "super"]);
24
- if (!parts.slice(0, -1).some((part) => modifiers.has(part))) return undefined;
25
- return parts;
26
- }
27
-
28
- /** Human-readable label ("ctrl+b" → "Ctrl+B"). */
29
- export function formatDetachHint(parts: string[] | undefined): string | undefined {
30
- if (!parts) return undefined;
31
- const label = parts
32
- .map((part) => {
33
- if (part === "ctrl") return "Ctrl";
34
- if (part === "alt") return "Alt";
35
- if (part === "shift") return "Shift";
36
- if (part === "escape") return "Esc";
37
- if (part.length === 1) return part.toUpperCase();
38
- return part.charAt(0).toUpperCase() + part.slice(1);
39
- })
40
- .join("+");
41
- return `${label} detaches (run continues in background)`;
42
- }
43
-
44
- /**
45
- * Whether a raw terminal input matches the configured shortcut.
46
- * Matches pi-tui-style control sequences for ctrl+<letter> plus literal text
47
- * for other combos.
48
- */
49
- export function matchesDetachInput(data: string, parts: string[] | undefined): boolean {
50
- if (!parts) return false;
51
- const hasCtrl = parts.includes("ctrl");
52
- const key = parts[parts.length - 1]!;
53
- if (hasCtrl && parts.length === 2 && key.length === 1) {
54
- // Control sequence: C0 codes 0x01–0x1a map to ctrl+a–z.
55
- const expected = String.fromCharCode(key.charCodeAt(0) - 96);
56
- return data === expected;
57
- }
58
- return data === parts.join("+");
59
- }
@@ -1,285 +0,0 @@
1
- /**
2
- * @pi-unipi/subagents — Fork context resolution
3
- *
4
- * Ported from pi-subagents src/shared/fork-context.ts. Creates branched child
5
- * sessions from the parent session file, sanitizes signed Anthropic thinking
6
- * blocks (redacted_thinking always; signed thinking on Anthropic models),
7
- * appends a thinking_level_change:off entry when sanitization occurred, and
8
- * aligns the forked session cwd to the child launch cwd. Fork files nest
9
- * under <parent-session-dir>/<parent-stem>/forks/ so top-level session
10
- * discovery never picks them up.
11
- */
12
-
13
- import * as fs from "node:fs";
14
- import * as path from "node:path";
15
- import { randomUUID } from "node:crypto";
16
- import { SessionManager } from "@earendil-works/pi-coding-agent";
17
-
18
- export type SubagentExecutionContext = "fresh" | "fork";
19
-
20
- interface BranchSessionEntry {
21
- type: string;
22
- id?: string;
23
- parentId?: string | null;
24
- timestamp?: string;
25
- message?: {
26
- role?: string;
27
- content?: unknown;
28
- provider?: string;
29
- api?: string;
30
- model?: string;
31
- };
32
- thinkingLevel?: string;
33
- cwd?: string;
34
- [extra: string]: unknown;
35
- }
36
-
37
- export interface PreferredForkAvailability {
38
- getSessionFile(): string | undefined;
39
- getLeafId(): string | null;
40
- }
41
-
42
- export interface PreferredForkSnapshot {
43
- parentSessionFile?: string;
44
- leafId?: string | null;
45
- }
46
-
47
- export function resolveSubagentContext(value: unknown): SubagentExecutionContext {
48
- return value === "fork" ? "fork" : "fresh";
49
- }
50
-
51
- export function canPreferFork(sessionManager: PreferredForkAvailability): boolean {
52
- const parentSessionFile = sessionManager.getSessionFile();
53
- const leafId = sessionManager.getLeafId();
54
- if (!parentSessionFile || !leafId) return false;
55
- try {
56
- return fs.existsSync(parentSessionFile);
57
- } catch {
58
- return false;
59
- }
60
- }
61
-
62
- export function canPreferForkFromSnapshot(input: PreferredForkSnapshot): boolean {
63
- if (!input.parentSessionFile || !input.leafId) return false;
64
- try {
65
- return fs.existsSync(input.parentSessionFile);
66
- } catch {
67
- return false;
68
- }
69
- }
70
-
71
- /** Anthropic provider/api models require thinking off on a sanitized fork. */
72
- export function forkedChildRequiresThinkingOff(
73
- model: string | undefined,
74
- modelInfoProvider?: string,
75
- modelInfoApi?: string,
76
- ): boolean {
77
- if (!model) return true;
78
- if (modelInfoProvider?.toLowerCase() === "anthropic") return true;
79
- if (modelInfoApi?.toLowerCase() === "anthropic-messages") return true;
80
- // Unknown models stay conservative (reference rule).
81
- if (modelInfoProvider === undefined && modelInfoApi === undefined) return true;
82
- return false;
83
- }
84
-
85
- function isUnsafeAnthropicThinkingBlock(message: BranchSessionEntry["message"], block: unknown): boolean {
86
- if (!message || !block || typeof block !== "object" || !("type" in block)) return false;
87
- const provider = typeof message.provider === "string" ? message.provider.toLowerCase() : "";
88
- const api = typeof message.api === "string" ? message.api.toLowerCase() : "";
89
- const model = typeof message.model === "string" ? message.model.toLowerCase() : "";
90
- const isAnthropic = provider === "anthropic" || api === "anthropic-messages" || model.startsWith("anthropic/");
91
- const b = block as Record<string, unknown>;
92
- if (b.type === "redacted_thinking") return true;
93
- if (b.type !== "thinking" || !isAnthropic) return false;
94
- const signature =
95
- "thinkingSignature" in b ? b.thinkingSignature : "signature" in b ? b.signature : undefined;
96
- return b.redacted === true || (typeof signature === "string" && (signature as string).length > 0);
97
- }
98
-
99
- function createEntryId(entries: BranchSessionEntry[]): string {
100
- const ids = new Set(entries.map((entry) => entry.id).filter((id): id is string => typeof id === "string"));
101
- for (let attempt = 0; attempt < 100; attempt++) {
102
- const id = randomUUID().slice(0, 8);
103
- if (!ids.has(id)) return id;
104
- }
105
- return randomUUID();
106
- }
107
-
108
- function appendThinkingOffEntry(entries: BranchSessionEntry[]): void {
109
- const last = entries[entries.length - 1];
110
- if (last?.type === "thinking_level_change" && last.thinkingLevel === "off") return;
111
- const parent = [...entries].reverse().find((entry) => typeof entry.id === "string");
112
- entries.push({
113
- type: "thinking_level_change",
114
- id: createEntryId(entries),
115
- parentId: parent?.id ?? null,
116
- timestamp: new Date().toISOString(),
117
- thinkingLevel: "off",
118
- });
119
- }
120
-
121
- /** Strip signed/redacted Anthropic thinking blocks from forked entries. */
122
- export function sanitizeUnsafeThinkingBlocks(entries: BranchSessionEntry[]): boolean {
123
- let sanitized = false;
124
- for (const entry of entries) {
125
- if (entry.type !== "message" || entry.message?.role !== "assistant" || !Array.isArray(entry.message.content)) continue;
126
- const filtered = (entry.message.content as unknown[]).filter(
127
- (block) => !isUnsafeAnthropicThinkingBlock(entry.message, block),
128
- );
129
- if (filtered.length === (entry.message.content as unknown[]).length) continue;
130
- entry.message.content = filtered;
131
- sanitized = true;
132
- }
133
- return sanitized;
134
- }
135
-
136
- function readSessionEntries(sessionFile: string): BranchSessionEntry[] {
137
- const lines = fs.readFileSync(sessionFile, "utf-8").split("\n").filter((line) => line.trim().length > 0);
138
- return lines.map((line, index) => {
139
- try {
140
- return JSON.parse(line) as BranchSessionEntry;
141
- } catch (error) {
142
- const cause = error instanceof Error ? error : new Error(String(error));
143
- throw new Error(
144
- `Unable to inspect forked session ${sessionFile}: invalid JSONL on line ${index + 1}: ${cause.message}`,
145
- { cause },
146
- );
147
- }
148
- });
149
- }
150
-
151
- /** Align a forked session's cwd to the child launch cwd. */
152
- export function alignForkedSessionCwd(sessionFile: string, cwd: string): void {
153
- const entries = readSessionEntries(sessionFile);
154
- const header = entries[0];
155
- if (header?.type !== "session") {
156
- throw new Error(`Forked session ${sessionFile} does not start with a session header.`);
157
- }
158
- const resolvedCwd = path.resolve(cwd);
159
- const effectiveCwd = fs.realpathSync.native(resolvedCwd);
160
- if (header.cwd === effectiveCwd) return;
161
- header.cwd = effectiveCwd;
162
- fs.writeFileSync(sessionFile, `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`, "utf-8");
163
- }
164
-
165
- export interface ForkContextResolution {
166
- sessionFile: string;
167
- thinkingOverride?: "off";
168
- }
169
-
170
- export interface ForkContextResolver {
171
- sessionFileForIndex(index?: number): string | undefined;
172
- thinkingOverrideForIndex(index?: number): "off" | undefined;
173
- }
174
-
175
- interface ForkableSessionManager extends PreferredForkAvailability {
176
- openSession?: (file: string, dir?: string) => {
177
- createBranchedSession(leafId: string): string | undefined;
178
- getHeader?: () => BranchSessionEntry | undefined;
179
- getEntries?: () => BranchSessionEntry[] | undefined;
180
- };
181
- }
182
-
183
- export interface ForkContextResolverOptions {
184
- openSession?: ForkableSessionManager["openSession"];
185
- forceThinkingOffForIndex?: (index: number) => boolean;
186
- }
187
-
188
- /**
189
- * Create the fork resolver. Errors follow reference semantics: an explicit
190
- * fork requires a persisted parent session + current leaf, failing fast
191
- * rather than silently downgrading to fresh.
192
- */
193
- export function createForkContextResolver(
194
- sessionManager: ForkableSessionManager,
195
- requestedContext: unknown,
196
- options: ForkContextResolverOptions = {},
197
- ): ForkContextResolver {
198
- if (resolveSubagentContext(requestedContext) !== "fork") {
199
- return {
200
- sessionFileForIndex: () => undefined,
201
- thinkingOverrideForIndex: () => undefined,
202
- };
203
- }
204
-
205
- const parentSessionFile = sessionManager.getSessionFile();
206
- if (!parentSessionFile) {
207
- throw new Error("Forked subagent context requires a persisted parent session.");
208
- }
209
-
210
- const leafId = sessionManager.getLeafId();
211
- if (!leafId) {
212
- throw new Error("Forked subagent context requires a current leaf to fork from.");
213
- }
214
-
215
- const openSession =
216
- options.openSession ?? sessionManager.openSession ?? ((file: string, dir?: string) => SessionManager.open(file, dir));
217
-
218
- // Fork files nest under <parent-dir>/<parent-stem>/forks/ so top-level
219
- // session discovery (largest-mtime *.jsonl, non-recursive) never hijacks.
220
- const sessionDir = path.join(
221
- path.dirname(parentSessionFile),
222
- path.basename(parentSessionFile, ".jsonl"),
223
- "forks",
224
- );
225
- const cachedResolutions = new Map<number, ForkContextResolution>();
226
-
227
- const resolveFork = (index = 0): ForkContextResolution => {
228
- const cached = cachedResolutions.get(index);
229
- if (cached) return cached;
230
- try {
231
- if (!fs.existsSync(parentSessionFile)) {
232
- throw new Error(
233
- `Parent session file does not exist: ${parentSessionFile}. Pi has not persisted enough history to fork yet.`,
234
- );
235
- }
236
- const sourceManager = openSession(parentSessionFile, sessionDir);
237
- const sessionFile = sourceManager.createBranchedSession(leafId);
238
- if (!sessionFile) {
239
- throw new Error("Session manager did not return a forked session file.");
240
- }
241
- const forceThinkingOff = (sanitized: boolean): boolean =>
242
- sanitized && (options.forceThinkingOffForIndex?.(index) ?? true);
243
- let thinkingOverride: "off" | undefined;
244
- if (!fs.existsSync(sessionFile)) {
245
- const header = sourceManager.getHeader?.();
246
- const entries = sourceManager.getEntries?.() as BranchSessionEntry[] | undefined;
247
- if (!header || !entries) {
248
- throw new Error(
249
- `Session manager returned a forked session file that does not exist and cannot be persisted by fallback: ${sessionFile}`,
250
- );
251
- }
252
- if (forceThinkingOff(sanitizeUnsafeThinkingBlocks(entries as BranchSessionEntry[]))) {
253
- appendThinkingOffEntry(entries);
254
- thinkingOverride = "off";
255
- }
256
- fs.mkdirSync(path.dirname(sessionFile), { recursive: true });
257
- fs.writeFileSync(sessionFile, `${[header, ...entries].map((entry) => JSON.stringify(entry)).join("\n")}\n`, "utf-8");
258
- } else {
259
- const entries = readSessionEntries(sessionFile);
260
- if (sanitizeUnsafeThinkingBlocks(entries)) {
261
- if (forceThinkingOff(true)) {
262
- appendThinkingOffEntry(entries);
263
- thinkingOverride = "off";
264
- }
265
- fs.writeFileSync(sessionFile, `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`, "utf-8");
266
- }
267
- }
268
- const resolution = { sessionFile, ...(thinkingOverride ? { thinkingOverride } : {}) };
269
- cachedResolutions.set(index, resolution);
270
- return resolution;
271
- } catch (error) {
272
- const cause = error instanceof Error ? error : new Error(String(error));
273
- throw new Error(`Failed to create forked subagent session: ${cause.message}`, { cause });
274
- }
275
- };
276
-
277
- return {
278
- sessionFileForIndex(index = 0): string | undefined {
279
- return resolveFork(index).sessionFile;
280
- },
281
- thinkingOverrideForIndex(index = 0): "off" | undefined {
282
- return resolveFork(index).thinkingOverride;
283
- },
284
- };
285
- }
@@ -1,7 +0,0 @@
1
- import type { InfoRegistryLike } from "@pi-unipi/core/global-types";
2
-
3
- declare global {
4
- var __unipi_info_registry: InfoRegistryLike | undefined;
5
- }
6
-
7
- export {};