@agimon-ai/doompi 0.0.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +546 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  4. package/dist/bin/cli.cjs +3 -0
  5. package/dist/bin/cli.cjs.map +1 -0
  6. package/dist/bin/cli.d.cts +1 -0
  7. package/dist/bin/cli.d.mts +1 -0
  8. package/dist/bin/cli.mjs +3 -0
  9. package/dist/bin/cli.mjs.map +1 -0
  10. package/dist/bin/doomRunner.cjs +3 -0
  11. package/dist/bin/doomRunner.cjs.map +1 -0
  12. package/dist/bin/doomRunner.d.cts +1 -0
  13. package/dist/bin/doomRunner.d.mts +1 -0
  14. package/dist/bin/doomRunner.mjs +3 -0
  15. package/dist/bin/doomRunner.mjs.map +1 -0
  16. package/dist/cli/cliApp.cjs +2 -0
  17. package/dist/cli/cliApp.cjs.map +1 -0
  18. package/dist/cli/cliApp.d.cts +50 -0
  19. package/dist/cli/cliApp.d.cts.map +1 -0
  20. package/dist/cli/cliApp.d.mts +50 -0
  21. package/dist/cli/cliApp.d.mts.map +1 -0
  22. package/dist/cli/cliApp.mjs +2 -0
  23. package/dist/cli/cliApp.mjs.map +1 -0
  24. package/dist/cli/compatibilityOptions.cjs +2 -0
  25. package/dist/cli/compatibilityOptions.cjs.map +1 -0
  26. package/dist/cli/compatibilityOptions.d.cts +15 -0
  27. package/dist/cli/compatibilityOptions.d.cts.map +1 -0
  28. package/dist/cli/compatibilityOptions.d.mts +15 -0
  29. package/dist/cli/compatibilityOptions.d.mts.map +1 -0
  30. package/dist/cli/compatibilityOptions.mjs +2 -0
  31. package/dist/cli/compatibilityOptions.mjs.map +1 -0
  32. package/dist/cli/help.cjs +61 -0
  33. package/dist/cli/help.cjs.map +1 -0
  34. package/dist/cli/help.d.cts +6 -0
  35. package/dist/cli/help.d.cts.map +1 -0
  36. package/dist/cli/help.d.mts +6 -0
  37. package/dist/cli/help.d.mts.map +1 -0
  38. package/dist/cli/help.mjs +61 -0
  39. package/dist/cli/help.mjs.map +1 -0
  40. package/dist/cli/index.cjs +1 -0
  41. package/dist/cli/index.d.cts +5 -0
  42. package/dist/cli/index.d.mts +5 -0
  43. package/dist/cli/index.mjs +1 -0
  44. package/dist/cli/matrixOptions.cjs +2 -0
  45. package/dist/cli/matrixOptions.cjs.map +1 -0
  46. package/dist/cli/matrixOptions.d.cts +99 -0
  47. package/dist/cli/matrixOptions.d.cts.map +1 -0
  48. package/dist/cli/matrixOptions.d.mts +99 -0
  49. package/dist/cli/matrixOptions.d.mts.map +1 -0
  50. package/dist/cli/matrixOptions.mjs +2 -0
  51. package/dist/cli/matrixOptions.mjs.map +1 -0
  52. package/dist/cli/options.cjs +2 -0
  53. package/dist/cli/options.cjs.map +1 -0
  54. package/dist/cli/options.d.cts +7 -0
  55. package/dist/cli/options.d.cts.map +1 -0
  56. package/dist/cli/options.d.mts +7 -0
  57. package/dist/cli/options.d.mts.map +1 -0
  58. package/dist/cli/options.mjs +2 -0
  59. package/dist/cli/options.mjs.map +1 -0
  60. package/dist/commands/baseCommand.cjs +2 -0
  61. package/dist/commands/baseCommand.cjs.map +1 -0
  62. package/dist/commands/baseCommand.d.cts +36 -0
  63. package/dist/commands/baseCommand.d.cts.map +1 -0
  64. package/dist/commands/baseCommand.d.mts +36 -0
  65. package/dist/commands/baseCommand.d.mts.map +1 -0
  66. package/dist/commands/baseCommand.mjs +2 -0
  67. package/dist/commands/baseCommand.mjs.map +1 -0
  68. package/dist/commands/compatibilityCommand.cjs +2 -0
  69. package/dist/commands/compatibilityCommand.cjs.map +1 -0
  70. package/dist/commands/compatibilityCommand.d.cts +14 -0
  71. package/dist/commands/compatibilityCommand.d.cts.map +1 -0
  72. package/dist/commands/compatibilityCommand.d.mts +14 -0
  73. package/dist/commands/compatibilityCommand.d.mts.map +1 -0
  74. package/dist/commands/compatibilityCommand.mjs +2 -0
  75. package/dist/commands/compatibilityCommand.mjs.map +1 -0
  76. package/dist/commands/emitMcpCommand.cjs +2 -0
  77. package/dist/commands/emitMcpCommand.cjs.map +1 -0
  78. package/dist/commands/emitMcpCommand.d.cts +19 -0
  79. package/dist/commands/emitMcpCommand.d.cts.map +1 -0
  80. package/dist/commands/emitMcpCommand.d.mts +19 -0
  81. package/dist/commands/emitMcpCommand.d.mts.map +1 -0
  82. package/dist/commands/emitMcpCommand.mjs +2 -0
  83. package/dist/commands/emitMcpCommand.mjs.map +1 -0
  84. package/dist/commands/explainCommand.cjs +21 -0
  85. package/dist/commands/explainCommand.cjs.map +1 -0
  86. package/dist/commands/explainCommand.d.cts +63 -0
  87. package/dist/commands/explainCommand.d.cts.map +1 -0
  88. package/dist/commands/explainCommand.d.mts +63 -0
  89. package/dist/commands/explainCommand.d.mts.map +1 -0
  90. package/dist/commands/explainCommand.mjs +21 -0
  91. package/dist/commands/explainCommand.mjs.map +1 -0
  92. package/dist/commands/index.cjs +1 -0
  93. package/dist/commands/index.d.cts +8 -0
  94. package/dist/commands/index.d.mts +8 -0
  95. package/dist/commands/index.mjs +1 -0
  96. package/dist/commands/initCommand.cjs +3 -0
  97. package/dist/commands/initCommand.cjs.map +1 -0
  98. package/dist/commands/initCommand.d.cts +11 -0
  99. package/dist/commands/initCommand.d.cts.map +1 -0
  100. package/dist/commands/initCommand.d.mts +11 -0
  101. package/dist/commands/initCommand.d.mts.map +1 -0
  102. package/dist/commands/initCommand.mjs +3 -0
  103. package/dist/commands/initCommand.mjs.map +1 -0
  104. package/dist/commands/launchCommand.cjs +2 -0
  105. package/dist/commands/launchCommand.cjs.map +1 -0
  106. package/dist/commands/launchCommand.d.cts +31 -0
  107. package/dist/commands/launchCommand.d.cts.map +1 -0
  108. package/dist/commands/launchCommand.d.mts +31 -0
  109. package/dist/commands/launchCommand.d.mts.map +1 -0
  110. package/dist/commands/launchCommand.mjs +2 -0
  111. package/dist/commands/launchCommand.mjs.map +1 -0
  112. package/dist/commands/syncCommand.cjs +6 -0
  113. package/dist/commands/syncCommand.cjs.map +1 -0
  114. package/dist/commands/syncCommand.d.cts +37 -0
  115. package/dist/commands/syncCommand.d.cts.map +1 -0
  116. package/dist/commands/syncCommand.d.mts +37 -0
  117. package/dist/commands/syncCommand.d.mts.map +1 -0
  118. package/dist/commands/syncCommand.mjs +6 -0
  119. package/dist/commands/syncCommand.mjs.map +1 -0
  120. package/dist/config/harnessState.cjs +2 -0
  121. package/dist/config/harnessState.cjs.map +1 -0
  122. package/dist/config/harnessState.d.cts +24 -0
  123. package/dist/config/harnessState.d.cts.map +1 -0
  124. package/dist/config/harnessState.d.mts +24 -0
  125. package/dist/config/harnessState.d.mts.map +1 -0
  126. package/dist/config/harnessState.mjs +2 -0
  127. package/dist/config/harnessState.mjs.map +1 -0
  128. package/dist/config/index.cjs +1 -0
  129. package/dist/config/index.d.cts +7 -0
  130. package/dist/config/index.d.mts +7 -0
  131. package/dist/config/index.mjs +1 -0
  132. package/dist/config/projectTrust.cjs +2 -0
  133. package/dist/config/projectTrust.cjs.map +1 -0
  134. package/dist/config/projectTrust.d.cts +14 -0
  135. package/dist/config/projectTrust.d.cts.map +1 -0
  136. package/dist/config/projectTrust.d.mts +14 -0
  137. package/dist/config/projectTrust.d.mts.map +1 -0
  138. package/dist/config/projectTrust.mjs +2 -0
  139. package/dist/config/projectTrust.mjs.map +1 -0
  140. package/dist/entries/autoStop.cjs +2 -0
  141. package/dist/entries/autoStop.cjs.map +1 -0
  142. package/dist/entries/autoStop.d.cts +6 -0
  143. package/dist/entries/autoStop.d.cts.map +1 -0
  144. package/dist/entries/autoStop.d.mts +7 -0
  145. package/dist/entries/autoStop.d.mts.map +1 -0
  146. package/dist/entries/autoStop.mjs +2 -0
  147. package/dist/entries/autoStop.mjs.map +1 -0
  148. package/dist/entries/components/matrixPicker.cjs +2 -0
  149. package/dist/entries/components/matrixPicker.cjs.map +1 -0
  150. package/dist/entries/components/matrixPicker.d.cts +55 -0
  151. package/dist/entries/components/matrixPicker.d.cts.map +1 -0
  152. package/dist/entries/components/matrixPicker.d.mts +55 -0
  153. package/dist/entries/components/matrixPicker.d.mts.map +1 -0
  154. package/dist/entries/components/matrixPicker.mjs +2 -0
  155. package/dist/entries/components/matrixPicker.mjs.map +1 -0
  156. package/dist/entries/components/skillsOverlay.cjs +4 -0
  157. package/dist/entries/components/skillsOverlay.cjs.map +1 -0
  158. package/dist/entries/components/skillsOverlay.d.cts +58 -0
  159. package/dist/entries/components/skillsOverlay.d.cts.map +1 -0
  160. package/dist/entries/components/skillsOverlay.d.mts +58 -0
  161. package/dist/entries/components/skillsOverlay.d.mts.map +1 -0
  162. package/dist/entries/components/skillsOverlay.mjs +4 -0
  163. package/dist/entries/components/skillsOverlay.mjs.map +1 -0
  164. package/dist/entries/domains.cjs +2 -0
  165. package/dist/entries/domains.cjs.map +1 -0
  166. package/dist/entries/domains.d.cts +10 -0
  167. package/dist/entries/domains.d.cts.map +1 -0
  168. package/dist/entries/domains.d.mts +10 -0
  169. package/dist/entries/domains.d.mts.map +1 -0
  170. package/dist/entries/domains.mjs +2 -0
  171. package/dist/entries/domains.mjs.map +1 -0
  172. package/dist/entries/doom.cjs +2 -0
  173. package/dist/entries/doom.cjs.map +1 -0
  174. package/dist/entries/doom.d.cts +13 -0
  175. package/dist/entries/doom.d.cts.map +1 -0
  176. package/dist/entries/doom.d.mts +14 -0
  177. package/dist/entries/doom.d.mts.map +1 -0
  178. package/dist/entries/doom.mjs +2 -0
  179. package/dist/entries/doom.mjs.map +1 -0
  180. package/dist/entries/effort.cjs +2 -0
  181. package/dist/entries/effort.cjs.map +1 -0
  182. package/dist/entries/effort.d.cts +10 -0
  183. package/dist/entries/effort.d.cts.map +1 -0
  184. package/dist/entries/effort.d.mts +10 -0
  185. package/dist/entries/effort.d.mts.map +1 -0
  186. package/dist/entries/effort.mjs +2 -0
  187. package/dist/entries/effort.mjs.map +1 -0
  188. package/dist/entries/majorMode.cjs +6 -0
  189. package/dist/entries/majorMode.cjs.map +1 -0
  190. package/dist/entries/majorMode.d.cts +29 -0
  191. package/dist/entries/majorMode.d.cts.map +1 -0
  192. package/dist/entries/majorMode.d.mts +29 -0
  193. package/dist/entries/majorMode.d.mts.map +1 -0
  194. package/dist/entries/majorMode.mjs +6 -0
  195. package/dist/entries/majorMode.mjs.map +1 -0
  196. package/dist/entries/notifications.cjs +2 -0
  197. package/dist/entries/notifications.cjs.map +1 -0
  198. package/dist/entries/notifications.d.cts +13 -0
  199. package/dist/entries/notifications.d.cts.map +1 -0
  200. package/dist/entries/notifications.d.mts +13 -0
  201. package/dist/entries/notifications.d.mts.map +1 -0
  202. package/dist/entries/notifications.mjs +2 -0
  203. package/dist/entries/notifications.mjs.map +1 -0
  204. package/dist/entries/ollamaProvider.cjs +2 -0
  205. package/dist/entries/ollamaProvider.cjs.map +1 -0
  206. package/dist/entries/ollamaProvider.d.cts +6 -0
  207. package/dist/entries/ollamaProvider.d.cts.map +1 -0
  208. package/dist/entries/ollamaProvider.d.mts +7 -0
  209. package/dist/entries/ollamaProvider.d.mts.map +1 -0
  210. package/dist/entries/ollamaProvider.mjs +2 -0
  211. package/dist/entries/ollamaProvider.mjs.map +1 -0
  212. package/dist/entries/persona.cjs +2 -0
  213. package/dist/entries/persona.cjs.map +1 -0
  214. package/dist/entries/persona.d.cts +14 -0
  215. package/dist/entries/persona.d.cts.map +1 -0
  216. package/dist/entries/persona.d.mts +15 -0
  217. package/dist/entries/persona.d.mts.map +1 -0
  218. package/dist/entries/persona.mjs +2 -0
  219. package/dist/entries/persona.mjs.map +1 -0
  220. package/dist/entries/profile.cjs +3 -0
  221. package/dist/entries/profile.cjs.map +1 -0
  222. package/dist/entries/profile.d.cts +16 -0
  223. package/dist/entries/profile.d.cts.map +1 -0
  224. package/dist/entries/profile.d.mts +16 -0
  225. package/dist/entries/profile.d.mts.map +1 -0
  226. package/dist/entries/profile.mjs +3 -0
  227. package/dist/entries/profile.mjs.map +1 -0
  228. package/dist/entries/repositoryHooks.cjs +9 -0
  229. package/dist/entries/repositoryHooks.cjs.map +1 -0
  230. package/dist/entries/repositoryHooks.d.cts +7 -0
  231. package/dist/entries/repositoryHooks.d.cts.map +1 -0
  232. package/dist/entries/repositoryHooks.d.mts +8 -0
  233. package/dist/entries/repositoryHooks.d.mts.map +1 -0
  234. package/dist/entries/repositoryHooks.mjs +9 -0
  235. package/dist/entries/repositoryHooks.mjs.map +1 -0
  236. package/dist/entries/skills.cjs +2 -0
  237. package/dist/entries/skills.cjs.map +1 -0
  238. package/dist/entries/skills.d.cts +34 -0
  239. package/dist/entries/skills.d.cts.map +1 -0
  240. package/dist/entries/skills.d.mts +34 -0
  241. package/dist/entries/skills.d.mts.map +1 -0
  242. package/dist/entries/skills.mjs +2 -0
  243. package/dist/entries/skills.mjs.map +1 -0
  244. package/dist/entries/styleSystem.cjs +4 -0
  245. package/dist/entries/styleSystem.cjs.map +1 -0
  246. package/dist/entries/styleSystem.d.cts +32 -0
  247. package/dist/entries/styleSystem.d.cts.map +1 -0
  248. package/dist/entries/styleSystem.d.mts +32 -0
  249. package/dist/entries/styleSystem.d.mts.map +1 -0
  250. package/dist/entries/styleSystem.mjs +4 -0
  251. package/dist/entries/styleSystem.mjs.map +1 -0
  252. package/dist/index.cjs +1 -0
  253. package/dist/index.d.cts +34 -0
  254. package/dist/index.d.mts +34 -0
  255. package/dist/index.mjs +1 -0
  256. package/dist/interfaces/compatibility.d.cts +23 -0
  257. package/dist/interfaces/compatibility.d.cts.map +1 -0
  258. package/dist/interfaces/compatibility.d.mts +23 -0
  259. package/dist/interfaces/compatibility.d.mts.map +1 -0
  260. package/dist/interfaces/harness.d.cts +83 -0
  261. package/dist/interfaces/harness.d.cts.map +1 -0
  262. package/dist/interfaces/harness.d.mts +83 -0
  263. package/dist/interfaces/harness.d.mts.map +1 -0
  264. package/dist/logSinkTelemetry.cjs +2 -0
  265. package/dist/logSinkTelemetry.cjs.map +1 -0
  266. package/dist/logSinkTelemetry.d.cts +49 -0
  267. package/dist/logSinkTelemetry.d.cts.map +1 -0
  268. package/dist/logSinkTelemetry.d.mts +49 -0
  269. package/dist/logSinkTelemetry.d.mts.map +1 -0
  270. package/dist/logSinkTelemetry.mjs +2 -0
  271. package/dist/logSinkTelemetry.mjs.map +1 -0
  272. package/dist/node_modules/.pnpm/@juicesharp_rpiv-ask-user-question@2.2.0_@earendil-works_pi-coding-agent@0.84.1_support_6ba1249e24a50b62791c1c91c9f324c6/node_modules/@juicesharp/rpiv-ask-user-question/events.cjs +2 -0
  273. package/dist/node_modules/.pnpm/@juicesharp_rpiv-ask-user-question@2.2.0_@earendil-works_pi-coding-agent@0.84.1_support_6ba1249e24a50b62791c1c91c9f324c6/node_modules/@juicesharp/rpiv-ask-user-question/events.cjs.map +1 -0
  274. package/dist/node_modules/.pnpm/@juicesharp_rpiv-ask-user-question@2.2.0_@earendil-works_pi-coding-agent@0.84.1_support_6ba1249e24a50b62791c1c91c9f324c6/node_modules/@juicesharp/rpiv-ask-user-question/events.mjs +2 -0
  275. package/dist/node_modules/.pnpm/@juicesharp_rpiv-ask-user-question@2.2.0_@earendil-works_pi-coding-agent@0.84.1_support_6ba1249e24a50b62791c1c91c9f324c6/node_modules/@juicesharp/rpiv-ask-user-question/events.mjs.map +1 -0
  276. package/dist/services/compatibility/antigravity.cjs +2 -0
  277. package/dist/services/compatibility/antigravity.cjs.map +1 -0
  278. package/dist/services/compatibility/antigravity.d.cts +11 -0
  279. package/dist/services/compatibility/antigravity.d.cts.map +1 -0
  280. package/dist/services/compatibility/antigravity.d.mts +11 -0
  281. package/dist/services/compatibility/antigravity.d.mts.map +1 -0
  282. package/dist/services/compatibility/antigravity.mjs +2 -0
  283. package/dist/services/compatibility/antigravity.mjs.map +1 -0
  284. package/dist/services/compatibility/codex.cjs +2 -0
  285. package/dist/services/compatibility/codex.cjs.map +1 -0
  286. package/dist/services/compatibility/codex.d.cts +19 -0
  287. package/dist/services/compatibility/codex.d.cts.map +1 -0
  288. package/dist/services/compatibility/codex.d.mts +19 -0
  289. package/dist/services/compatibility/codex.d.mts.map +1 -0
  290. package/dist/services/compatibility/codex.mjs +2 -0
  291. package/dist/services/compatibility/codex.mjs.map +1 -0
  292. package/dist/services/compatibility/index.cjs +2 -0
  293. package/dist/services/compatibility/index.cjs.map +1 -0
  294. package/dist/services/compatibility/index.d.cts +16 -0
  295. package/dist/services/compatibility/index.d.cts.map +1 -0
  296. package/dist/services/compatibility/index.d.mts +16 -0
  297. package/dist/services/compatibility/index.d.mts.map +1 -0
  298. package/dist/services/compatibility/index.mjs +2 -0
  299. package/dist/services/compatibility/index.mjs.map +1 -0
  300. package/dist/services/compatibility/process.cjs +2 -0
  301. package/dist/services/compatibility/process.cjs.map +1 -0
  302. package/dist/services/compatibility/process.d.cts +35 -0
  303. package/dist/services/compatibility/process.d.cts.map +1 -0
  304. package/dist/services/compatibility/process.d.mts +35 -0
  305. package/dist/services/compatibility/process.d.mts.map +1 -0
  306. package/dist/services/compatibility/process.mjs +2 -0
  307. package/dist/services/compatibility/process.mjs.map +1 -0
  308. package/dist/services/compatibility/shared.cjs +2 -0
  309. package/dist/services/compatibility/shared.cjs.map +1 -0
  310. package/dist/services/compatibility/shared.d.cts +33 -0
  311. package/dist/services/compatibility/shared.d.cts.map +1 -0
  312. package/dist/services/compatibility/shared.d.mts +33 -0
  313. package/dist/services/compatibility/shared.d.mts.map +1 -0
  314. package/dist/services/compatibility/shared.mjs +2 -0
  315. package/dist/services/compatibility/shared.mjs.map +1 -0
  316. package/dist/services/compatibilityContext.cjs +2 -0
  317. package/dist/services/compatibilityContext.cjs.map +1 -0
  318. package/dist/services/compatibilityContext.d.cts +23 -0
  319. package/dist/services/compatibilityContext.d.cts.map +1 -0
  320. package/dist/services/compatibilityContext.d.mts +23 -0
  321. package/dist/services/compatibilityContext.d.mts.map +1 -0
  322. package/dist/services/compatibilityContext.mjs +2 -0
  323. package/dist/services/compatibilityContext.mjs.map +1 -0
  324. package/dist/services/composer.cjs +2 -0
  325. package/dist/services/composer.cjs.map +1 -0
  326. package/dist/services/composer.d.cts +133 -0
  327. package/dist/services/composer.d.cts.map +1 -0
  328. package/dist/services/composer.d.mts +133 -0
  329. package/dist/services/composer.d.mts.map +1 -0
  330. package/dist/services/composer.mjs +2 -0
  331. package/dist/services/composer.mjs.map +1 -0
  332. package/dist/services/extensionAssembler.cjs +2 -0
  333. package/dist/services/extensionAssembler.cjs.map +1 -0
  334. package/dist/services/extensionAssembler.d.cts +72 -0
  335. package/dist/services/extensionAssembler.d.cts.map +1 -0
  336. package/dist/services/extensionAssembler.d.mts +72 -0
  337. package/dist/services/extensionAssembler.d.mts.map +1 -0
  338. package/dist/services/extensionAssembler.mjs +2 -0
  339. package/dist/services/extensionAssembler.mjs.map +1 -0
  340. package/dist/services/extensionCompiler.cjs +2 -0
  341. package/dist/services/extensionCompiler.cjs.map +1 -0
  342. package/dist/services/extensionCompiler.mjs +2 -0
  343. package/dist/services/extensionCompiler.mjs.map +1 -0
  344. package/dist/services/harnessContext.cjs +2 -0
  345. package/dist/services/harnessContext.cjs.map +1 -0
  346. package/dist/services/harnessContext.d.cts +61 -0
  347. package/dist/services/harnessContext.d.cts.map +1 -0
  348. package/dist/services/harnessContext.d.mts +61 -0
  349. package/dist/services/harnessContext.d.mts.map +1 -0
  350. package/dist/services/harnessContext.mjs +2 -0
  351. package/dist/services/harnessContext.mjs.map +1 -0
  352. package/dist/services/index.cjs +1 -0
  353. package/dist/services/index.d.cts +14 -0
  354. package/dist/services/index.d.mts +14 -0
  355. package/dist/services/index.mjs +1 -0
  356. package/dist/services/matrixSwitcher.cjs +2 -0
  357. package/dist/services/matrixSwitcher.cjs.map +1 -0
  358. package/dist/services/matrixSwitcher.d.cts +46 -0
  359. package/dist/services/matrixSwitcher.d.cts.map +1 -0
  360. package/dist/services/matrixSwitcher.d.mts +46 -0
  361. package/dist/services/matrixSwitcher.d.mts.map +1 -0
  362. package/dist/services/matrixSwitcher.mjs +2 -0
  363. package/dist/services/matrixSwitcher.mjs.map +1 -0
  364. package/dist/services/mcpFilter.cjs +3 -0
  365. package/dist/services/mcpFilter.cjs.map +1 -0
  366. package/dist/services/mcpFilter.d.cts +40 -0
  367. package/dist/services/mcpFilter.d.cts.map +1 -0
  368. package/dist/services/mcpFilter.d.mts +40 -0
  369. package/dist/services/mcpFilter.d.mts.map +1 -0
  370. package/dist/services/mcpFilter.mjs +3 -0
  371. package/dist/services/mcpFilter.mjs.map +1 -0
  372. package/dist/services/piSettings.cjs +2 -0
  373. package/dist/services/piSettings.cjs.map +1 -0
  374. package/dist/services/piSettings.d.cts +24 -0
  375. package/dist/services/piSettings.d.cts.map +1 -0
  376. package/dist/services/piSettings.d.mts +24 -0
  377. package/dist/services/piSettings.d.mts.map +1 -0
  378. package/dist/services/piSettings.mjs +2 -0
  379. package/dist/services/piSettings.mjs.map +1 -0
  380. package/dist/services/resourceCollector.cjs +3 -0
  381. package/dist/services/resourceCollector.cjs.map +1 -0
  382. package/dist/services/resourceCollector.d.cts +16 -0
  383. package/dist/services/resourceCollector.d.cts.map +1 -0
  384. package/dist/services/resourceCollector.d.mts +16 -0
  385. package/dist/services/resourceCollector.d.mts.map +1 -0
  386. package/dist/services/resourceCollector.mjs +3 -0
  387. package/dist/services/resourceCollector.mjs.map +1 -0
  388. package/dist/services/skillCatalog.cjs +2 -0
  389. package/dist/services/skillCatalog.cjs.map +1 -0
  390. package/dist/services/skillCatalog.d.cts +56 -0
  391. package/dist/services/skillCatalog.d.cts.map +1 -0
  392. package/dist/services/skillCatalog.d.mts +56 -0
  393. package/dist/services/skillCatalog.d.mts.map +1 -0
  394. package/dist/services/skillCatalog.mjs +2 -0
  395. package/dist/services/skillCatalog.mjs.map +1 -0
  396. package/dist/services/skillSources.cjs +2 -0
  397. package/dist/services/skillSources.cjs.map +1 -0
  398. package/dist/services/skillSources.d.cts +24 -0
  399. package/dist/services/skillSources.d.cts.map +1 -0
  400. package/dist/services/skillSources.d.mts +24 -0
  401. package/dist/services/skillSources.d.mts.map +1 -0
  402. package/dist/services/skillSources.mjs +2 -0
  403. package/dist/services/skillSources.mjs.map +1 -0
  404. package/dist/services/syncState.cjs +2 -0
  405. package/dist/services/syncState.cjs.map +1 -0
  406. package/dist/services/syncState.d.cts +130 -0
  407. package/dist/services/syncState.d.cts.map +1 -0
  408. package/dist/services/syncState.d.mts +130 -0
  409. package/dist/services/syncState.d.mts.map +1 -0
  410. package/dist/services/syncState.mjs +2 -0
  411. package/dist/services/syncState.mjs.map +1 -0
  412. package/dist/utils/index.cjs +1 -0
  413. package/dist/utils/index.d.cts +5 -0
  414. package/dist/utils/index.d.mts +5 -0
  415. package/dist/utils/index.mjs +1 -0
  416. package/dist/utils/json.cjs +2 -0
  417. package/dist/utils/json.cjs.map +1 -0
  418. package/dist/utils/json.d.cts +23 -0
  419. package/dist/utils/json.d.cts.map +1 -0
  420. package/dist/utils/json.d.mts +23 -0
  421. package/dist/utils/json.d.mts.map +1 -0
  422. package/dist/utils/json.mjs +2 -0
  423. package/dist/utils/json.mjs.map +1 -0
  424. package/dist/utils/moduleResolution.cjs +2 -0
  425. package/dist/utils/moduleResolution.cjs.map +1 -0
  426. package/dist/utils/moduleResolution.d.cts +56 -0
  427. package/dist/utils/moduleResolution.d.cts.map +1 -0
  428. package/dist/utils/moduleResolution.d.mts +56 -0
  429. package/dist/utils/moduleResolution.d.mts.map +1 -0
  430. package/dist/utils/moduleResolution.mjs +2 -0
  431. package/dist/utils/moduleResolution.mjs.map +1 -0
  432. package/dist/utils/repository.cjs +2 -0
  433. package/dist/utils/repository.cjs.map +1 -0
  434. package/dist/utils/repository.d.cts +21 -0
  435. package/dist/utils/repository.d.cts.map +1 -0
  436. package/dist/utils/repository.d.mts +21 -0
  437. package/dist/utils/repository.d.mts.map +1 -0
  438. package/dist/utils/repository.mjs +2 -0
  439. package/dist/utils/repository.mjs.map +1 -0
  440. package/dist/utils/toolNames.cjs +2 -0
  441. package/dist/utils/toolNames.cjs.map +1 -0
  442. package/dist/utils/toolNames.d.cts +25 -0
  443. package/dist/utils/toolNames.d.cts.map +1 -0
  444. package/dist/utils/toolNames.d.mts +25 -0
  445. package/dist/utils/toolNames.d.mts.map +1 -0
  446. package/dist/utils/toolNames.mjs +2 -0
  447. package/dist/utils/toolNames.mjs.map +1 -0
  448. package/package.json +369 -0
@@ -0,0 +1,58 @@
1
+ import { SkillCatalog, SkillEntry } from "../../services/skillCatalog.cjs";
2
+ import { ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
3
+ import { DoomOverlay, DoomOverlayChrome, DoomOverlayTui } from "@agimon-ai/doompi-ui/components/doomOverlay";
4
+
5
+ //#region src/entries/components/skillsOverlay.d.ts
6
+ type SkillsOverlayResult = {
7
+ kind: 'invoke';
8
+ skill: SkillEntry;
9
+ } | undefined;
10
+ interface SkillsOverlayOptions {
11
+ catalog: SkillCatalog;
12
+ /** Repo root, so paths render relative rather than as absolute noise. */
13
+ repoRoot: string;
14
+ readFile?: (filePath: string) => string;
15
+ }
16
+ /** Drops YAML frontmatter so the preview starts at the prose, as Pi does. */
17
+ declare function skillBody(content: string): string;
18
+ declare class SkillsOverlayComponent extends DoomOverlay {
19
+ private readonly options;
20
+ private readonly done;
21
+ private readonly readFile;
22
+ private readonly bodyCache;
23
+ /** Index into the skill rows, not into every row: headings are not selectable. */
24
+ private selected;
25
+ private focus;
26
+ private filtering;
27
+ private query;
28
+ private bodyOffset;
29
+ constructor(tui: DoomOverlayTui, theme: Theme, options: SkillsOverlayOptions, done: (result: SkillsOverlayResult) => void);
30
+ /** Every row, honouring the active filter. The tree does not fold. */
31
+ private rows;
32
+ /**
33
+ * Where the skill rows sit in `rows()`.
34
+ *
35
+ * The selection indexes this list rather than `rows()`, which is what keeps
36
+ * headings unselectable without the key handler having to hunt past them, and
37
+ * what puts the opening selection on a skill rather than on the first group.
38
+ */
39
+ private selectable;
40
+ private currentRow;
41
+ private move;
42
+ private bodyLines;
43
+ handleInput(data: string): void;
44
+ private handleFilterInput;
45
+ protected getChrome(): DoomOverlayChrome;
46
+ private badge;
47
+ /** Footer hints as capped keys: `[ enter ] use skill`, per the mockup. */
48
+ private hintLine;
49
+ protected renderBody(width: number, height: number): string[];
50
+ private renderStacked;
51
+ private treeLines;
52
+ private field;
53
+ private detailLines;
54
+ }
55
+ declare function openSkillsOverlay(ctx: ExtensionContext, options: SkillsOverlayOptions): Promise<SkillsOverlayResult>;
56
+ //#endregion
57
+ export { SkillsOverlayComponent, SkillsOverlayOptions, SkillsOverlayResult, openSkillsOverlay, skillBody };
58
+ //# sourceMappingURL=skillsOverlay.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillsOverlay.d.cts","names":[],"sources":["../../../src/entries/components/skillsOverlay.ts"],"mappings":";;;;;KA4EY,mBAAA;EAAwB,IAAA;EAAgB,KAAA,EAAO,UAAA;AAAA;AAAA,UAE1C,oBAAA;EACf,OAAA,EAAS,YAAA;EAGG;EADZ,QAAA;EACA,QAAA,IAAY,QAAA;AAAA;;iBAoCE,SAAA,CAAU,OAAA;AAAA,cAUb,sBAAA,SAA+B,WAAA;EAAA,iBACzB,OAAA;EAAA,iBACA,IAAA;EAAA,iBACA,QAAA;EAAA,iBACA,SAAA;EAUV;EAAA,QAPC,QAAA;EAAA,QACA,KAAA;EAAA,QACA,SAAA;EAAA,QACA,KAAA;EAAA,QACA,UAAA;cAGN,GAAA,EAAK,cAAA,EACL,KAAA,EAAO,KAAA,EACP,OAAA,EAAS,oBAAA,EACT,IAAA,GAAO,MAAA,EAAQ,mBAAA;EAjBoC;EAAA,QA0B7C,IAAA;EAzBS;;;;;;;EAAA,QAsDT,UAAA;EAAA,QAMA,UAAA;EAAA,QAOA,IAAA;EAAA,QAQA,SAAA;EAiBR,WAAA,CAAY,IAAA;EAAA,QA8CJ,iBAAA;EAAA,UAqBE,SAAA,CAAA,GAAa,iBAAA;EAAA,QAef,KAAA;EA/JN;EAAA,QAoKM,QAAA;EAAA,UAME,UAAA,CAAW,KAAA,UAAe,MAAA;EAAA,QAiB5B,aAAA;EAAA,QAaA,SAAA;EAAA,QAoCA,KAAA;EAAA,QAQA,WAAA;AAAA;AAAA,iBAqCY,iBAAA,CACpB,GAAA,EAAK,gBAAA,EACL,OAAA,EAAS,oBAAA,GACR,OAAA,CAAQ,mBAAA"}
@@ -0,0 +1,58 @@
1
+ import { SkillCatalog, SkillEntry } from "../../services/skillCatalog.mjs";
2
+ import { ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
3
+ import { DoomOverlay, DoomOverlayChrome, DoomOverlayTui } from "@agimon-ai/doompi-ui/components/doomOverlay";
4
+
5
+ //#region src/entries/components/skillsOverlay.d.ts
6
+ type SkillsOverlayResult = {
7
+ kind: 'invoke';
8
+ skill: SkillEntry;
9
+ } | undefined;
10
+ interface SkillsOverlayOptions {
11
+ catalog: SkillCatalog;
12
+ /** Repo root, so paths render relative rather than as absolute noise. */
13
+ repoRoot: string;
14
+ readFile?: (filePath: string) => string;
15
+ }
16
+ /** Drops YAML frontmatter so the preview starts at the prose, as Pi does. */
17
+ declare function skillBody(content: string): string;
18
+ declare class SkillsOverlayComponent extends DoomOverlay {
19
+ private readonly options;
20
+ private readonly done;
21
+ private readonly readFile;
22
+ private readonly bodyCache;
23
+ /** Index into the skill rows, not into every row: headings are not selectable. */
24
+ private selected;
25
+ private focus;
26
+ private filtering;
27
+ private query;
28
+ private bodyOffset;
29
+ constructor(tui: DoomOverlayTui, theme: Theme, options: SkillsOverlayOptions, done: (result: SkillsOverlayResult) => void);
30
+ /** Every row, honouring the active filter. The tree does not fold. */
31
+ private rows;
32
+ /**
33
+ * Where the skill rows sit in `rows()`.
34
+ *
35
+ * The selection indexes this list rather than `rows()`, which is what keeps
36
+ * headings unselectable without the key handler having to hunt past them, and
37
+ * what puts the opening selection on a skill rather than on the first group.
38
+ */
39
+ private selectable;
40
+ private currentRow;
41
+ private move;
42
+ private bodyLines;
43
+ handleInput(data: string): void;
44
+ private handleFilterInput;
45
+ protected getChrome(): DoomOverlayChrome;
46
+ private badge;
47
+ /** Footer hints as capped keys: `[ enter ] use skill`, per the mockup. */
48
+ private hintLine;
49
+ protected renderBody(width: number, height: number): string[];
50
+ private renderStacked;
51
+ private treeLines;
52
+ private field;
53
+ private detailLines;
54
+ }
55
+ declare function openSkillsOverlay(ctx: ExtensionContext, options: SkillsOverlayOptions): Promise<SkillsOverlayResult>;
56
+ //#endregion
57
+ export { SkillsOverlayComponent, SkillsOverlayOptions, SkillsOverlayResult, openSkillsOverlay, skillBody };
58
+ //# sourceMappingURL=skillsOverlay.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillsOverlay.d.mts","names":[],"sources":["../../../src/entries/components/skillsOverlay.ts"],"mappings":";;;;;KA4EY,mBAAA;EAAwB,IAAA;EAAgB,KAAA,EAAO,UAAA;AAAA;AAAA,UAE1C,oBAAA;EACf,OAAA,EAAS,YAAA;EAGG;EADZ,QAAA;EACA,QAAA,IAAY,QAAA;AAAA;;iBAoCE,SAAA,CAAU,OAAA;AAAA,cAUb,sBAAA,SAA+B,WAAA;EAAA,iBACzB,OAAA;EAAA,iBACA,IAAA;EAAA,iBACA,QAAA;EAAA,iBACA,SAAA;EAUV;EAAA,QAPC,QAAA;EAAA,QACA,KAAA;EAAA,QACA,SAAA;EAAA,QACA,KAAA;EAAA,QACA,UAAA;cAGN,GAAA,EAAK,cAAA,EACL,KAAA,EAAO,KAAA,EACP,OAAA,EAAS,oBAAA,EACT,IAAA,GAAO,MAAA,EAAQ,mBAAA;EAjBoC;EAAA,QA0B7C,IAAA;EAzBS;;;;;;;EAAA,QAsDT,UAAA;EAAA,QAMA,UAAA;EAAA,QAOA,IAAA;EAAA,QAQA,SAAA;EAiBR,WAAA,CAAY,IAAA;EAAA,QA8CJ,iBAAA;EAAA,UAqBE,SAAA,CAAA,GAAa,iBAAA;EAAA,QAef,KAAA;EA/JN;EAAA,QAoKM,QAAA;EAAA,UAME,UAAA,CAAW,KAAA,UAAe,MAAA;EAAA,QAiB5B,aAAA;EAAA,QAaA,SAAA;EAAA,QAoCA,KAAA;EAAA,QAQA,WAAA;AAAA;AAAA,iBAqCY,iBAAA,CACpB,GAAA,EAAK,gBAAA,EACL,OAAA,EAAS,oBAAA,GACR,OAAA,CAAQ,mBAAA"}
@@ -0,0 +1,4 @@
1
+ import e from"node:path";import t from"node:fs";import{matchesKey as n,truncateToWidth as r,visibleWidth as i}from"@earendil-works/pi-tui";import{DOOM_FULLSCREEN_UI_OPTIONS as a,DOOM_OVERLAY_ACCENT as o,DoomOverlay as s}from"@agimon-ai/doompi-ui/components/doomOverlay";import{formatTokens as c}from"@agimon-ai/doompi-ui/rendering";const l=`CATALOG`,u=[[`↑↓`,`select`],[`enter`,`use skill`],[`tab`,`detail pane`],[`/`,`filter`],[`esc`,`close`]],d=[[`pgup/pgdn`,`scroll`],[`tab`,`tree`],[`esc`,`close`]],f=[[`type`,`to filter`],[`enter`,`keep`],[`esc`,`clear`]];function p(e,t){let n=r(e,Math.max(0,t),`…`);return n+` `.repeat(Math.max(0,t-i(n)))}function m(e,t){if(t<=0)return[];let n=[],r=``;for(let a of e.split(/\s+/).filter(Boolean))r.length===0?r=a:i(r)+1+i(a)<=t?r+=` ${a}`:(n.push(r),r=a);return r.length>0&&n.push(r),n}function h(e){let t=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?([\s\S]*)$/);return(t?t[1]??``:e).replace(/^\s+/,``)}function g(e,t){let n=t.toLowerCase();return e.name.toLowerCase().includes(n)||e.description.toLowerCase().includes(n)}var _=class extends s{options;done;readFile;bodyCache=new Map;selected=0;focus=`tree`;filtering=!1;query=``;bodyOffset=0;constructor(e,n,r,i){super(e,n),this.options=r,this.done=i,this.readFile=r.readFile??(e=>t.readFileSync(e,`utf8`))}rows(){let e=this.query.trim(),t=[];for(let n of this.options.catalog.groups){let r=e?n.owners.map(t=>({...t,skills:t.skills.filter(t=>g(t,e))})).filter(e=>e.skills.length>0):n.owners;if(r.length===0)continue;let i=r.reduce((e,t)=>e+t.skills.length,0);t.push({kind:`group`,depth:0,label:n.label,tag:String(i)});for(let e of r){t.push({kind:`owner`,depth:1,label:e.owner,tag:String(e.skills.length)});for(let n of e.skills)t.push({kind:`skill`,depth:2,label:n.name,tag:``,skill:n})}}return t}selectable(e){let t=[];for(let[n,r]of e.entries())r.skill&&t.push(n);return t}currentRow(){let e=this.rows(),t=this.selectable(e);if(t.length!==0)return e[t[Math.min(this.selected,t.length-1)]]}move(e){let t=this.selectable(this.rows()).length;t!==0&&(this.selected=Math.max(0,Math.min(t-1,this.selected+e)),this.bodyOffset=0,this.invalidate())}bodyLines(e,t){let n=this.bodyCache.get(e.filePath);if(!n){let t;try{t=h(this.readFile(e.filePath))}catch{t=`Could not read SKILL.md.`}n=t.split(/\r?\n/),this.bodyCache.set(e.filePath,n)}return n.flatMap(e=>e.trim()===``?[``]:m(e,t))}handleInput(e){if(this.filtering)return this.handleFilterInput(e);if(n(e,`escape`)){if(this.query){this.query=``,this.selected=0,this.invalidate();return}this.done(void 0);return}if(e===` `||n(e,`tab`)){this.focus=this.focus===`tree`?`body`:`tree`,this.invalidate();return}if(n(e,`pageUp`)){this.bodyOffset=Math.max(0,this.bodyOffset-10),this.invalidate();return}if(n(e,`pageDown`)){this.bodyOffset+=10,this.invalidate();return}if(this.focus!==`body`){if(e===`/`){this.filtering=!0,this.invalidate();return}if(n(e,`up`)||n(e,`k`))return this.move(-1);if(n(e,`down`)||n(e,`j`))return this.move(1);if(e===`\r`||e===`
2
+ `||n(e,`enter`)){let e=this.currentRow()?.skill;e&&this.done({kind:`invoke`,skill:e})}}}handleFilterInput(e){if(n(e,`escape`)){this.filtering=!1,this.query=``,this.selected=0,this.invalidate();return}if(e===`\r`||e===`
3
+ `){this.filtering=!1,this.invalidate();return}e===``?this.query=this.query.slice(0,-1):e.length===1&&e>=` `&&(this.query+=e),this.selected=0,this.invalidate()}getChrome(){let{skillCount:e,promptTokens:t,bodyTokens:n}=this.options.catalog,r=this.options.catalog.groups.filter(e=>e.owners.length>0).length,i=this.filtering?f:this.focus===`body`?d:u;return{title:`SKILLS`,accent:o,breadcrumb:`SPC › e / extension › s / skills`,headerRight:`${e} skills · ${r} sources · ${c(t)} always-on · ${c(n)} full`,footer:this.hintLine(i)}}badge(e,t,n=`text`){return this.theme.bg(t,this.theme.fg(n,` ${e} `))}hintLine(e){return e.map(([e,t])=>`${this.badge(e,`selectedBg`)}${this.theme.fg(`dim`,` ${t}`)}`).join(this.theme.fg(`dim`,` `))}renderBody(e,t){if(e<60)return this.renderStacked(e,t);let n=Math.max(20,Math.floor((e-1)*.3333333333333333)),i=Math.max(1,e-n-1),a=Math.max(1,n-1),o=Math.max(1,i-1),s=this.treeLines(a,t),c=this.detailLines(o,t),l=this.theme.fg(`borderMuted`,`│`);return Array.from({length:t},(t,n)=>r(`${p(s[n]??``,a)} ${l} ${p(c[n]??``,o)}`,e,`…`))}renderStacked(e,t){let n=Math.max(1,Math.floor((t-1)/2)),r=Math.max(0,t-n-1),i=this.treeLines(e,n),a=this.detailLines(e,r);return[...i.slice(0,n),...Array.from({length:Math.max(0,n-i.length)},()=>``),this.theme.fg(`borderMuted`,`─`.repeat(e)),...a.slice(0,r)]}treeLines(e,t){let n=this.filtering||this.query?`${l} /${this.query}`:l,a=[this.theme.bold(this.theme.fg(`accent`,n)),``],o=this.rows();if(o.length===0)return a.push(this.theme.fg(`dim`,`No skills discovered.`)),a;let s=Math.max(1,t-a.length),c=this.selectable(o),u=c[Math.min(this.selected,c.length-1)]??-1,d=Math.max(0,Math.min(u-s+1,Math.max(0,o.length-s)));for(let[t,n]of o.slice(d,d+s).entries()){let o=d+t===u,s=o?this.theme.fg(`accent`,`›`):` `,c=` `.repeat(n.depth*2),l=n.kind===`group`?`accent`:n.kind===`owner`?`dim`:`text`,f=this.theme.fg(l,`${c}${n.label}`);(n.kind===`group`||o)&&(f=this.theme.bold(f));let m=n.tag?r(n.tag,Math.floor(e*.4),`…`):``,h=m?i(m)+1:0,g=p(`${s} ${f}`,Math.max(1,e-h)),_=m?`${g} ${this.theme.fg(`dim`,m)}`:g;a.push(o?this.theme.bg(`selectedBg`,p(_,e)):_)}return a}field(e,t,n,r){return m(t,Math.max(1,r-13)).map((t,r)=>`${this.theme.fg(`dim`,p(r===0?e:``,13))}${this.theme.fg(n,t)}`)}detailLines(t,n){let r=this.currentRow()?.skill;if(!r)return[``,``,this.theme.fg(`dim`,`Select a skill to read it.`)];let i=e.relative(this.options.repoRoot,r.filePath)||r.filePath,a=[this.theme.bold(this.theme.fg(`accent`,r.name)),``,...this.field(`description`,r.description,`text`,t),...this.field(`source`,`${r.group} › ${r.owner}`,`success`,t),...this.field(`path`,i,`text`,t),...this.field(`invocable`,r.modelInvocable?`model · /skill:${r.name}`:`/skill:${r.name} only`,`success`,t)],o=this.bodyLines(r,t),s=Math.max(0,n-a.length-2);this.bodyOffset=Math.min(this.bodyOffset,Math.max(0,o.length-s));let c=o.slice(this.bodyOffset,this.bodyOffset+s),l=o.length>s?`lines ${this.bodyOffset+1}-${this.bodyOffset+c.length} / ${o.length}`:`SKILL.md`,u=this.focus===`body`?this.theme.fg(`accent`,` ◀ focused`):``;a.push(``,`${this.theme.fg(`dim`,l)}${u}`);for(let e of c)a.push(this.theme.fg(`dim`,e));return a}};async function v(e,t){return e.ui.custom((e,n,r,i)=>new _(e,n,t,i),a)}export{_ as SkillsOverlayComponent,v as openSkillsOverlay,h as skillBody};
4
+ //# sourceMappingURL=skillsOverlay.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillsOverlay.mjs","names":[],"sources":["../../../src/entries/components/skillsOverlay.ts"],"sourcesContent":["/**\n * Skills: the `SPC e s` overlay.\n *\n * A tree of the skills this session loaded on the left, the selected skill's\n * frontmatter and body on the right. Everything listed is loaded, so the\n * surface answers \"what do I have, and what does it cost\" rather than doubling\n * as a domain browser.\n *\n * The tree is flat and always open: groups and owners are headings, only skills\n * take the selection. Rendering is pure: the catalogue is resolved once by the\n * caller and passed in, so `render(width)` returns lines with no side effects\n * and the whole surface can be asserted as text without a live terminal.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport {\n DOOM_FULLSCREEN_UI_OPTIONS,\n DOOM_OVERLAY_ACCENT,\n DoomOverlay,\n type DoomOverlayChrome,\n type DoomOverlayTui,\n} from '@agimon-ai/doompi-ui/components/doomOverlay';\nimport { formatTokens } from '@agimon-ai/doompi-ui/rendering';\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { matchesKey, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\nimport type { SkillCatalog, SkillEntry } from '../../services/skillCatalog.ts';\n\ntype ThemeColor = Parameters<Theme['fg']>[0];\ntype ThemeBg = Parameters<Theme['bg']>[0];\n\nconst MIN_WIDTH = 60;\n/** A third for the tree, two thirds for the skill being read. */\nconst TREE_PANE_RATIO = 1 / 3;\n/** One blank column each side of the pane divider so neither column touches it. */\nconst PANE_GUTTER = 1;\nconst MIN_PANE_WIDTH = 20;\nconst LABEL_COLUMN = 13;\n/** Ceiling on the columns a row's right-hand tag may take from its label. */\nconst TAG_SHARE = 0.4;\nconst INDENT = 2;\nconst ELLIPSIS = '…';\nconst SELECTION_MARKER = '›';\nconst RULE = '─';\nconst KEY_TAB = '\\t';\nconst KEY_ENTER = '\\r';\nconst KEY_NEWLINE = '\\n';\nconst KEY_BACKSPACE = '\\x7f';\nconst FILTER_KEY = '/';\nconst BODY_PAGE = 10;\n\nconst TITLE = 'SKILLS';\nconst BREADCRUMB = 'SPC › e / extension › s / skills';\nconst HEADING = 'CATALOG';\nconst EMPTY_TREE = 'No skills discovered.';\nconst NO_SELECTION = 'Select a skill to read it.';\nconst UNREADABLE = 'Could not read SKILL.md.';\n\nconst TREE_HINTS: readonly (readonly [string, string])[] = [\n ['↑↓', 'select'],\n ['enter', 'use skill'],\n ['tab', 'detail pane'],\n ['/', 'filter'],\n ['esc', 'close'],\n];\nconst BODY_HINTS: readonly (readonly [string, string])[] = [\n ['pgup/pgdn', 'scroll'],\n ['tab', 'tree'],\n ['esc', 'close'],\n];\nconst FILTER_HINTS: readonly (readonly [string, string])[] = [\n ['type', 'to filter'],\n ['enter', 'keep'],\n ['esc', 'clear'],\n];\n\nexport type SkillsOverlayResult = { kind: 'invoke'; skill: SkillEntry } | undefined;\n\nexport interface SkillsOverlayOptions {\n catalog: SkillCatalog;\n /** Repo root, so paths render relative rather than as absolute noise. */\n repoRoot: string;\n readFile?: (filePath: string) => string;\n}\n\ntype RowKind = 'group' | 'owner' | 'skill';\n\ninterface TreeRow {\n kind: RowKind;\n depth: number;\n label: string;\n tag: string;\n /** Only a skill row carries one; group and owner rows are headings. */\n skill?: SkillEntry;\n}\n\nfunction fit(text: string, width: number): string {\n const clipped = truncateToWidth(text, Math.max(0, width), ELLIPSIS);\n return clipped + ' '.repeat(Math.max(0, width - visibleWidth(clipped)));\n}\n\nfunction wrap(text: string, width: number): string[] {\n if (width <= 0) return [];\n const lines: string[] = [];\n let current = '';\n for (const word of text.split(/\\s+/).filter(Boolean)) {\n if (current.length === 0) current = word;\n else if (visibleWidth(current) + 1 + visibleWidth(word) <= width) current += ` ${word}`;\n else {\n lines.push(current);\n current = word;\n }\n }\n if (current.length > 0) lines.push(current);\n return lines;\n}\n\n/** Drops YAML frontmatter so the preview starts at the prose, as Pi does. */\nexport function skillBody(content: string): string {\n const match = content.match(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n return (match ? (match[1] ?? '') : content).replace(/^\\s+/, '');\n}\n\nfunction matches(skill: SkillEntry, query: string): boolean {\n const needle = query.toLowerCase();\n return skill.name.toLowerCase().includes(needle) || skill.description.toLowerCase().includes(needle);\n}\n\nexport class SkillsOverlayComponent extends DoomOverlay {\n private readonly options: SkillsOverlayOptions;\n private readonly done: (result: SkillsOverlayResult) => void;\n private readonly readFile: (filePath: string) => string;\n private readonly bodyCache = new Map<string, string[]>();\n\n /** Index into the skill rows, not into every row: headings are not selectable. */\n private selected = 0;\n private focus: 'tree' | 'body' = 'tree';\n private filtering = false;\n private query = '';\n private bodyOffset = 0;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n options: SkillsOverlayOptions,\n done: (result: SkillsOverlayResult) => void,\n ) {\n super(tui, theme);\n this.options = options;\n this.done = done;\n this.readFile = options.readFile ?? ((filePath) => fs.readFileSync(filePath, 'utf8'));\n }\n\n /** Every row, honouring the active filter. The tree does not fold. */\n private rows(): TreeRow[] {\n const query = this.query.trim();\n const rows: TreeRow[] = [];\n for (const group of this.options.catalog.groups) {\n const owners = query\n ? group.owners\n .map((owner) => ({ ...owner, skills: owner.skills.filter((skill) => matches(skill, query)) }))\n .filter((owner) => owner.skills.length > 0)\n : group.owners;\n if (owners.length === 0) continue;\n const count = owners.reduce((total, owner) => total + owner.skills.length, 0);\n rows.push({ kind: 'group', depth: 0, label: group.label, tag: String(count) });\n for (const owner of owners) {\n rows.push({ kind: 'owner', depth: 1, label: owner.owner, tag: String(owner.skills.length) });\n for (const skill of owner.skills) {\n rows.push({ kind: 'skill', depth: 2, label: skill.name, tag: '', skill });\n }\n }\n }\n return rows;\n }\n\n /**\n * Where the skill rows sit in `rows()`.\n *\n * The selection indexes this list rather than `rows()`, which is what keeps\n * headings unselectable without the key handler having to hunt past them, and\n * what puts the opening selection on a skill rather than on the first group.\n */\n private selectable(rows: TreeRow[]): number[] {\n const indexes: number[] = [];\n for (const [index, row] of rows.entries()) if (row.skill) indexes.push(index);\n return indexes;\n }\n\n private currentRow(): TreeRow | undefined {\n const rows = this.rows();\n const indexes = this.selectable(rows);\n if (indexes.length === 0) return undefined;\n return rows[indexes[Math.min(this.selected, indexes.length - 1)] as number];\n }\n\n private move(delta: number): void {\n const count = this.selectable(this.rows()).length;\n if (count === 0) return;\n this.selected = Math.max(0, Math.min(count - 1, this.selected + delta));\n this.bodyOffset = 0;\n this.invalidate();\n }\n\n private bodyLines(skill: SkillEntry, width: number): string[] {\n let raw = this.bodyCache.get(skill.filePath);\n if (!raw) {\n let source: string;\n try {\n source = skillBody(this.readFile(skill.filePath));\n } catch {\n source = UNREADABLE;\n }\n raw = source.split(/\\r?\\n/);\n this.bodyCache.set(skill.filePath, raw);\n }\n // Wrapped at render width rather than at read time, so a resize reflows the\n // same cached file instead of re-reading it.\n return raw.flatMap((line) => (line.trim() === '' ? [''] : wrap(line, width)));\n }\n\n handleInput(data: string): void {\n if (this.filtering) return this.handleFilterInput(data);\n\n if (matchesKey(data, 'escape')) {\n // The filter clears before the overlay closes: escaping straight out of a\n // narrowed tree loses the search with no way to see what it hid.\n if (this.query) {\n this.query = '';\n this.selected = 0;\n this.invalidate();\n return;\n }\n this.done(undefined);\n return;\n }\n if (data === KEY_TAB || matchesKey(data, 'tab')) {\n this.focus = this.focus === 'tree' ? 'body' : 'tree';\n this.invalidate();\n return;\n }\n if (matchesKey(data, 'pageUp')) {\n this.bodyOffset = Math.max(0, this.bodyOffset - BODY_PAGE);\n this.invalidate();\n return;\n }\n if (matchesKey(data, 'pageDown')) {\n this.bodyOffset += BODY_PAGE;\n this.invalidate();\n return;\n }\n if (this.focus === 'body') return;\n\n if (data === FILTER_KEY) {\n this.filtering = true;\n this.invalidate();\n return;\n }\n if (matchesKey(data, 'up') || matchesKey(data, 'k')) return this.move(-1);\n if (matchesKey(data, 'down') || matchesKey(data, 'j')) return this.move(1);\n\n if (data === KEY_ENTER || data === KEY_NEWLINE || matchesKey(data, 'enter')) {\n const skill = this.currentRow()?.skill;\n if (skill) this.done({ kind: 'invoke', skill });\n }\n }\n\n private handleFilterInput(data: string): void {\n if (matchesKey(data, 'escape')) {\n this.filtering = false;\n this.query = '';\n this.selected = 0;\n this.invalidate();\n return;\n }\n if (data === KEY_ENTER || data === KEY_NEWLINE) {\n this.filtering = false;\n this.invalidate();\n return;\n }\n if (data === KEY_BACKSPACE) this.query = this.query.slice(0, -1);\n // Control sequences are dropped rather than appended: an arrow key would\n // otherwise land in the query as a raw escape sequence.\n else if (data.length === 1 && data >= ' ') this.query += data;\n this.selected = 0;\n this.invalidate();\n }\n\n protected getChrome(): DoomOverlayChrome {\n const { skillCount, promptTokens, bodyTokens } = this.options.catalog;\n const sources = this.options.catalog.groups.filter((group) => group.owners.length > 0).length;\n const hints = this.filtering ? FILTER_HINTS : this.focus === 'body' ? BODY_HINTS : TREE_HINTS;\n return {\n title: TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: BREADCRUMB,\n // Two token figures, because they answer different questions: what the\n // catalogue costs on every request, and what reading all of it would cost.\n headerRight: `${skillCount} skills · ${sources} sources · ${formatTokens(promptTokens)} always-on · ${formatTokens(bodyTokens)} full`,\n footer: this.hintLine(hints),\n };\n }\n\n private badge(text: string, background: ThemeBg, colour: ThemeColor = 'text'): string {\n return this.theme.bg(background, this.theme.fg(colour, ` ${text} `));\n }\n\n /** Footer hints as capped keys: `[ enter ] use skill`, per the mockup. */\n private hintLine(hints: readonly (readonly [string, string])[]): string {\n return hints\n .map(([key, label]) => `${this.badge(key, 'selectedBg')}${this.theme.fg('dim', ` ${label}`)}`)\n .join(this.theme.fg('dim', ' '));\n }\n\n protected renderBody(width: number, height: number): string[] {\n if (width < MIN_WIDTH) return this.renderStacked(width, height);\n\n const treeWidth = Math.max(MIN_PANE_WIDTH, Math.floor((width - 1) * TREE_PANE_RATIO));\n const detailWidth = Math.max(1, width - treeWidth - 1);\n const treeContent = Math.max(1, treeWidth - PANE_GUTTER);\n const detailContent = Math.max(1, detailWidth - PANE_GUTTER);\n\n const left = this.treeLines(treeContent, height);\n const right = this.detailLines(detailContent, height);\n const divider = this.theme.fg('borderMuted', '│');\n return Array.from({ length: height }, (_, index) => {\n const row = `${fit(left[index] ?? '', treeContent)} ${divider} ${fit(right[index] ?? '', detailContent)}`;\n return truncateToWidth(row, width, ELLIPSIS);\n });\n }\n\n private renderStacked(width: number, height: number): string[] {\n const topHeight = Math.max(1, Math.floor((height - 1) / 2));\n const bottomHeight = Math.max(0, height - topHeight - 1);\n const top = this.treeLines(width, topHeight);\n const bottom = this.detailLines(width, bottomHeight);\n return [\n ...top.slice(0, topHeight),\n ...Array.from({ length: Math.max(0, topHeight - top.length) }, () => ''),\n this.theme.fg('borderMuted', RULE.repeat(width)),\n ...bottom.slice(0, bottomHeight),\n ];\n }\n\n private treeLines(width: number, height: number): string[] {\n const heading = this.filtering || this.query ? `${HEADING} ${FILTER_KEY}${this.query}` : HEADING;\n const lines = [this.theme.bold(this.theme.fg('accent', heading)), ''];\n const rows = this.rows();\n if (rows.length === 0) {\n lines.push(this.theme.fg('dim', EMPTY_TREE));\n return lines;\n }\n\n const budget = Math.max(1, height - lines.length);\n const indexes = this.selectable(rows);\n // No skill rows means the filter matched nothing, so nothing is highlighted.\n const selected = indexes[Math.min(this.selected, indexes.length - 1)] ?? -1;\n const start = Math.max(0, Math.min(selected - budget + 1, Math.max(0, rows.length - budget)));\n for (const [offset, row] of rows.slice(start, start + budget).entries()) {\n const isSelected = start + offset === selected;\n const marker = isSelected ? this.theme.fg('accent', SELECTION_MARKER) : ' ';\n const indent = ' '.repeat(row.depth * INDENT);\n // Three tiers rather than two: the group heading leads, the owner beneath\n // it recedes to a caption, and the skills it holds carry the reading\n // weight because they are the only rows that do anything.\n const colour: ThemeColor = row.kind === 'group' ? 'accent' : row.kind === 'owner' ? 'dim' : 'text';\n let label = this.theme.fg(colour, `${indent}${row.label}`);\n if (row.kind === 'group' || isSelected) label = this.theme.bold(label);\n // The tag is capped before it claims columns: an owner in many domains\n // carries a long `+a,b,c` hint that would otherwise leave the name with\n // no room at all and render the row as a bare count.\n const tag = row.tag ? truncateToWidth(row.tag, Math.floor(width * TAG_SHARE), ELLIPSIS) : '';\n const tagWidth = tag ? visibleWidth(tag) + 1 : 0;\n const body = fit(`${marker} ${label}`, Math.max(1, width - tagWidth));\n const line = tag ? `${body} ${this.theme.fg('dim', tag)}` : body;\n lines.push(isSelected ? this.theme.bg('selectedBg', fit(line, width)) : line);\n }\n return lines;\n }\n\n private field(label: string, value: string, colour: ThemeColor, width: number): string[] {\n const valueWidth = Math.max(1, width - LABEL_COLUMN);\n return wrap(value, valueWidth).map(\n (line, index) =>\n `${this.theme.fg('dim', fit(index === 0 ? label : '', LABEL_COLUMN))}${this.theme.fg(colour, line)}`,\n );\n }\n\n private detailLines(width: number, height: number): string[] {\n const skill = this.currentRow()?.skill;\n if (!skill) return ['', '', this.theme.fg('dim', NO_SELECTION)];\n\n const relative = path.relative(this.options.repoRoot, skill.filePath) || skill.filePath;\n const lines = [\n this.theme.bold(this.theme.fg('accent', skill.name)),\n '',\n ...this.field('description', skill.description, 'text', width),\n ...this.field('source', `${skill.group} › ${skill.owner}`, 'success', width),\n ...this.field('path', relative, 'text', width),\n ...this.field(\n 'invocable',\n skill.modelInvocable ? `model · /skill:${skill.name}` : `/skill:${skill.name} only`,\n 'success',\n width,\n ),\n ];\n\n const body = this.bodyLines(skill, width);\n const remaining = Math.max(0, height - lines.length - 2);\n // Clamped here rather than in the key handler, because how far the body can\n // scroll depends on the width it has just wrapped to.\n this.bodyOffset = Math.min(this.bodyOffset, Math.max(0, body.length - remaining));\n const shown = body.slice(this.bodyOffset, this.bodyOffset + remaining);\n const position =\n body.length > remaining\n ? `lines ${this.bodyOffset + 1}-${this.bodyOffset + shown.length} / ${body.length}`\n : 'SKILL.md';\n const focus = this.focus === 'body' ? this.theme.fg('accent', ' ◀ focused') : '';\n\n lines.push('', `${this.theme.fg('dim', position)}${focus}`);\n for (const line of shown) lines.push(this.theme.fg('dim', line));\n return lines;\n }\n}\n\nexport async function openSkillsOverlay(\n ctx: ExtensionContext,\n options: SkillsOverlayOptions,\n): Promise<SkillsOverlayResult> {\n return ctx.ui.custom<SkillsOverlayResult>(\n (tui, theme, _keybindings, done) => new SkillsOverlayComponent(tui, theme, options, done),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../config/harnessState.cjs`),t=require(`../services/matrixSwitcher.cjs`),n=require(`./components/matrixPicker.cjs`);let r=require(`@agimon-ai/doompi-config`),i=require(`@agimon-ai/doompi-config/domains`);const a=`info`,o=`(none)`;function s(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function c(e){let{domains:t}=e;return t.length>0?t:[`default`]}function l(e,t){return`Active domains: ${c(t).join(`, `)||o}\nAvailable domains: ${(0,i.listDomainNames)(e).join(`, `)}\nUse /domains <name[,name...]> to switch.`}function u(e){return e.map(e=>({value:e,label:e}))}function d(d){d.on(`resources_discover`,(e,t)=>({skillPaths:[...(0,r.requireDoomConfigContext)(t).harness.skillDirectories]})),d.on(`session_start`,(e,t)=>{let n=(0,r.requireDoomConfigContext)(t).harness;t.ui.addAutocompleteProvider(e=>({triggerCharacters:[`,`],async getSuggestions(t,r,a,o){let s=(0,i.domainCompletionPrefix)((t[r]??``).slice(0,a));if(s===void 0)return e.getSuggestions(t,r,a,o);let c=n.root;if(!c)return e.getSuggestions(t,r,a,o);let l=(0,i.domainCompletionItems)((0,i.listDomainNames)(c),s);return l.length===0?e.getSuggestions(t,r,a,o):{prefix:s,items:l}},applyCompletion(t,n,r,i,a){return e.applyCompletion(t,n,r,i,a)},shouldTriggerFileCompletion(t,n,r){return e.shouldTriggerFileCompletion?.(t,n,r)??!0}}))}),d.registerCommand(`domains`,{description:`Show the selected domains and pick a different set`,handler:async(f,p)=>{let m=(0,r.requireDoomConfigContext)(p).harness,h=(0,r.requireHarnessRoot)(m),g=s(f);if(g.length===0&&p.mode===`tui`){let e=c(m),t=await p.ui.custom((t,r,a,s)=>new n.MatrixPickerComponent({title:`Domains (active: ${e.join(`, `)||o})`,items:u((0,i.listDomainNames)(h)),selected:[...e],multi:!0},r,a,s));if(!t||t.length===0)return;g=t}if(g.length===0){p.ui.notify(l(h,m),a);return}await p.waitForIdle(),e.persistHarnessSelection(d,await t.applyDomains(g,m)),p.ui.notify(`Switched domains to: ${g.join(`, `)}`,a),await p.reload()}})}exports.default=d,exports.domainItems=u;
2
+ //# sourceMappingURL=domains.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.cjs","names":["MatrixPickerComponent","applyDomains"],"sources":["../../src/entries/domains.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport type { SelectItem } from '@earendil-works/pi-tui';\nimport { MatrixPickerComponent } from './components/matrixPicker.ts';\nimport { domainCompletionItems, domainCompletionPrefix, listDomainNames } from '@agimon-ai/doompi-config/domains';\nimport { type DoomHarnessContext, persistHarnessSelection, requireHarnessRoot } from '../config/harnessState.ts';\nimport { applyDomains } from '../services/matrixSwitcher.ts';\n\nconst DOMAIN_SEPARATOR = ',';\nconst INFO = 'info';\nconst NONE = '(none)';\n\nfunction splitDomains(value: string): string[] {\n return value\n .split(DOMAIN_SEPARATOR)\n .map((item) => item.trim())\n .filter(Boolean);\n}\n\nfunction currentDomains(state: DoomHarnessContext): readonly string[] {\n const { domains } = state;\n return domains.length > 0 ? domains : ['default'];\n}\n\nfunction domainSummary(repoRoot: string, state: DoomHarnessContext): string {\n const active = currentDomains(state).join(', ') || NONE;\n const available = listDomainNames(repoRoot).join(', ');\n return `Active domains: ${active}\\nAvailable domains: ${available}\\nUse /domains <name[,name...]> to switch.`;\n}\n\n/** Picker rows for the domain multi-select. */\nexport function domainItems(names: string[]): SelectItem[] {\n return names.map((name) => ({ value: name, label: name }));\n}\n\nexport default function domainsExtension(pi: ExtensionAPI): void {\n // Fires on startup and again on every reload, which makes it the one place\n // guaranteed to run after a switch. Pi re-reads settings and files on reload\n // but never the environment, so the re-read has to happen here.\n pi.on('resources_discover', (_event, ctx) => ({\n skillPaths: [...requireDoomConfigContext(ctx).harness.skillDirectories],\n }));\n\n pi.on('session_start', (_event, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n ctx.ui.addAutocompleteProvider((current) => ({\n triggerCharacters: [','],\n async getSuggestions(lines, cursorLine, cursorCol, options) {\n const line = lines[cursorLine] ?? '';\n const prefix = domainCompletionPrefix(line.slice(0, cursorCol));\n if (prefix === undefined) return current.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const repoRoot = state.root;\n if (!repoRoot) return current.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const items = domainCompletionItems(listDomainNames(repoRoot), prefix);\n if (items.length === 0) return current.getSuggestions(lines, cursorLine, cursorCol, options);\n return { prefix, items };\n },\n applyCompletion(lines, cursorLine, cursorCol, item, prefix) {\n return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n },\n shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {\n return current.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? true;\n },\n }));\n });\n\n pi.registerCommand('domains', {\n description: 'Show the selected domains and pick a different set',\n handler: async (args, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n const repoRoot = requireHarnessRoot(state);\n\n let requested = splitDomains(args);\n // No argument opens the multi-select. Domains compose, unlike a layer\n // base, so this picker toggles with space and confirms the whole set.\n if (requested.length === 0 && ctx.mode === 'tui') {\n const active = currentDomains(state);\n const chosen = await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n {\n title: `Domains (active: ${active.join(', ') || NONE})`,\n items: domainItems(listDomainNames(repoRoot)),\n selected: [...active],\n multi: true,\n },\n theme,\n keybindings,\n done,\n ),\n );\n if (!chosen || chosen.length === 0) return;\n requested = chosen;\n }\n\n if (requested.length === 0) {\n ctx.ui.notify(domainSummary(repoRoot, state), INFO);\n return;\n }\n\n await ctx.waitForIdle();\n const updated = await applyDomains(requested, state);\n persistHarnessSelection(pi, updated);\n ctx.ui.notify(`Switched domains to: ${requested.join(', ')}`, INFO);\n await ctx.reload();\n },\n });\n}\n"],"mappings":"yWAQA,MACM,EAAO,OACP,EAAO,SAEb,SAAS,EAAa,EAAyB,CAC7C,OAAO,EACJ,MAAM,IAAiB,CACvB,IAAK,GAAS,EAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ,CAGpB,SAAS,EAAe,EAA8C,CACpE,GAAM,CAAE,WAAY,EACpB,OAAO,EAAQ,OAAS,EAAI,EAAU,CAAC,UAAU,CAGnD,SAAS,EAAc,EAAkB,EAAmC,CAG1E,MAAO,mBAFQ,EAAe,EAAM,CAAC,KAAK,KAAK,EAAI,EAElB,wBAAA,EAAA,EAAA,iBADC,EAAS,CAAC,KAAK,KACgB,CAAC,4CAIpE,SAAgB,EAAY,EAA+B,CACzD,OAAO,EAAM,IAAK,IAAU,CAAE,MAAO,EAAM,MAAO,EAAM,EAAE,CAG5D,SAAwB,EAAiB,EAAwB,CAI/D,EAAG,GAAG,sBAAuB,EAAQ,KAAS,CAC5C,WAAY,CAAC,IAAA,EAAA,EAAA,0BAA4B,EAAI,CAAC,QAAQ,iBAAiB,CACxE,EAAE,CAEH,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,IAAM,GAAA,EAAA,EAAA,0BAAiC,EAAI,CAAC,QAC5C,EAAI,GAAG,wBAAyB,IAAa,CAC3C,kBAAmB,CAAC,IAAI,CACxB,MAAM,eAAe,EAAO,EAAY,EAAW,EAAS,CAE1D,IAAM,GAAA,EAAA,EAAA,yBADO,EAAM,IAAe,IACS,MAAM,EAAG,EAAU,CAAC,CAC/D,GAAI,IAAW,IAAA,GAAW,OAAO,EAAQ,eAAe,EAAO,EAAY,EAAW,EAAQ,CAE9F,IAAM,EAAW,EAAM,KACvB,GAAI,CAAC,EAAU,OAAO,EAAQ,eAAe,EAAO,EAAY,EAAW,EAAQ,CAEnF,IAAM,GAAA,EAAA,EAAA,wBAAA,EAAA,EAAA,iBAA8C,EAAS,CAAE,EAAO,CAEtE,OADI,EAAM,SAAW,EAAU,EAAQ,eAAe,EAAO,EAAY,EAAW,EAAQ,CACrF,CAAE,SAAQ,QAAO,EAE1B,gBAAgB,EAAO,EAAY,EAAW,EAAM,EAAQ,CAC1D,OAAO,EAAQ,gBAAgB,EAAO,EAAY,EAAW,EAAM,EAAO,EAE5E,4BAA4B,EAAO,EAAY,EAAW,CACxD,OAAO,EAAQ,8BAA8B,EAAO,EAAY,EAAU,EAAI,IAEjF,EAAE,EACH,CAEF,EAAG,gBAAgB,UAAW,CAC5B,YAAa,qDACb,QAAS,MAAO,EAAM,IAAQ,CAC5B,IAAM,GAAA,EAAA,EAAA,0BAAiC,EAAI,CAAC,QACtC,GAAA,EAAA,EAAA,oBAA8B,EAAM,CAEtC,EAAY,EAAa,EAAK,CAGlC,GAAI,EAAU,SAAW,GAAK,EAAI,OAAS,MAAO,CAChD,IAAM,EAAS,EAAe,EAAM,CAC9B,EAAS,MAAM,EAAI,GAAG,QACzB,EAAM,EAAO,EAAa,IACzB,IAAIA,EAAAA,sBACF,CACE,MAAO,oBAAoB,EAAO,KAAK,KAAK,EAAI,EAAK,GACrD,MAAO,GAAA,EAAA,EAAA,iBAA4B,EAAS,CAAC,CAC7C,SAAU,CAAC,GAAG,EAAO,CACrB,MAAO,GACR,CACD,EACA,EACA,EACD,CACJ,CACD,GAAI,CAAC,GAAU,EAAO,SAAW,EAAG,OACpC,EAAY,EAGd,GAAI,EAAU,SAAW,EAAG,CAC1B,EAAI,GAAG,OAAO,EAAc,EAAU,EAAM,CAAE,EAAK,CACnD,OAGF,MAAM,EAAI,aAAa,CAEvB,EAAA,wBAAwB,EAAI,MADNC,EAAAA,aAAa,EAAW,EAAM,CAChB,CACpC,EAAI,GAAG,OAAO,wBAAwB,EAAU,KAAK,KAAK,GAAI,EAAK,CACnE,MAAM,EAAI,QAAQ,EAErB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { SelectItem } from "@earendil-works/pi-tui";
3
+
4
+ //#region src/entries/domains.d.ts
5
+ /** Picker rows for the domain multi-select. */
6
+ declare function domainItems(names: string[]): SelectItem[];
7
+ declare function domainsExtension(pi: ExtensionAPI): void;
8
+ //#endregion
9
+ export { domainsExtension as default, domainItems };
10
+ //# sourceMappingURL=domains.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.d.cts","names":[],"sources":["../../src/entries/domains.ts"],"mappings":";;;;;iBA+BgB,WAAA,CAAY,KAAA,aAAkB,UAAA;AAAA,iBAItB,gBAAA,CAAiB,EAAA,EAAI,YAAA"}
@@ -0,0 +1,10 @@
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { SelectItem } from "@earendil-works/pi-tui";
3
+
4
+ //#region src/entries/domains.d.ts
5
+ /** Picker rows for the domain multi-select. */
6
+ declare function domainItems(names: string[]): SelectItem[];
7
+ declare function domainsExtension(pi: ExtensionAPI): void;
8
+ //#endregion
9
+ export { domainsExtension as default, domainItems };
10
+ //# sourceMappingURL=domains.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.d.mts","names":[],"sources":["../../src/entries/domains.ts"],"mappings":";;;;;iBA+BgB,WAAA,CAAY,KAAA,aAAkB,UAAA;AAAA,iBAItB,gBAAA,CAAiB,EAAA,EAAI,YAAA"}
@@ -0,0 +1,2 @@
1
+ import{persistHarnessSelection as e,requireHarnessRoot as t}from"../config/harnessState.mjs";import{applyDomains as n}from"../services/matrixSwitcher.mjs";import{MatrixPickerComponent as r}from"./components/matrixPicker.mjs";import{requireDoomConfigContext as i}from"@agimon-ai/doompi-config";import{domainCompletionItems as a,domainCompletionPrefix as o,listDomainNames as s}from"@agimon-ai/doompi-config/domains";const c=`info`,l=`(none)`;function u(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function d(e){let{domains:t}=e;return t.length>0?t:[`default`]}function f(e,t){return`Active domains: ${d(t).join(`, `)||l}\nAvailable domains: ${s(e).join(`, `)}\nUse /domains <name[,name...]> to switch.`}function p(e){return e.map(e=>({value:e,label:e}))}function m(m){m.on(`resources_discover`,(e,t)=>({skillPaths:[...i(t).harness.skillDirectories]})),m.on(`session_start`,(e,t)=>{let n=i(t).harness;t.ui.addAutocompleteProvider(e=>({triggerCharacters:[`,`],async getSuggestions(t,r,i,c){let l=o((t[r]??``).slice(0,i));if(l===void 0)return e.getSuggestions(t,r,i,c);let u=n.root;if(!u)return e.getSuggestions(t,r,i,c);let d=a(s(u),l);return d.length===0?e.getSuggestions(t,r,i,c):{prefix:l,items:d}},applyCompletion(t,n,r,i,a){return e.applyCompletion(t,n,r,i,a)},shouldTriggerFileCompletion(t,n,r){return e.shouldTriggerFileCompletion?.(t,n,r)??!0}}))}),m.registerCommand(`domains`,{description:`Show the selected domains and pick a different set`,handler:async(a,o)=>{let h=i(o).harness,g=t(h),_=u(a);if(_.length===0&&o.mode===`tui`){let e=d(h),t=await o.ui.custom((t,n,i,a)=>new r({title:`Domains (active: ${e.join(`, `)||l})`,items:p(s(g)),selected:[...e],multi:!0},n,i,a));if(!t||t.length===0)return;_=t}if(_.length===0){o.ui.notify(f(g,h),c);return}await o.waitForIdle(),e(m,await n(_,h)),o.ui.notify(`Switched domains to: ${_.join(`, `)}`,c),await o.reload()}})}export{m as default,p as domainItems};
2
+ //# sourceMappingURL=domains.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.mjs","names":[],"sources":["../../src/entries/domains.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport type { SelectItem } from '@earendil-works/pi-tui';\nimport { MatrixPickerComponent } from './components/matrixPicker.ts';\nimport { domainCompletionItems, domainCompletionPrefix, listDomainNames } from '@agimon-ai/doompi-config/domains';\nimport { type DoomHarnessContext, persistHarnessSelection, requireHarnessRoot } from '../config/harnessState.ts';\nimport { applyDomains } from '../services/matrixSwitcher.ts';\n\nconst DOMAIN_SEPARATOR = ',';\nconst INFO = 'info';\nconst NONE = '(none)';\n\nfunction splitDomains(value: string): string[] {\n return value\n .split(DOMAIN_SEPARATOR)\n .map((item) => item.trim())\n .filter(Boolean);\n}\n\nfunction currentDomains(state: DoomHarnessContext): readonly string[] {\n const { domains } = state;\n return domains.length > 0 ? domains : ['default'];\n}\n\nfunction domainSummary(repoRoot: string, state: DoomHarnessContext): string {\n const active = currentDomains(state).join(', ') || NONE;\n const available = listDomainNames(repoRoot).join(', ');\n return `Active domains: ${active}\\nAvailable domains: ${available}\\nUse /domains <name[,name...]> to switch.`;\n}\n\n/** Picker rows for the domain multi-select. */\nexport function domainItems(names: string[]): SelectItem[] {\n return names.map((name) => ({ value: name, label: name }));\n}\n\nexport default function domainsExtension(pi: ExtensionAPI): void {\n // Fires on startup and again on every reload, which makes it the one place\n // guaranteed to run after a switch. Pi re-reads settings and files on reload\n // but never the environment, so the re-read has to happen here.\n pi.on('resources_discover', (_event, ctx) => ({\n skillPaths: [...requireDoomConfigContext(ctx).harness.skillDirectories],\n }));\n\n pi.on('session_start', (_event, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n ctx.ui.addAutocompleteProvider((current) => ({\n triggerCharacters: [','],\n async getSuggestions(lines, cursorLine, cursorCol, options) {\n const line = lines[cursorLine] ?? '';\n const prefix = domainCompletionPrefix(line.slice(0, cursorCol));\n if (prefix === undefined) return current.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const repoRoot = state.root;\n if (!repoRoot) return current.getSuggestions(lines, cursorLine, cursorCol, options);\n\n const items = domainCompletionItems(listDomainNames(repoRoot), prefix);\n if (items.length === 0) return current.getSuggestions(lines, cursorLine, cursorCol, options);\n return { prefix, items };\n },\n applyCompletion(lines, cursorLine, cursorCol, item, prefix) {\n return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);\n },\n shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {\n return current.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? true;\n },\n }));\n });\n\n pi.registerCommand('domains', {\n description: 'Show the selected domains and pick a different set',\n handler: async (args, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n const repoRoot = requireHarnessRoot(state);\n\n let requested = splitDomains(args);\n // No argument opens the multi-select. Domains compose, unlike a layer\n // base, so this picker toggles with space and confirms the whole set.\n if (requested.length === 0 && ctx.mode === 'tui') {\n const active = currentDomains(state);\n const chosen = await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n {\n title: `Domains (active: ${active.join(', ') || NONE})`,\n items: domainItems(listDomainNames(repoRoot)),\n selected: [...active],\n multi: true,\n },\n theme,\n keybindings,\n done,\n ),\n );\n if (!chosen || chosen.length === 0) return;\n requested = chosen;\n }\n\n if (requested.length === 0) {\n ctx.ui.notify(domainSummary(repoRoot, state), INFO);\n return;\n }\n\n await ctx.waitForIdle();\n const updated = await applyDomains(requested, state);\n persistHarnessSelection(pi, updated);\n ctx.ui.notify(`Switched domains to: ${requested.join(', ')}`, INFO);\n await ctx.reload();\n },\n });\n}\n"],"mappings":"+ZAQA,MACM,EAAO,OACP,EAAO,SAEb,SAAS,EAAa,EAAyB,CAC7C,OAAO,EACJ,MAAM,IAAiB,CACvB,IAAK,GAAS,EAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ,CAGpB,SAAS,EAAe,EAA8C,CACpE,GAAM,CAAE,WAAY,EACpB,OAAO,EAAQ,OAAS,EAAI,EAAU,CAAC,UAAU,CAGnD,SAAS,EAAc,EAAkB,EAAmC,CAG1E,MAAO,mBAFQ,EAAe,EAAM,CAAC,KAAK,KAAK,EAAI,EAElB,uBADf,EAAgB,EAAS,CAAC,KAAK,KACgB,CAAC,4CAIpE,SAAgB,EAAY,EAA+B,CACzD,OAAO,EAAM,IAAK,IAAU,CAAE,MAAO,EAAM,MAAO,EAAM,EAAE,CAG5D,SAAwB,EAAiB,EAAwB,CAI/D,EAAG,GAAG,sBAAuB,EAAQ,KAAS,CAC5C,WAAY,CAAC,GAAG,EAAyB,EAAI,CAAC,QAAQ,iBAAiB,CACxE,EAAE,CAEH,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,IAAM,EAAQ,EAAyB,EAAI,CAAC,QAC5C,EAAI,GAAG,wBAAyB,IAAa,CAC3C,kBAAmB,CAAC,IAAI,CACxB,MAAM,eAAe,EAAO,EAAY,EAAW,EAAS,CAE1D,IAAM,EAAS,GADF,EAAM,IAAe,IACS,MAAM,EAAG,EAAU,CAAC,CAC/D,GAAI,IAAW,IAAA,GAAW,OAAO,EAAQ,eAAe,EAAO,EAAY,EAAW,EAAQ,CAE9F,IAAM,EAAW,EAAM,KACvB,GAAI,CAAC,EAAU,OAAO,EAAQ,eAAe,EAAO,EAAY,EAAW,EAAQ,CAEnF,IAAM,EAAQ,EAAsB,EAAgB,EAAS,CAAE,EAAO,CAEtE,OADI,EAAM,SAAW,EAAU,EAAQ,eAAe,EAAO,EAAY,EAAW,EAAQ,CACrF,CAAE,SAAQ,QAAO,EAE1B,gBAAgB,EAAO,EAAY,EAAW,EAAM,EAAQ,CAC1D,OAAO,EAAQ,gBAAgB,EAAO,EAAY,EAAW,EAAM,EAAO,EAE5E,4BAA4B,EAAO,EAAY,EAAW,CACxD,OAAO,EAAQ,8BAA8B,EAAO,EAAY,EAAU,EAAI,IAEjF,EAAE,EACH,CAEF,EAAG,gBAAgB,UAAW,CAC5B,YAAa,qDACb,QAAS,MAAO,EAAM,IAAQ,CAC5B,IAAM,EAAQ,EAAyB,EAAI,CAAC,QACtC,EAAW,EAAmB,EAAM,CAEtC,EAAY,EAAa,EAAK,CAGlC,GAAI,EAAU,SAAW,GAAK,EAAI,OAAS,MAAO,CAChD,IAAM,EAAS,EAAe,EAAM,CAC9B,EAAS,MAAM,EAAI,GAAG,QACzB,EAAM,EAAO,EAAa,IACzB,IAAI,EACF,CACE,MAAO,oBAAoB,EAAO,KAAK,KAAK,EAAI,EAAK,GACrD,MAAO,EAAY,EAAgB,EAAS,CAAC,CAC7C,SAAU,CAAC,GAAG,EAAO,CACrB,MAAO,GACR,CACD,EACA,EACA,EACD,CACJ,CACD,GAAI,CAAC,GAAU,EAAO,SAAW,EAAG,OACpC,EAAY,EAGd,GAAI,EAAU,SAAW,EAAG,CAC1B,EAAI,GAAG,OAAO,EAAc,EAAU,EAAM,CAAE,EAAK,CACnD,OAGF,MAAM,EAAI,aAAa,CAEvB,EAAwB,EAAI,MADN,EAAa,EAAW,EAAM,CAChB,CACpC,EAAI,GAAG,OAAO,wBAAwB,EAAU,KAAK,KAAK,GAAI,EAAK,CACnE,MAAM,EAAI,QAAQ,EAErB,CAAC"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../services/composer.cjs`);let t=require(`@agimon-ai/doompi-config`);const n=`warning`;async function r(r){e.registerDoomFlags(r);let i=await e.composeDoomSession(r);r.on(`session_start`,(e,t)=>{for(let e of i.problems)t.ui.notify(e,n);i.stale&&t.ui.notify(`doompi config changed since the last sync. Run doompi sync.`,n)}),r.on(`session_shutdown`,async(n,r)=>{let i=e.findSyncedRoot(r.cwd);i&&((0,t.disposeHarnessState)(),await e.cleanupRunDirectory(i))})}module.exports=r;
2
+ //# sourceMappingURL=doom.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.cjs","names":["composeDoomSession","findSyncedRoot","cleanupRunDirectory"],"sources":["../../src/entries/doom.ts"],"sourcesContent":["import { disposeHarnessState } from '@agimon-ai/doompi-config';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n// Imported from the module rather than the barrel: Pi loads this file directly\n// and it is the first thing a synced session runs, so it pulls in nothing it\n// does not use.\nimport {\n cleanupRunDirectory,\n composeDoomSession,\n findSyncedRoot,\n registerDoomFlags,\n type ComposeOutcome,\n} from '../services/composer.ts';\n\nconst WARNING = 'warning';\nconst STALE_MESSAGE = 'doompi config changed since the last sync. Run doompi sync.';\n\n/**\n * The one entry `doom-pi sync` puts in Pi's own config.\n *\n * Everything doom-pi contributes to a plain `pi` session is loaded from here,\n * which is what keeps `.pi/settings.json` to a single stable line and lets the\n * whole matrix be recomposed on `/reload` rather than frozen at startup.\n */\nexport default async function doomExtension(pi: ExtensionAPI): Promise<void> {\n registerDoomFlags(pi);\n\n const outcome: ComposeOutcome = await composeDoomSession(pi);\n\n // Reported on session_start rather than thrown: composition problems have to\n // reach the user through the UI, and the UI does not exist yet at load time.\n pi.on('session_start', (_event, ctx) => {\n for (const problem of outcome.problems) ctx.ui.notify(problem, WARNING);\n if (outcome.stale) ctx.ui.notify(STALE_MESSAGE, WARNING);\n });\n\n pi.on('session_shutdown', async (_event, ctx) => {\n const repoRoot = findSyncedRoot(ctx.cwd);\n if (!repoRoot) return;\n // The state file first, so nothing is left pointing at a path that is\n // about to disappear, then the directory it lived in.\n disposeHarnessState();\n await cleanupRunDirectory(repoRoot);\n });\n}\n"],"mappings":"mIAaA,MAAM,EAAU,UAUhB,eAA8B,EAAc,EAAiC,CAC3E,EAAA,kBAAkB,EAAG,CAErB,IAAM,EAA0B,MAAMA,EAAAA,mBAAmB,EAAG,CAI5D,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,IAAK,IAAM,KAAW,EAAQ,SAAU,EAAI,GAAG,OAAO,EAAS,EAAQ,CACnE,EAAQ,OAAO,EAAI,GAAG,OAAO,8DAAe,EAAQ,EACxD,CAEF,EAAG,GAAG,mBAAoB,MAAO,EAAQ,IAAQ,CAC/C,IAAM,EAAWC,EAAAA,eAAe,EAAI,IAAI,CACnC,KAGL,EAAA,EAAA,sBAAqB,CACrB,MAAMC,EAAAA,oBAAoB,EAAS,GACnC"}
@@ -0,0 +1,13 @@
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ //#region src/entries/doom.d.ts
4
+ /**
5
+ * The one entry `doom-pi sync` puts in Pi's own config.
6
+ *
7
+ * Everything doom-pi contributes to a plain `pi` session is loaded from here,
8
+ * which is what keeps `.pi/settings.json` to a single stable line and lets the
9
+ * whole matrix be recomposed on `/reload` rather than frozen at startup.
10
+ */
11
+ declare function doomExtension(pi: ExtensionAPI): Promise<void>;
12
+ export = doomExtension;
13
+ //# sourceMappingURL=doom.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.d.cts","names":[],"sources":["../../src/entries/doom.ts"],"mappings":";;;;;AACoE;;;;;iBAsBtC,aAAA,CAAc,EAAA,EAAI,YAAA,GAAe,OAAA;AAAA"}
@@ -0,0 +1,14 @@
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ //#region src/entries/doom.d.ts
4
+ /**
5
+ * The one entry `doom-pi sync` puts in Pi's own config.
6
+ *
7
+ * Everything doom-pi contributes to a plain `pi` session is loaded from here,
8
+ * which is what keeps `.pi/settings.json` to a single stable line and lets the
9
+ * whole matrix be recomposed on `/reload` rather than frozen at startup.
10
+ */
11
+ declare function doomExtension(pi: ExtensionAPI): Promise<void>;
12
+ //#endregion
13
+ export { doomExtension as default };
14
+ //# sourceMappingURL=doom.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.d.mts","names":[],"sources":["../../src/entries/doom.ts"],"mappings":";;;;;AACoE;;;;;iBAsBtC,aAAA,CAAc,EAAA,EAAI,YAAA,GAAe,OAAA"}
@@ -0,0 +1,2 @@
1
+ import{cleanupRunDirectory as e,composeDoomSession as t,findSyncedRoot as n,registerDoomFlags as r}from"../services/composer.mjs";import{disposeHarnessState as i}from"@agimon-ai/doompi-config";const a=`warning`;async function o(o){r(o);let s=await t(o);o.on(`session_start`,(e,t)=>{for(let e of s.problems)t.ui.notify(e,a);s.stale&&t.ui.notify(`doompi config changed since the last sync. Run doompi sync.`,a)}),o.on(`session_shutdown`,async(t,r)=>{let a=n(r.cwd);a&&(i(),await e(a))})}export{o as default};
2
+ //# sourceMappingURL=doom.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doom.mjs","names":[],"sources":["../../src/entries/doom.ts"],"sourcesContent":["import { disposeHarnessState } from '@agimon-ai/doompi-config';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n// Imported from the module rather than the barrel: Pi loads this file directly\n// and it is the first thing a synced session runs, so it pulls in nothing it\n// does not use.\nimport {\n cleanupRunDirectory,\n composeDoomSession,\n findSyncedRoot,\n registerDoomFlags,\n type ComposeOutcome,\n} from '../services/composer.ts';\n\nconst WARNING = 'warning';\nconst STALE_MESSAGE = 'doompi config changed since the last sync. Run doompi sync.';\n\n/**\n * The one entry `doom-pi sync` puts in Pi's own config.\n *\n * Everything doom-pi contributes to a plain `pi` session is loaded from here,\n * which is what keeps `.pi/settings.json` to a single stable line and lets the\n * whole matrix be recomposed on `/reload` rather than frozen at startup.\n */\nexport default async function doomExtension(pi: ExtensionAPI): Promise<void> {\n registerDoomFlags(pi);\n\n const outcome: ComposeOutcome = await composeDoomSession(pi);\n\n // Reported on session_start rather than thrown: composition problems have to\n // reach the user through the UI, and the UI does not exist yet at load time.\n pi.on('session_start', (_event, ctx) => {\n for (const problem of outcome.problems) ctx.ui.notify(problem, WARNING);\n if (outcome.stale) ctx.ui.notify(STALE_MESSAGE, WARNING);\n });\n\n pi.on('session_shutdown', async (_event, ctx) => {\n const repoRoot = findSyncedRoot(ctx.cwd);\n if (!repoRoot) return;\n // The state file first, so nothing is left pointing at a path that is\n // about to disappear, then the directory it lived in.\n disposeHarnessState();\n await cleanupRunDirectory(repoRoot);\n });\n}\n"],"mappings":"iMAaA,MAAM,EAAU,UAUhB,eAA8B,EAAc,EAAiC,CAC3E,EAAkB,EAAG,CAErB,IAAM,EAA0B,MAAM,EAAmB,EAAG,CAI5D,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,IAAK,IAAM,KAAW,EAAQ,SAAU,EAAI,GAAG,OAAO,EAAS,EAAQ,CACnE,EAAQ,OAAO,EAAI,GAAG,OAAO,8DAAe,EAAQ,EACxD,CAEF,EAAG,GAAG,mBAAoB,MAAO,EAAQ,IAAQ,CAC/C,IAAM,EAAW,EAAe,EAAI,IAAI,CACnC,IAGL,GAAqB,CACrB,MAAM,EAAoB,EAAS,GACnC"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../_virtual/_rolldown/runtime.cjs`);let e=require(`@earendil-works/pi-coding-agent`);const t=[`off`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`];function n(e){let[n]=e.trim().toLowerCase().split(/\s+/).filter(Boolean);return t.find(e=>e===n)}function r(){return`Usage: /effort <${t.join(`|`)}>`}function i(i){i.registerCommand(`effort`,{description:`Set thinking effort and persist it as the default for future sessions`,getArgumentCompletions:e=>{let n=e.trim().toLowerCase();return t.filter(e=>e.startsWith(n)).map(e=>({value:e,label:e}))},handler:async(t,a)=>{let o=n(t);if(!o){a.ui.notify(`${r()}\nCurrent effort: ${i.getThinkingLevel()}`,`warning`);return}i.setThinkingLevel(o);let s=i.getThinkingLevel(),c=e.SettingsManager.create(a.cwd);c.setDefaultThinkingLevel(o),await c.flush();let l=s===o?``:` Current model clamps it to ${s}.`;a.ui.notify(`Effort set to ${o} and saved for future sessions.${l}`,`info`)}})}exports.default=i,exports.effortUsage=r,exports.parseEffortLevel=n;
2
+ //# sourceMappingURL=effort.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort.cjs","names":["SettingsManager"],"sources":["../../src/entries/effort.ts"],"sourcesContent":["import { SettingsManager, type ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\ntype ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n\nconst THINKING_LEVELS: ThinkingLevel[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\nexport function parseEffortLevel(args: string): ThinkingLevel | undefined {\n const [level] = args.trim().toLowerCase().split(/\\s+/).filter(Boolean);\n return THINKING_LEVELS.find((candidate) => candidate === level);\n}\n\nexport function effortUsage(): string {\n return `Usage: /effort <${THINKING_LEVELS.join('|')}>`;\n}\n\nexport default function effortExtension(pi: ExtensionAPI): void {\n pi.registerCommand('effort', {\n description: 'Set thinking effort and persist it as the default for future sessions',\n getArgumentCompletions: (prefix) => {\n const query = prefix.trim().toLowerCase();\n return THINKING_LEVELS.filter((level) => level.startsWith(query)).map((level) => ({\n value: level,\n label: level,\n }));\n },\n handler: async (args, ctx) => {\n const requestedLevel = parseEffortLevel(args);\n if (!requestedLevel) {\n ctx.ui.notify(`${effortUsage()}\\nCurrent effort: ${pi.getThinkingLevel()}`, 'warning');\n return;\n }\n\n pi.setThinkingLevel(requestedLevel);\n const effectiveLevel = pi.getThinkingLevel();\n\n const settings = SettingsManager.create(ctx.cwd);\n settings.setDefaultThinkingLevel(requestedLevel);\n await settings.flush();\n\n const suffix = effectiveLevel === requestedLevel ? '' : ` Current model clamps it to ${effectiveLevel}.`;\n ctx.ui.notify(`Effort set to ${requestedLevel} and saved for future sessions.${suffix}`, 'info');\n },\n });\n}\n"],"mappings":"6LAIA,MAAM,EAAmC,CAAC,MAAO,UAAW,MAAO,SAAU,OAAQ,QAAS,MAAM,CAEpG,SAAgB,EAAiB,EAAyC,CACxE,GAAM,CAAC,GAAS,EAAK,MAAM,CAAC,aAAa,CAAC,MAAM,MAAM,CAAC,OAAO,QAAQ,CACtE,OAAO,EAAgB,KAAM,GAAc,IAAc,EAAM,CAGjE,SAAgB,GAAsB,CACpC,MAAO,mBAAmB,EAAgB,KAAK,IAAI,CAAC,GAGtD,SAAwB,EAAgB,EAAwB,CAC9D,EAAG,gBAAgB,SAAU,CAC3B,YAAa,wEACb,uBAAyB,GAAW,CAClC,IAAM,EAAQ,EAAO,MAAM,CAAC,aAAa,CACzC,OAAO,EAAgB,OAAQ,GAAU,EAAM,WAAW,EAAM,CAAC,CAAC,IAAK,IAAW,CAChF,MAAO,EACP,MAAO,EACR,EAAE,EAEL,QAAS,MAAO,EAAM,IAAQ,CAC5B,IAAM,EAAiB,EAAiB,EAAK,CAC7C,GAAI,CAAC,EAAgB,CACnB,EAAI,GAAG,OAAO,GAAG,GAAa,CAAC,oBAAoB,EAAG,kBAAkB,GAAI,UAAU,CACtF,OAGF,EAAG,iBAAiB,EAAe,CACnC,IAAM,EAAiB,EAAG,kBAAkB,CAEtC,EAAWA,EAAAA,gBAAgB,OAAO,EAAI,IAAI,CAChD,EAAS,wBAAwB,EAAe,CAChD,MAAM,EAAS,OAAO,CAEtB,IAAM,EAAS,IAAmB,EAAiB,GAAK,+BAA+B,EAAe,GACtG,EAAI,GAAG,OAAO,iBAAiB,EAAe,iCAAiC,IAAU,OAAO,EAEnG,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ //#region src/entries/effort.d.ts
4
+ type ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
5
+ declare function parseEffortLevel(args: string): ThinkingLevel | undefined;
6
+ declare function effortUsage(): string;
7
+ declare function effortExtension(pi: ExtensionAPI): void;
8
+ //#endregion
9
+ export { effortExtension as default, effortUsage, parseEffortLevel };
10
+ //# sourceMappingURL=effort.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort.d.cts","names":[],"sources":["../../src/entries/effort.ts"],"mappings":";;;KAEK,aAAA;AAAA,iBAIW,gBAAA,CAAiB,IAAA,WAAe,aAAA;AAAA,iBAKhC,WAAA,CAAA;AAAA,iBAIQ,eAAA,CAAgB,EAAA,EAAI,YAAA"}
@@ -0,0 +1,10 @@
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ //#region src/entries/effort.d.ts
4
+ type ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
5
+ declare function parseEffortLevel(args: string): ThinkingLevel | undefined;
6
+ declare function effortUsage(): string;
7
+ declare function effortExtension(pi: ExtensionAPI): void;
8
+ //#endregion
9
+ export { effortExtension as default, effortUsage, parseEffortLevel };
10
+ //# sourceMappingURL=effort.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort.d.mts","names":[],"sources":["../../src/entries/effort.ts"],"mappings":";;;KAEK,aAAA;AAAA,iBAIW,gBAAA,CAAiB,IAAA,WAAe,aAAA;AAAA,iBAKhC,WAAA,CAAA;AAAA,iBAIQ,eAAA,CAAgB,EAAA,EAAI,YAAA"}
@@ -0,0 +1,2 @@
1
+ import{SettingsManager as e}from"@earendil-works/pi-coding-agent";const t=[`off`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`];function n(e){let[n]=e.trim().toLowerCase().split(/\s+/).filter(Boolean);return t.find(e=>e===n)}function r(){return`Usage: /effort <${t.join(`|`)}>`}function i(i){i.registerCommand(`effort`,{description:`Set thinking effort and persist it as the default for future sessions`,getArgumentCompletions:e=>{let n=e.trim().toLowerCase();return t.filter(e=>e.startsWith(n)).map(e=>({value:e,label:e}))},handler:async(t,a)=>{let o=n(t);if(!o){a.ui.notify(`${r()}\nCurrent effort: ${i.getThinkingLevel()}`,`warning`);return}i.setThinkingLevel(o);let s=i.getThinkingLevel(),c=e.create(a.cwd);c.setDefaultThinkingLevel(o),await c.flush();let l=s===o?``:` Current model clamps it to ${s}.`;a.ui.notify(`Effort set to ${o} and saved for future sessions.${l}`,`info`)}})}export{i as default,r as effortUsage,n as parseEffortLevel};
2
+ //# sourceMappingURL=effort.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort.mjs","names":[],"sources":["../../src/entries/effort.ts"],"sourcesContent":["import { SettingsManager, type ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\ntype ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n\nconst THINKING_LEVELS: ThinkingLevel[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\nexport function parseEffortLevel(args: string): ThinkingLevel | undefined {\n const [level] = args.trim().toLowerCase().split(/\\s+/).filter(Boolean);\n return THINKING_LEVELS.find((candidate) => candidate === level);\n}\n\nexport function effortUsage(): string {\n return `Usage: /effort <${THINKING_LEVELS.join('|')}>`;\n}\n\nexport default function effortExtension(pi: ExtensionAPI): void {\n pi.registerCommand('effort', {\n description: 'Set thinking effort and persist it as the default for future sessions',\n getArgumentCompletions: (prefix) => {\n const query = prefix.trim().toLowerCase();\n return THINKING_LEVELS.filter((level) => level.startsWith(query)).map((level) => ({\n value: level,\n label: level,\n }));\n },\n handler: async (args, ctx) => {\n const requestedLevel = parseEffortLevel(args);\n if (!requestedLevel) {\n ctx.ui.notify(`${effortUsage()}\\nCurrent effort: ${pi.getThinkingLevel()}`, 'warning');\n return;\n }\n\n pi.setThinkingLevel(requestedLevel);\n const effectiveLevel = pi.getThinkingLevel();\n\n const settings = SettingsManager.create(ctx.cwd);\n settings.setDefaultThinkingLevel(requestedLevel);\n await settings.flush();\n\n const suffix = effectiveLevel === requestedLevel ? '' : ` Current model clamps it to ${effectiveLevel}.`;\n ctx.ui.notify(`Effort set to ${requestedLevel} and saved for future sessions.${suffix}`, 'info');\n },\n });\n}\n"],"mappings":"kEAIA,MAAM,EAAmC,CAAC,MAAO,UAAW,MAAO,SAAU,OAAQ,QAAS,MAAM,CAEpG,SAAgB,EAAiB,EAAyC,CACxE,GAAM,CAAC,GAAS,EAAK,MAAM,CAAC,aAAa,CAAC,MAAM,MAAM,CAAC,OAAO,QAAQ,CACtE,OAAO,EAAgB,KAAM,GAAc,IAAc,EAAM,CAGjE,SAAgB,GAAsB,CACpC,MAAO,mBAAmB,EAAgB,KAAK,IAAI,CAAC,GAGtD,SAAwB,EAAgB,EAAwB,CAC9D,EAAG,gBAAgB,SAAU,CAC3B,YAAa,wEACb,uBAAyB,GAAW,CAClC,IAAM,EAAQ,EAAO,MAAM,CAAC,aAAa,CACzC,OAAO,EAAgB,OAAQ,GAAU,EAAM,WAAW,EAAM,CAAC,CAAC,IAAK,IAAW,CAChF,MAAO,EACP,MAAO,EACR,EAAE,EAEL,QAAS,MAAO,EAAM,IAAQ,CAC5B,IAAM,EAAiB,EAAiB,EAAK,CAC7C,GAAI,CAAC,EAAgB,CACnB,EAAI,GAAG,OAAO,GAAG,GAAa,CAAC,oBAAoB,EAAG,kBAAkB,GAAI,UAAU,CACtF,OAGF,EAAG,iBAAiB,EAAe,CACnC,IAAM,EAAiB,EAAG,kBAAkB,CAEtC,EAAW,EAAgB,OAAO,EAAI,IAAI,CAChD,EAAS,wBAAwB,EAAe,CAChD,MAAM,EAAS,OAAO,CAEtB,IAAM,EAAS,IAAmB,EAAiB,GAAK,+BAA+B,EAAe,GACtG,EAAI,GAAG,OAAO,iBAAiB,EAAe,iCAAiC,IAAU,OAAO,EAEnG,CAAC"}
@@ -0,0 +1,6 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../logSinkTelemetry.cjs`),t=require(`../config/harnessState.cjs`),n=require(`../services/extensionAssembler.cjs`),r=require(`../services/matrixSwitcher.cjs`),i=require(`../services/composer.cjs`),a=require(`./components/matrixPicker.cjs`);let o=require(`@agimon-ai/doompi-config`),s=require(`@agimon-ai/doompi-config/majorModes`);const c=`doom-major-mode`,l=/^\[[ x]\] /,u=`core only`,d=`--major-mode`;function f(e){return Object.keys(e.majorMode)}function p(e,t){return t.map(t=>({value:t,label:t,description:(e.majorMode[t]??[]).join(`, `)||u}))}function m(e,t,n){return`${e===n?`[x]`:`[ ]`} ${e}: ${t.join(`, `)||u}`}function h(e){return e.replace(l,``).split(`:`)[0]??e}function g(e,t,n){return[n?`*${n}*`:void 0,`[${e}]`,t.join(`,`)].filter(e=>!!e).join(`:`)}function _(e,t,n,r,i){return[r?e.fg(`success`,e.bold(`*${r}*`)):void 0,e.fg(i?`warning`:`accent`,`[${t}]`),n.length>0?e.fg(`muted`,n.join(`,`)):void 0].filter(e=>!!e).join(e.fg(`dim`,`:`))}function v(e,t,n,r=!1){let i=`Switched to ${e}: ${t.join(`, `)||u}`;return!n||r?[i,`Hooks reloaded.`].join(`
2
+ `):[i,`Hooks reloaded. Extensions are fixed at launch, so for those:`,` ./pi.sh ${d} ${e}`].join(`
3
+ `)}function y(e,t,n,r=!1){let i=`Major mode ${e}: ${t.join(`, `)||u}`;return e!==n&&!r?[i,`Relaunch with:\n ./pi.sh ${d} ${e}`].join(`
4
+ `):e===n?[i,`Already using this major mode.`].join(`
5
+ `):i}function b(e){let t=(0,o.requireDoomConfigContext)(e).harness,n=(0,s.loadMajorModesConfig)((0,o.requireHarnessRoot)(t)),r=(0,s.resolveLayers)(n,t.majorMode);return{config:n,majorMode:t.majorMode,active:t.layers.length===0?r:[...t.layers],domains:t.domains,profile:t.profile,hooks:t.hooks}}function x(l,u=e.createHarnessTelemetry()){l.on(`session_start`,(t,n)=>{try{let{majorMode:e,domains:t,profile:r}=b(n);n.ui.setStatus(c,_(n.ui.theme,e,t,r,!1))}catch(t){u.recordWarning(e.HARNESS_EVENT.majorModeUnavailable,t),n.ui.setStatus(c,`major mode unavailable (${t instanceof Error?t.message:String(t)})`)}}),l.registerCommand(`major-mode`,{description:`Pick a named major mode`,handler:async(d,g)=>{if(d.trim()){g.ui.notify(`Usage: /major-mode`,`warning`);return}let{config:x,majorMode:S,active:C,domains:w,profile:T,hooks:E}=b(g),D=f(x),O=`Major mode (current: ${S})`,k=(g.mode===`tui`?await g.ui.custom((e,t,n,r)=>new a.MatrixPickerComponent({title:O,items:p(x,D),selected:[S],multi:!1},t,n,r)):[h(await g.ui.select(O,D.map(e=>m(e,x.majorMode[e]??[],S)))??``)])?.[0];if(!k)return;let A=i.alreadyComposed();if(k===S){g.ui.notify(y(k,(0,s.resolveLayers)(x,k),S,A),`info`);return}let j=n.filterHookDisabledLayers((0,s.resolveLayers)(x,k),E),M=r.needsRelaunch(x,C,j);t.persistHarnessSelection(l,r.applyMajorMode(x,k,(0,o.requireDoomConfigContext)(g).harness)),u.recordEvent(e.HARNESS_EVENT.majorModeSwitched,{"harness.major_mode.previous":S,"harness.major_mode":k,"harness.layers":j.join(`,`),"harness.major_mode.stale":M}),g.ui.setStatus(c,_(g.ui.theme,k,w,T,M&&!A)),g.ui.notify(v(k,j,M,A),`info`),await g.waitForIdle(),await g.reload()}})}exports.applySummary=v,exports.colorStatus=_,exports.default=x,exports.majorModeItems=p,exports.majorModeNames=f,exports.majorModeOptionLabel=m,exports.majorModeSummary=y,exports.optionName=h,exports.statusText=g;
6
+ //# sourceMappingURL=majorMode.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"majorMode.cjs","names":["createHarnessTelemetry","HARNESS_EVENT","MatrixPickerComponent","alreadyComposed","filterHookDisabledLayers","needsRelaunch","applyMajorMode"],"sources":["../../src/entries/majorMode.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config';\nimport type { ExtensionAPI, ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport type { SelectItem } from '@earendil-works/pi-tui';\nimport { persistHarnessSelection, requireHarnessRoot } from '../config/harnessState.ts';\nimport { type MajorModesConfig, loadMajorModesConfig, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { createHarnessTelemetry, HARNESS_EVENT, type HarnessTelemetry } from '../logSinkTelemetry.ts';\nimport { alreadyComposed } from '../services/composer.ts';\nimport { filterHookDisabledLayers } from '../services/extensionAssembler.ts';\nimport { applyMajorMode, needsRelaunch } from '../services/matrixSwitcher.ts';\nimport { MatrixPickerComponent } from './components/matrixPicker.ts';\n\nconst STATUS_KEY = 'doom-major-mode';\nconst OPTION_PREFIX = /^\\[[ x]\\] /;\nconst CORE_ONLY = 'core only';\nconst MARK_ON = '[x]';\nconst MARK_OFF = '[ ]';\nconst RELAUNCH = 'Relaunch with:';\nconst MAJOR_MODE_OPTION = '--major-mode';\n\n/** Major mode names in the declaration order used by the picker. */\nexport function majorModeNames(config: MajorModesConfig): string[] {\n return Object.keys(config.majorMode);\n}\n\n/** Picker rows show the resolved layers while retaining bare major mode values. */\nexport function majorModeItems(config: MajorModesConfig, names: string[]): SelectItem[] {\n return names.map((name) => ({\n value: name,\n label: name,\n description: (config.majorMode[name] ?? []).join(', ') || CORE_ONLY,\n }));\n}\n\nexport function majorModeOptionLabel(name: string, layers: string[], current: string): string {\n return `${name === current ? MARK_ON : MARK_OFF} ${name}: ${layers.join(', ') || CORE_ONLY}`;\n}\n\nexport function optionName(option: string): string {\n return option.replace(OPTION_PREFIX, '').split(':')[0] ?? option;\n}\n\n/** Compact footer text for the selected major mode, domains, and profile. */\nexport function statusText(majorMode: string, domains: readonly string[], profile?: string): string {\n return [profile ? `*${profile}*` : undefined, `[${majorMode}]`, domains.join(',')]\n .filter((part) => Boolean(part))\n .join(':');\n}\n\nexport function colorStatus(\n theme: Theme,\n majorMode: string,\n domains: readonly string[],\n profile: string | undefined,\n pending: boolean,\n): string {\n const parts = [\n profile ? theme.fg('success', theme.bold(`*${profile}*`)) : undefined,\n theme.fg(pending ? 'warning' : 'accent', `[${majorMode}]`),\n domains.length > 0 ? theme.fg('muted', domains.join(',')) : undefined,\n ].filter((part): part is string => Boolean(part));\n return parts.join(theme.fg('dim', ':'));\n}\n\n/**\n * What a switch actually applied.\n *\n * A synced session composes its extension set on every load, so a reload picks\n * up the new layers outright. A launcher session cannot: Pi freezes the CLI\n * `--extension` list at construction, so a layer that contributes extensions\n * needs a relaunch there and only the hooks change in place.\n */\nexport function applySummary(picked: string, layers: string[], stale: boolean, composed = false): string {\n const head = `Switched to ${picked}: ${layers.join(', ') || CORE_ONLY}`;\n if (!stale || composed) return [head, 'Hooks reloaded.'].join('\\n');\n return [\n head,\n 'Hooks reloaded. Extensions are fixed at launch, so for those:',\n ` ./pi.sh ${MAJOR_MODE_OPTION} ${picked}`,\n ].join('\\n');\n}\n\nexport function majorModeSummary(picked: string, layers: string[], current: string, composed = false): string {\n const contents = `Major mode ${picked}: ${layers.join(', ') || CORE_ONLY}`;\n if (picked !== current && !composed) {\n return [contents, `${RELAUNCH}\\n ./pi.sh ${MAJOR_MODE_OPTION} ${picked}`].join('\\n');\n }\n if (picked !== current) return contents;\n return [contents, 'Already using this major mode.'].join('\\n');\n}\n\ninterface MajorModeView {\n config: MajorModesConfig;\n majorMode: string;\n active: string[];\n domains: readonly string[];\n profile?: string;\n hooks: boolean;\n}\n\nfunction currentView(ctx: ExtensionContext): MajorModeView {\n const state = requireDoomConfigContext(ctx).harness;\n const root = requireHarnessRoot(state);\n const config = loadMajorModesConfig(root);\n const resolved = resolveLayers(config, state.majorMode);\n return {\n config,\n majorMode: state.majorMode,\n active: state.layers.length === 0 ? resolved : [...state.layers],\n domains: state.domains,\n profile: state.profile,\n hooks: state.hooks,\n };\n}\n\nexport default function majorModeExtension(\n pi: ExtensionAPI,\n telemetry: HarnessTelemetry = createHarnessTelemetry(),\n): void {\n pi.on('session_start', (_event, ctx) => {\n try {\n const { majorMode, domains, profile } = currentView(ctx);\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, majorMode, domains, profile, false));\n } catch (error) {\n // The status line degrades to a message nobody reads, while the run keeps\n // going with whatever layers the environment happened to carry.\n void telemetry.recordWarning(HARNESS_EVENT.majorModeUnavailable, error);\n ctx.ui.setStatus(\n STATUS_KEY,\n `major mode unavailable (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n });\n\n pi.registerCommand('major-mode', {\n description: 'Pick a named major mode',\n handler: async (args, ctx) => {\n if (args.trim()) {\n ctx.ui.notify('Usage: /major-mode', 'warning');\n return;\n }\n\n const { config, majorMode, active, domains, profile, hooks } = currentView(ctx);\n const names = majorModeNames(config);\n const title = `Major mode (current: ${majorMode})`;\n const chosen =\n ctx.mode === 'tui'\n ? await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: majorModeItems(config, names), selected: [majorMode], multi: false },\n theme,\n keybindings,\n done,\n ),\n )\n : [\n optionName(\n (await ctx.ui.select(\n title,\n names.map((name) => majorModeOptionLabel(name, config.majorMode[name] ?? [], majorMode)),\n )) ?? '',\n ),\n ];\n const picked = chosen?.[0];\n if (!picked) return;\n\n const composed = alreadyComposed();\n if (picked === majorMode) {\n ctx.ui.notify(majorModeSummary(picked, resolveLayers(config, picked), majorMode, composed), 'info');\n return;\n }\n\n const selected = filterHookDisabledLayers(resolveLayers(config, picked), hooks);\n const stale = needsRelaunch(config, active, selected);\n const updated = applyMajorMode(config, picked, requireDoomConfigContext(ctx).harness);\n persistHarnessSelection(pi, updated);\n void telemetry.recordEvent(HARNESS_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': stale,\n });\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, picked, domains, profile, stale && !composed));\n ctx.ui.notify(applySummary(picked, selected, stale, composed), 'info');\n await ctx.waitForIdle();\n await ctx.reload();\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { HarnessTelemetry } from "../logSinkTelemetry.cjs";
2
+ import { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent";
3
+ import { MajorModesConfig } from "@agimon-ai/doompi-config/majorModes";
4
+ import { SelectItem } from "@earendil-works/pi-tui";
5
+
6
+ //#region src/entries/majorMode.d.ts
7
+ /** Major mode names in the declaration order used by the picker. */
8
+ declare function majorModeNames(config: MajorModesConfig): string[];
9
+ /** Picker rows show the resolved layers while retaining bare major mode values. */
10
+ declare function majorModeItems(config: MajorModesConfig, names: string[]): SelectItem[];
11
+ declare function majorModeOptionLabel(name: string, layers: string[], current: string): string;
12
+ declare function optionName(option: string): string;
13
+ /** Compact footer text for the selected major mode, domains, and profile. */
14
+ declare function statusText(majorMode: string, domains: readonly string[], profile?: string): string;
15
+ declare function colorStatus(theme: Theme, majorMode: string, domains: readonly string[], profile: string | undefined, pending: boolean): string;
16
+ /**
17
+ * What a switch actually applied.
18
+ *
19
+ * A synced session composes its extension set on every load, so a reload picks
20
+ * up the new layers outright. A launcher session cannot: Pi freezes the CLI
21
+ * `--extension` list at construction, so a layer that contributes extensions
22
+ * needs a relaunch there and only the hooks change in place.
23
+ */
24
+ declare function applySummary(picked: string, layers: string[], stale: boolean, composed?: boolean): string;
25
+ declare function majorModeSummary(picked: string, layers: string[], current: string, composed?: boolean): string;
26
+ declare function majorModeExtension(pi: ExtensionAPI, telemetry?: HarnessTelemetry): void;
27
+ //#endregion
28
+ export { applySummary, colorStatus, majorModeExtension as default, majorModeItems, majorModeNames, majorModeOptionLabel, majorModeSummary, optionName, statusText };
29
+ //# sourceMappingURL=majorMode.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"majorMode.d.cts","names":[],"sources":["../../src/entries/majorMode.ts"],"mappings":";;;;;;;iBAoBgB,cAAA,CAAe,MAAA,EAAQ,gBAAA;AAAvC;AAAA,iBAKgB,cAAA,CAAe,MAAA,EAAQ,gBAAA,EAAkB,KAAA,aAAkB,UAAA;AAAA,iBAQ3D,oBAAA,CAAqB,IAAA,UAAc,MAAA,YAAkB,OAAA;AAAA,iBAIrD,UAAA,CAAW,MAAA;;iBAKX,UAAA,CAAW,SAAA,UAAmB,OAAA,qBAA4B,OAAA;AAAA,iBAM1D,WAAA,CACd,KAAA,EAAO,KAAA,EACP,SAAA,UACA,OAAA,qBACA,OAAA,sBACA,OAAA;;;;;;;;;iBAkBc,YAAA,CAAa,MAAA,UAAgB,MAAA,YAAkB,KAAA,WAAgB,QAAA;AAAA,iBAU/D,gBAAA,CAAiB,MAAA,UAAgB,MAAA,YAAkB,OAAA,UAAiB,QAAA;AAAA,iBAiC5D,kBAAA,CACtB,EAAA,EAAI,YAAA,EACJ,SAAA,GAAW,gBAAA"}
@@ -0,0 +1,29 @@
1
+ import { HarnessTelemetry } from "../logSinkTelemetry.mjs";
2
+ import { MajorModesConfig } from "@agimon-ai/doompi-config/majorModes";
3
+ import { ExtensionAPI, Theme } from "@earendil-works/pi-coding-agent";
4
+ import { SelectItem } from "@earendil-works/pi-tui";
5
+
6
+ //#region src/entries/majorMode.d.ts
7
+ /** Major mode names in the declaration order used by the picker. */
8
+ declare function majorModeNames(config: MajorModesConfig): string[];
9
+ /** Picker rows show the resolved layers while retaining bare major mode values. */
10
+ declare function majorModeItems(config: MajorModesConfig, names: string[]): SelectItem[];
11
+ declare function majorModeOptionLabel(name: string, layers: string[], current: string): string;
12
+ declare function optionName(option: string): string;
13
+ /** Compact footer text for the selected major mode, domains, and profile. */
14
+ declare function statusText(majorMode: string, domains: readonly string[], profile?: string): string;
15
+ declare function colorStatus(theme: Theme, majorMode: string, domains: readonly string[], profile: string | undefined, pending: boolean): string;
16
+ /**
17
+ * What a switch actually applied.
18
+ *
19
+ * A synced session composes its extension set on every load, so a reload picks
20
+ * up the new layers outright. A launcher session cannot: Pi freezes the CLI
21
+ * `--extension` list at construction, so a layer that contributes extensions
22
+ * needs a relaunch there and only the hooks change in place.
23
+ */
24
+ declare function applySummary(picked: string, layers: string[], stale: boolean, composed?: boolean): string;
25
+ declare function majorModeSummary(picked: string, layers: string[], current: string, composed?: boolean): string;
26
+ declare function majorModeExtension(pi: ExtensionAPI, telemetry?: HarnessTelemetry): void;
27
+ //#endregion
28
+ export { applySummary, colorStatus, majorModeExtension as default, majorModeItems, majorModeNames, majorModeOptionLabel, majorModeSummary, optionName, statusText };
29
+ //# sourceMappingURL=majorMode.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"majorMode.d.mts","names":[],"sources":["../../src/entries/majorMode.ts"],"mappings":";;;;;;;iBAoBgB,cAAA,CAAe,MAAA,EAAQ,gBAAA;AAAvC;AAAA,iBAKgB,cAAA,CAAe,MAAA,EAAQ,gBAAA,EAAkB,KAAA,aAAkB,UAAA;AAAA,iBAQ3D,oBAAA,CAAqB,IAAA,UAAc,MAAA,YAAkB,OAAA;AAAA,iBAIrD,UAAA,CAAW,MAAA;;iBAKX,UAAA,CAAW,SAAA,UAAmB,OAAA,qBAA4B,OAAA;AAAA,iBAM1D,WAAA,CACd,KAAA,EAAO,KAAA,EACP,SAAA,UACA,OAAA,qBACA,OAAA,sBACA,OAAA;;;;;;;;;iBAkBc,YAAA,CAAa,MAAA,UAAgB,MAAA,YAAkB,KAAA,WAAgB,QAAA;AAAA,iBAU/D,gBAAA,CAAiB,MAAA,UAAgB,MAAA,YAAkB,OAAA,UAAiB,QAAA;AAAA,iBAiC5D,kBAAA,CACtB,EAAA,EAAI,YAAA,EACJ,SAAA,GAAW,gBAAA"}
@@ -0,0 +1,6 @@
1
+ import{HARNESS_EVENT as e,createHarnessTelemetry as t}from"../logSinkTelemetry.mjs";import{persistHarnessSelection as n,requireHarnessRoot as r}from"../config/harnessState.mjs";import{filterHookDisabledLayers as i}from"../services/extensionAssembler.mjs";import{applyMajorMode as a,needsRelaunch as o}from"../services/matrixSwitcher.mjs";import{alreadyComposed as s}from"../services/composer.mjs";import{MatrixPickerComponent as c}from"./components/matrixPicker.mjs";import{requireDoomConfigContext as l}from"@agimon-ai/doompi-config";import{loadMajorModesConfig as u,resolveLayers as d}from"@agimon-ai/doompi-config/majorModes";const f=`doom-major-mode`,p=/^\[[ x]\] /,m=`core only`,h=`--major-mode`;function g(e){return Object.keys(e.majorMode)}function _(e,t){return t.map(t=>({value:t,label:t,description:(e.majorMode[t]??[]).join(`, `)||m}))}function v(e,t,n){return`${e===n?`[x]`:`[ ]`} ${e}: ${t.join(`, `)||m}`}function y(e){return e.replace(p,``).split(`:`)[0]??e}function b(e,t,n){return[n?`*${n}*`:void 0,`[${e}]`,t.join(`,`)].filter(e=>!!e).join(`:`)}function x(e,t,n,r,i){return[r?e.fg(`success`,e.bold(`*${r}*`)):void 0,e.fg(i?`warning`:`accent`,`[${t}]`),n.length>0?e.fg(`muted`,n.join(`,`)):void 0].filter(e=>!!e).join(e.fg(`dim`,`:`))}function S(e,t,n,r=!1){let i=`Switched to ${e}: ${t.join(`, `)||m}`;return!n||r?[i,`Hooks reloaded.`].join(`
2
+ `):[i,`Hooks reloaded. Extensions are fixed at launch, so for those:`,` ./pi.sh ${h} ${e}`].join(`
3
+ `)}function C(e,t,n,r=!1){let i=`Major mode ${e}: ${t.join(`, `)||m}`;return e!==n&&!r?[i,`Relaunch with:\n ./pi.sh ${h} ${e}`].join(`
4
+ `):e===n?[i,`Already using this major mode.`].join(`
5
+ `):i}function w(e){let t=l(e).harness,n=u(r(t)),i=d(n,t.majorMode);return{config:n,majorMode:t.majorMode,active:t.layers.length===0?i:[...t.layers],domains:t.domains,profile:t.profile,hooks:t.hooks}}function T(r,u=t()){r.on(`session_start`,(t,n)=>{try{let{majorMode:e,domains:t,profile:r}=w(n);n.ui.setStatus(f,x(n.ui.theme,e,t,r,!1))}catch(t){u.recordWarning(e.majorModeUnavailable,t),n.ui.setStatus(f,`major mode unavailable (${t instanceof Error?t.message:String(t)})`)}}),r.registerCommand(`major-mode`,{description:`Pick a named major mode`,handler:async(t,p)=>{if(t.trim()){p.ui.notify(`Usage: /major-mode`,`warning`);return}let{config:m,majorMode:h,active:b,domains:T,profile:E,hooks:D}=w(p),O=g(m),k=`Major mode (current: ${h})`,A=(p.mode===`tui`?await p.ui.custom((e,t,n,r)=>new c({title:k,items:_(m,O),selected:[h],multi:!1},t,n,r)):[y(await p.ui.select(k,O.map(e=>v(e,m.majorMode[e]??[],h)))??``)])?.[0];if(!A)return;let j=s();if(A===h){p.ui.notify(C(A,d(m,A),h,j),`info`);return}let M=i(d(m,A),D),N=o(m,b,M);n(r,a(m,A,l(p).harness)),u.recordEvent(e.majorModeSwitched,{"harness.major_mode.previous":h,"harness.major_mode":A,"harness.layers":M.join(`,`),"harness.major_mode.stale":N}),p.ui.setStatus(f,x(p.ui.theme,A,T,E,N&&!j)),p.ui.notify(S(A,M,N,j),`info`),await p.waitForIdle(),await p.reload()}})}export{S as applySummary,x as colorStatus,T as default,_ as majorModeItems,g as majorModeNames,v as majorModeOptionLabel,C as majorModeSummary,y as optionName,b as statusText};
6
+ //# sourceMappingURL=majorMode.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"majorMode.mjs","names":[],"sources":["../../src/entries/majorMode.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config';\nimport type { ExtensionAPI, ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport type { SelectItem } from '@earendil-works/pi-tui';\nimport { persistHarnessSelection, requireHarnessRoot } from '../config/harnessState.ts';\nimport { type MajorModesConfig, loadMajorModesConfig, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { createHarnessTelemetry, HARNESS_EVENT, type HarnessTelemetry } from '../logSinkTelemetry.ts';\nimport { alreadyComposed } from '../services/composer.ts';\nimport { filterHookDisabledLayers } from '../services/extensionAssembler.ts';\nimport { applyMajorMode, needsRelaunch } from '../services/matrixSwitcher.ts';\nimport { MatrixPickerComponent } from './components/matrixPicker.ts';\n\nconst STATUS_KEY = 'doom-major-mode';\nconst OPTION_PREFIX = /^\\[[ x]\\] /;\nconst CORE_ONLY = 'core only';\nconst MARK_ON = '[x]';\nconst MARK_OFF = '[ ]';\nconst RELAUNCH = 'Relaunch with:';\nconst MAJOR_MODE_OPTION = '--major-mode';\n\n/** Major mode names in the declaration order used by the picker. */\nexport function majorModeNames(config: MajorModesConfig): string[] {\n return Object.keys(config.majorMode);\n}\n\n/** Picker rows show the resolved layers while retaining bare major mode values. */\nexport function majorModeItems(config: MajorModesConfig, names: string[]): SelectItem[] {\n return names.map((name) => ({\n value: name,\n label: name,\n description: (config.majorMode[name] ?? []).join(', ') || CORE_ONLY,\n }));\n}\n\nexport function majorModeOptionLabel(name: string, layers: string[], current: string): string {\n return `${name === current ? MARK_ON : MARK_OFF} ${name}: ${layers.join(', ') || CORE_ONLY}`;\n}\n\nexport function optionName(option: string): string {\n return option.replace(OPTION_PREFIX, '').split(':')[0] ?? option;\n}\n\n/** Compact footer text for the selected major mode, domains, and profile. */\nexport function statusText(majorMode: string, domains: readonly string[], profile?: string): string {\n return [profile ? `*${profile}*` : undefined, `[${majorMode}]`, domains.join(',')]\n .filter((part) => Boolean(part))\n .join(':');\n}\n\nexport function colorStatus(\n theme: Theme,\n majorMode: string,\n domains: readonly string[],\n profile: string | undefined,\n pending: boolean,\n): string {\n const parts = [\n profile ? theme.fg('success', theme.bold(`*${profile}*`)) : undefined,\n theme.fg(pending ? 'warning' : 'accent', `[${majorMode}]`),\n domains.length > 0 ? theme.fg('muted', domains.join(',')) : undefined,\n ].filter((part): part is string => Boolean(part));\n return parts.join(theme.fg('dim', ':'));\n}\n\n/**\n * What a switch actually applied.\n *\n * A synced session composes its extension set on every load, so a reload picks\n * up the new layers outright. A launcher session cannot: Pi freezes the CLI\n * `--extension` list at construction, so a layer that contributes extensions\n * needs a relaunch there and only the hooks change in place.\n */\nexport function applySummary(picked: string, layers: string[], stale: boolean, composed = false): string {\n const head = `Switched to ${picked}: ${layers.join(', ') || CORE_ONLY}`;\n if (!stale || composed) return [head, 'Hooks reloaded.'].join('\\n');\n return [\n head,\n 'Hooks reloaded. Extensions are fixed at launch, so for those:',\n ` ./pi.sh ${MAJOR_MODE_OPTION} ${picked}`,\n ].join('\\n');\n}\n\nexport function majorModeSummary(picked: string, layers: string[], current: string, composed = false): string {\n const contents = `Major mode ${picked}: ${layers.join(', ') || CORE_ONLY}`;\n if (picked !== current && !composed) {\n return [contents, `${RELAUNCH}\\n ./pi.sh ${MAJOR_MODE_OPTION} ${picked}`].join('\\n');\n }\n if (picked !== current) return contents;\n return [contents, 'Already using this major mode.'].join('\\n');\n}\n\ninterface MajorModeView {\n config: MajorModesConfig;\n majorMode: string;\n active: string[];\n domains: readonly string[];\n profile?: string;\n hooks: boolean;\n}\n\nfunction currentView(ctx: ExtensionContext): MajorModeView {\n const state = requireDoomConfigContext(ctx).harness;\n const root = requireHarnessRoot(state);\n const config = loadMajorModesConfig(root);\n const resolved = resolveLayers(config, state.majorMode);\n return {\n config,\n majorMode: state.majorMode,\n active: state.layers.length === 0 ? resolved : [...state.layers],\n domains: state.domains,\n profile: state.profile,\n hooks: state.hooks,\n };\n}\n\nexport default function majorModeExtension(\n pi: ExtensionAPI,\n telemetry: HarnessTelemetry = createHarnessTelemetry(),\n): void {\n pi.on('session_start', (_event, ctx) => {\n try {\n const { majorMode, domains, profile } = currentView(ctx);\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, majorMode, domains, profile, false));\n } catch (error) {\n // The status line degrades to a message nobody reads, while the run keeps\n // going with whatever layers the environment happened to carry.\n void telemetry.recordWarning(HARNESS_EVENT.majorModeUnavailable, error);\n ctx.ui.setStatus(\n STATUS_KEY,\n `major mode unavailable (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n });\n\n pi.registerCommand('major-mode', {\n description: 'Pick a named major mode',\n handler: async (args, ctx) => {\n if (args.trim()) {\n ctx.ui.notify('Usage: /major-mode', 'warning');\n return;\n }\n\n const { config, majorMode, active, domains, profile, hooks } = currentView(ctx);\n const names = majorModeNames(config);\n const title = `Major mode (current: ${majorMode})`;\n const chosen =\n ctx.mode === 'tui'\n ? await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: majorModeItems(config, names), selected: [majorMode], multi: false },\n theme,\n keybindings,\n done,\n ),\n )\n : [\n optionName(\n (await ctx.ui.select(\n title,\n names.map((name) => majorModeOptionLabel(name, config.majorMode[name] ?? [], majorMode)),\n )) ?? '',\n ),\n ];\n const picked = chosen?.[0];\n if (!picked) return;\n\n const composed = alreadyComposed();\n if (picked === majorMode) {\n ctx.ui.notify(majorModeSummary(picked, resolveLayers(config, picked), majorMode, composed), 'info');\n return;\n }\n\n const selected = filterHookDisabledLayers(resolveLayers(config, picked), hooks);\n const stale = needsRelaunch(config, active, selected);\n const updated = applyMajorMode(config, picked, requireDoomConfigContext(ctx).harness);\n persistHarnessSelection(pi, updated);\n void telemetry.recordEvent(HARNESS_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': stale,\n });\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, picked, domains, profile, stale && !composed));\n ctx.ui.notify(applySummary(picked, selected, stale, composed), 'info');\n await ctx.waitForIdle();\n await ctx.reload();\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../node_modules/.pnpm/@juicesharp_rpiv-ask-user-question@2.2.0_@earendil-works_pi-coding-agent@0.84.1_support_6ba1249e24a50b62791c1c91c9f324c6/node_modules/@juicesharp/rpiv-ask-user-question/events.cjs`);let n=require(`node:path`);n=e.__toESM(n,1);const r=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`];function i(e){let t=e.replace(/\s+/g,` `).trim();if(t)return t.length>36?`${t.slice(0,35)}…`:t}function a(e,t,r,i){let a=i?`${i} `:``,o=n.default.basename(t),s=e.getSessionName()??r;return s?`${a}π - ${s} - ${o}`:`${a}π - ${o}`}function o(e){let t=e.replace(/\s+/g,` `).trim();return t.length>240?`${t.slice(0,239)}…`:t}async function s(e,t,n){try{return(await e.exec(t,n,{timeout:3e3})).code===0}catch{return!1}}async function c(e,t,n=process.platform){let r=o(t.body);await s(e,`cmux`,[`notify`,`--title`,t.title,`--subtitle`,t.subtitle,`--body`,r])||n!==`darwin`||await s(e,`osascript`,[`-e`,`on run argv`,`-e`,`display notification (item 3 of argv) with title (item 1 of argv) subtitle (item 2 of argv)`,`-e`,`end run`,t.title,t.subtitle,r])}function l(e,t,n){let r=e.confirm.bind(e);e.confirm=(e,i,a)=>(t()&&n(`${e}: ${i}`),r(e,i,a));let i=e.select.bind(e);e.select=(e,r,a)=>(t()&&n(e),i(e,r,a));let a=e.input.bind(e);e.input=(e,r,i)=>(t()&&n(e),a(e,r,i));let o=e.editor.bind(e);e.editor=(e,r)=>(t()&&n(e),o(e,r))}function u(e){if(process.env.PI_SUBAGENT_CHILD)return;let o=!1,s=!1,u,d=0,f,p=new WeakSet,m=t=>{f&&=(clearInterval(f),void 0),d=0,t.hasUI&&t.ui.setTitle(a(e,t.cwd,u))},h=t=>{if(m(t),!t.hasUI)return;let n=()=>{t.ui.setTitle(a(e,t.cwd,u,r[d%r.length])),d+=1};n(),f=setInterval(n,80)},g=t=>{c(e,{title:`Pi needs your input`,subtitle:`Approval or feedback required`,body:t})};e.events.on(t.ASK_USER_PROMPT_EVENT,e=>{g(e.questions[0]?.question??`The agent is waiting for your feedback.`)}),e.events.on(t.ASK_USER_BLOCKED_EVENT,e=>{s=e.active}),e.on(`input`,(t,n)=>{u||t.source===`extension`||(u=i(t.text),u&&n.hasUI&&n.ui.setTitle(a(e,n.cwd,u)))}),e.on(`session_start`,(e,t)=>{p.has(t.ui)||(p.add(t.ui),l(t.ui,()=>o&&!s,g))}),e.on(`agent_start`,(e,t)=>{o=!0,h(t)}),e.on(`agent_settled`,async(t,r)=>{o=!1,s=!1,m(r),!r.hasPendingMessages()&&await c(e,{title:`Pi finished`,subtitle:e.getSessionName()??n.default.basename(r.cwd),body:`The agent finished its work and is waiting for you.`})}),e.on(`session_shutdown`,(e,t)=>{o=!1,s=!1,m(t)})}exports.default=u,exports.sendSystemNotification=c;
2
+ //# sourceMappingURL=notifications.cjs.map