@caupulican/pi-adaptative 0.80.103 → 0.81.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 (401) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/dist/cli/session-picker.d.ts +1 -1
  3. package/dist/cli/session-picker.d.ts.map +1 -1
  4. package/dist/cli/session-picker.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +7 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/agent-session-runtime.d.ts +1 -1
  9. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  10. package/dist/core/agent-session-runtime.js +6 -6
  11. package/dist/core/agent-session-runtime.js.map +1 -1
  12. package/dist/core/agent-session-services.d.ts +1 -1
  13. package/dist/core/agent-session-services.d.ts.map +1 -1
  14. package/dist/core/agent-session-services.js.map +1 -1
  15. package/dist/core/agent-session.d.ts +152 -512
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +635 -4590
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/autonomy/session-lane-record.d.ts +1 -1
  20. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
  21. package/dist/core/autonomy/session-lane-record.js.map +1 -1
  22. package/dist/core/autonomy/status.d.ts +1 -0
  23. package/dist/core/autonomy/status.d.ts.map +1 -1
  24. package/dist/core/autonomy/status.js +1 -0
  25. package/dist/core/autonomy/status.js.map +1 -1
  26. package/dist/core/autonomy-telemetry.d.ts +80 -0
  27. package/dist/core/autonomy-telemetry.d.ts.map +1 -0
  28. package/dist/core/autonomy-telemetry.js +266 -0
  29. package/dist/core/autonomy-telemetry.js.map +1 -0
  30. package/dist/core/background-lane-controller.d.ts +186 -0
  31. package/dist/core/background-lane-controller.d.ts.map +1 -0
  32. package/dist/core/background-lane-controller.js +691 -0
  33. package/dist/core/background-lane-controller.js.map +1 -0
  34. package/dist/core/bash-execution-controller.d.ts +51 -0
  35. package/dist/core/bash-execution-controller.d.ts.map +1 -0
  36. package/dist/core/bash-execution-controller.js +96 -0
  37. package/dist/core/bash-execution-controller.js.map +1 -0
  38. package/dist/core/bash-executor.d.ts.map +1 -1
  39. package/dist/core/bash-executor.js +9 -2
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/compaction-support.d.ts +56 -0
  42. package/dist/core/compaction-support.d.ts.map +1 -0
  43. package/dist/core/compaction-support.js +99 -0
  44. package/dist/core/compaction-support.js.map +1 -0
  45. package/dist/core/context/artifact-retrieval.d.ts +1 -1
  46. package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
  47. package/dist/core/context/artifact-retrieval.js +1 -1
  48. package/dist/core/context/artifact-retrieval.js.map +1 -1
  49. package/dist/core/context/context-composition.d.ts.map +1 -1
  50. package/dist/core/context/context-composition.js +1 -1
  51. package/dist/core/context/context-composition.js.map +1 -1
  52. package/dist/core/context/tool-output-packer.d.ts +1 -1
  53. package/dist/core/context/tool-output-packer.d.ts.map +1 -1
  54. package/dist/core/context/tool-output-packer.js +1 -1
  55. package/dist/core/context/tool-output-packer.js.map +1 -1
  56. package/dist/core/context-gc.d.ts.map +1 -1
  57. package/dist/core/context-gc.js +1 -1
  58. package/dist/core/context-gc.js.map +1 -1
  59. package/dist/core/context-pipeline.d.ts +223 -0
  60. package/dist/core/context-pipeline.d.ts.map +1 -0
  61. package/dist/core/context-pipeline.js +594 -0
  62. package/dist/core/context-pipeline.js.map +1 -0
  63. package/dist/core/cost/daily-usage.d.ts +1 -1
  64. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  65. package/dist/core/cost/daily-usage.js +1 -1
  66. package/dist/core/cost/daily-usage.js.map +1 -1
  67. package/dist/core/cost/session-usage.d.ts +1 -1
  68. package/dist/core/cost/session-usage.d.ts.map +1 -1
  69. package/dist/core/cost/session-usage.js +1 -1
  70. package/dist/core/cost/session-usage.js.map +1 -1
  71. package/dist/core/delegation/session-worker-result.d.ts +1 -1
  72. package/dist/core/delegation/session-worker-result.d.ts.map +1 -1
  73. package/dist/core/delegation/session-worker-result.js.map +1 -1
  74. package/dist/core/exec.d.ts +2 -0
  75. package/dist/core/exec.d.ts.map +1 -1
  76. package/dist/core/exec.js +15 -9
  77. package/dist/core/exec.js.map +1 -1
  78. package/dist/core/export-html/index.d.ts +1 -1
  79. package/dist/core/export-html/index.d.ts.map +1 -1
  80. package/dist/core/export-html/index.js +2 -2
  81. package/dist/core/export-html/index.js.map +1 -1
  82. package/dist/core/extensions/builtin.d.ts.map +1 -1
  83. package/dist/core/extensions/builtin.js +2 -2
  84. package/dist/core/extensions/builtin.js.map +1 -1
  85. package/dist/core/extensions/runner.d.ts +1 -1
  86. package/dist/core/extensions/runner.d.ts.map +1 -1
  87. package/dist/core/extensions/runner.js.map +1 -1
  88. package/dist/core/extensions/types.d.ts +2 -4
  89. package/dist/core/extensions/types.d.ts.map +1 -1
  90. package/dist/core/extensions/types.js.map +1 -1
  91. package/dist/core/goal-loop-controller.d.ts +24 -0
  92. package/dist/core/goal-loop-controller.d.ts.map +1 -0
  93. package/dist/core/goal-loop-controller.js +83 -0
  94. package/dist/core/goal-loop-controller.js.map +1 -0
  95. package/dist/core/goals/goal-runtime-snapshot.d.ts +1 -1
  96. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
  97. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
  98. package/dist/core/goals/session-goal-state.d.ts +1 -1
  99. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  100. package/dist/core/goals/session-goal-state.js.map +1 -1
  101. package/dist/core/index.d.ts +1 -1
  102. package/dist/core/index.d.ts.map +1 -1
  103. package/dist/core/index.js.map +1 -1
  104. package/dist/core/learning/learning-audit.d.ts +1 -1
  105. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  106. package/dist/core/learning/learning-audit.js.map +1 -1
  107. package/dist/core/learning/session-learning-decision.d.ts +1 -1
  108. package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
  109. package/dist/core/learning/session-learning-decision.js.map +1 -1
  110. package/dist/core/local-runtime-controller.d.ts +99 -0
  111. package/dist/core/local-runtime-controller.d.ts.map +1 -0
  112. package/dist/core/local-runtime-controller.js +214 -0
  113. package/dist/core/local-runtime-controller.js.map +1 -0
  114. package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
  115. package/dist/core/memory/providers/transcript-recall.js +1 -1
  116. package/dist/core/memory/providers/transcript-recall.js.map +1 -1
  117. package/dist/core/memory-controller.d.ts +139 -0
  118. package/dist/core/memory-controller.d.ts.map +1 -0
  119. package/dist/core/memory-controller.js +323 -0
  120. package/dist/core/memory-controller.js.map +1 -0
  121. package/dist/core/model-router/status.d.ts +1 -1
  122. package/dist/core/model-router/status.d.ts.map +1 -1
  123. package/dist/core/model-router/status.js.map +1 -1
  124. package/dist/core/model-router-controller.d.ts +140 -0
  125. package/dist/core/model-router-controller.d.ts.map +1 -0
  126. package/dist/core/model-router-controller.js +623 -0
  127. package/dist/core/model-router-controller.js.map +1 -0
  128. package/dist/core/model-selection-controller.d.ts +95 -0
  129. package/dist/core/model-selection-controller.d.ts.map +1 -0
  130. package/dist/core/model-selection-controller.js +252 -0
  131. package/dist/core/model-selection-controller.js.map +1 -0
  132. package/dist/core/models/model-ref.d.ts +13 -0
  133. package/dist/core/models/model-ref.d.ts.map +1 -1
  134. package/dist/core/models/model-ref.js +22 -0
  135. package/dist/core/models/model-ref.js.map +1 -1
  136. package/dist/core/profile-filter-controller.d.ts +77 -0
  137. package/dist/core/profile-filter-controller.d.ts.map +1 -0
  138. package/dist/core/profile-filter-controller.js +159 -0
  139. package/dist/core/profile-filter-controller.js.map +1 -0
  140. package/dist/core/reflection-controller.d.ts +111 -0
  141. package/dist/core/reflection-controller.d.ts.map +1 -0
  142. package/dist/core/reflection-controller.js +412 -0
  143. package/dist/core/reflection-controller.js.map +1 -0
  144. package/dist/core/research/model-fitness.d.ts +12 -0
  145. package/dist/core/research/model-fitness.d.ts.map +1 -1
  146. package/dist/core/research/model-fitness.js +21 -0
  147. package/dist/core/research/model-fitness.js.map +1 -1
  148. package/dist/core/research/session-evidence-bundle.d.ts +1 -1
  149. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
  150. package/dist/core/research/session-evidence-bundle.js.map +1 -1
  151. package/dist/core/runtime-builder.d.ts +222 -0
  152. package/dist/core/runtime-builder.d.ts.map +1 -0
  153. package/dist/core/runtime-builder.js +640 -0
  154. package/dist/core/runtime-builder.js.map +1 -0
  155. package/dist/core/sdk.d.ts +2 -2
  156. package/dist/core/sdk.d.ts.map +1 -1
  157. package/dist/core/sdk.js +3 -4
  158. package/dist/core/sdk.js.map +1 -1
  159. package/dist/core/session-analytics.d.ts +96 -0
  160. package/dist/core/session-analytics.d.ts.map +1 -0
  161. package/dist/core/session-analytics.js +331 -0
  162. package/dist/core/session-analytics.js.map +1 -0
  163. package/dist/core/session-manager-factory.d.ts +18 -0
  164. package/dist/core/session-manager-factory.d.ts.map +1 -0
  165. package/dist/core/session-manager-factory.js +32 -0
  166. package/dist/core/session-manager-factory.js.map +1 -0
  167. package/dist/core/session-tree-navigator.d.ts +68 -0
  168. package/dist/core/session-tree-navigator.d.ts.map +1 -0
  169. package/dist/core/session-tree-navigator.js +217 -0
  170. package/dist/core/session-tree-navigator.js.map +1 -0
  171. package/dist/core/system-prompt-builder.d.ts +63 -0
  172. package/dist/core/system-prompt-builder.d.ts.map +1 -0
  173. package/dist/core/system-prompt-builder.js +181 -0
  174. package/dist/core/system-prompt-builder.js.map +1 -0
  175. package/dist/core/tool-gate-controller.d.ts +36 -0
  176. package/dist/core/tool-gate-controller.d.ts.map +1 -0
  177. package/dist/core/tool-gate-controller.js +94 -0
  178. package/dist/core/tool-gate-controller.js.map +1 -0
  179. package/dist/core/tools/artifact-retrieve.d.ts.map +1 -1
  180. package/dist/core/tools/artifact-retrieve.js +1 -1
  181. package/dist/core/tools/artifact-retrieve.js.map +1 -1
  182. package/dist/core/tools/bash.d.ts +4 -2
  183. package/dist/core/tools/bash.d.ts.map +1 -1
  184. package/dist/core/tools/bash.js +49 -7
  185. package/dist/core/tools/bash.js.map +1 -1
  186. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  187. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  188. package/dist/core/tools/file-mutation-queue.js +61 -1
  189. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  190. package/dist/core/tools/find.d.ts +1 -1
  191. package/dist/core/tools/find.d.ts.map +1 -1
  192. package/dist/core/tools/find.js +1 -1
  193. package/dist/core/tools/find.js.map +1 -1
  194. package/dist/core/tools/grep.d.ts +1 -1
  195. package/dist/core/tools/grep.d.ts.map +1 -1
  196. package/dist/core/tools/grep.js +1 -1
  197. package/dist/core/tools/grep.js.map +1 -1
  198. package/dist/core/tools/index.d.ts +1 -1
  199. package/dist/core/tools/index.d.ts.map +1 -1
  200. package/dist/core/tools/index.js +1 -1
  201. package/dist/core/tools/index.js.map +1 -1
  202. package/dist/core/tools/ls.d.ts +1 -1
  203. package/dist/core/tools/ls.d.ts.map +1 -1
  204. package/dist/core/tools/ls.js +1 -1
  205. package/dist/core/tools/ls.js.map +1 -1
  206. package/dist/core/tools/output-accumulator.d.ts +1 -1
  207. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  208. package/dist/core/tools/output-accumulator.js +1 -1
  209. package/dist/core/tools/output-accumulator.js.map +1 -1
  210. package/dist/core/tools/read.d.ts +1 -1
  211. package/dist/core/tools/read.d.ts.map +1 -1
  212. package/dist/core/tools/read.js +1 -1
  213. package/dist/core/tools/read.js.map +1 -1
  214. package/dist/core/tools/render-utils.d.ts.map +1 -1
  215. package/dist/core/tools/render-utils.js +1 -1
  216. package/dist/core/tools/render-utils.js.map +1 -1
  217. package/dist/index.d.ts +2 -3
  218. package/dist/index.d.ts.map +1 -1
  219. package/dist/index.js +3 -4
  220. package/dist/index.js.map +1 -1
  221. package/dist/main.d.ts.map +1 -1
  222. package/dist/main.js +13 -12
  223. package/dist/main.js.map +1 -1
  224. package/dist/modes/interactive/auth-dialogs-controller.d.ts +59 -0
  225. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -0
  226. package/dist/modes/interactive/auth-dialogs-controller.js +398 -0
  227. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -0
  228. package/dist/modes/interactive/auto-learn-controller.d.ts +168 -0
  229. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -0
  230. package/dist/modes/interactive/auto-learn-controller.js +1239 -0
  231. package/dist/modes/interactive/auto-learn-controller.js.map +1 -0
  232. package/dist/modes/interactive/autocomplete-provider.d.ts +26 -0
  233. package/dist/modes/interactive/autocomplete-provider.d.ts.map +1 -0
  234. package/dist/modes/interactive/autocomplete-provider.js +103 -0
  235. package/dist/modes/interactive/autocomplete-provider.js.map +1 -0
  236. package/dist/modes/interactive/autonomy-commands.d.ts +38 -0
  237. package/dist/modes/interactive/autonomy-commands.d.ts.map +1 -0
  238. package/dist/modes/interactive/autonomy-commands.js +142 -0
  239. package/dist/modes/interactive/autonomy-commands.js.map +1 -0
  240. package/dist/modes/interactive/clipboard-input.d.ts +37 -0
  241. package/dist/modes/interactive/clipboard-input.d.ts.map +1 -0
  242. package/dist/modes/interactive/clipboard-input.js +59 -0
  243. package/dist/modes/interactive/clipboard-input.js.map +1 -0
  244. package/dist/modes/interactive/compaction-queue.d.ts +30 -0
  245. package/dist/modes/interactive/compaction-queue.d.ts.map +1 -0
  246. package/dist/modes/interactive/compaction-queue.js +91 -0
  247. package/dist/modes/interactive/compaction-queue.js.map +1 -0
  248. package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
  249. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  250. package/dist/modes/interactive/components/bash-execution.js +1 -1
  251. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  252. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  253. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  254. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  255. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  256. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  257. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  258. package/dist/modes/interactive/components/custom-message.d.ts +1 -1
  259. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  261. package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
  262. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  263. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  264. package/dist/modes/interactive/components/session-selector.d.ts +1 -1
  265. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  266. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  267. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  268. package/dist/modes/interactive/components/tool-execution.js +2 -2
  269. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  270. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  271. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  273. package/dist/modes/interactive/config-backup.d.ts +27 -0
  274. package/dist/modes/interactive/config-backup.d.ts.map +1 -0
  275. package/dist/modes/interactive/config-backup.js +146 -0
  276. package/dist/modes/interactive/config-backup.js.map +1 -0
  277. package/dist/modes/interactive/editor-overlay-host.d.ts +48 -0
  278. package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -0
  279. package/dist/modes/interactive/editor-overlay-host.js +43 -0
  280. package/dist/modes/interactive/editor-overlay-host.js.map +1 -0
  281. package/dist/modes/interactive/extension-ui-host.d.ts +165 -0
  282. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -0
  283. package/dist/modes/interactive/extension-ui-host.js +610 -0
  284. package/dist/modes/interactive/extension-ui-host.js.map +1 -0
  285. package/dist/modes/interactive/external-editor.d.ts +18 -0
  286. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  287. package/dist/modes/interactive/external-editor.js +107 -0
  288. package/dist/modes/interactive/external-editor.js.map +1 -0
  289. package/dist/modes/interactive/history-reload-math.d.ts +24 -0
  290. package/dist/modes/interactive/history-reload-math.d.ts.map +1 -0
  291. package/dist/modes/interactive/history-reload-math.js +129 -0
  292. package/dist/modes/interactive/history-reload-math.js.map +1 -0
  293. package/dist/modes/interactive/interactive-mode.d.ts +22 -238
  294. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  295. package/dist/modes/interactive/interactive-mode.js +714 -5910
  296. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  297. package/dist/modes/interactive/key-handlers.d.ts +46 -0
  298. package/dist/modes/interactive/key-handlers.d.ts.map +1 -0
  299. package/dist/modes/interactive/key-handlers.js +80 -0
  300. package/dist/modes/interactive/key-handlers.js.map +1 -0
  301. package/dist/modes/interactive/local-model-commands.d.ts +68 -0
  302. package/dist/modes/interactive/local-model-commands.d.ts.map +1 -0
  303. package/dist/modes/interactive/local-model-commands.js +288 -0
  304. package/dist/modes/interactive/local-model-commands.js.map +1 -0
  305. package/dist/modes/interactive/profile-menu-controller.d.ts +77 -0
  306. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -0
  307. package/dist/modes/interactive/profile-menu-controller.js +917 -0
  308. package/dist/modes/interactive/profile-menu-controller.js.map +1 -0
  309. package/dist/modes/interactive/report-commands.d.ts +46 -0
  310. package/dist/modes/interactive/report-commands.d.ts.map +1 -0
  311. package/dist/modes/interactive/report-commands.js +255 -0
  312. package/dist/modes/interactive/report-commands.js.map +1 -0
  313. package/dist/modes/interactive/resource-display.d.ts +73 -0
  314. package/dist/modes/interactive/resource-display.d.ts.map +1 -0
  315. package/dist/modes/interactive/resource-display.js +278 -0
  316. package/dist/modes/interactive/resource-display.js.map +1 -0
  317. package/dist/modes/interactive/resource-shell-commands.d.ts +64 -0
  318. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -0
  319. package/dist/modes/interactive/resource-shell-commands.js +202 -0
  320. package/dist/modes/interactive/resource-shell-commands.js.map +1 -0
  321. package/dist/modes/interactive/session-flow-commands.d.ts +139 -0
  322. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -0
  323. package/dist/modes/interactive/session-flow-commands.js +458 -0
  324. package/dist/modes/interactive/session-flow-commands.js.map +1 -0
  325. package/dist/modes/interactive/session-io-commands.d.ts +73 -0
  326. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -0
  327. package/dist/modes/interactive/session-io-commands.js +202 -0
  328. package/dist/modes/interactive/session-io-commands.js.map +1 -0
  329. package/dist/modes/interactive/settings-selector-flow.d.ts +42 -0
  330. package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -0
  331. package/dist/modes/interactive/settings-selector-flow.js +287 -0
  332. package/dist/modes/interactive/settings-selector-flow.js.map +1 -0
  333. package/dist/modes/interactive/signal-lifecycle.d.ts +55 -0
  334. package/dist/modes/interactive/signal-lifecycle.d.ts.map +1 -0
  335. package/dist/modes/interactive/signal-lifecycle.js +177 -0
  336. package/dist/modes/interactive/signal-lifecycle.js.map +1 -0
  337. package/dist/modes/interactive/startup-checks.d.ts +38 -0
  338. package/dist/modes/interactive/startup-checks.d.ts.map +1 -0
  339. package/dist/modes/interactive/startup-checks.js +189 -0
  340. package/dist/modes/interactive/startup-checks.js.map +1 -0
  341. package/dist/modes/rpc/rpc-client.d.ts +1 -1
  342. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  343. package/dist/modes/rpc/rpc-client.js.map +1 -1
  344. package/dist/modes/rpc/rpc-types.d.ts +1 -1
  345. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  346. package/dist/modes/rpc/rpc-types.js.map +1 -1
  347. package/dist/utils/paths.d.ts +2 -14
  348. package/dist/utils/paths.d.ts.map +1 -1
  349. package/dist/utils/paths.js +5 -30
  350. package/dist/utils/paths.js.map +1 -1
  351. package/dist/utils/process-memory.d.ts +8 -0
  352. package/dist/utils/process-memory.d.ts.map +1 -0
  353. package/dist/utils/process-memory.js +11 -0
  354. package/dist/utils/process-memory.js.map +1 -0
  355. package/dist/utils/shell.d.ts +0 -9
  356. package/dist/utils/shell.d.ts.map +1 -1
  357. package/dist/utils/shell.js +0 -37
  358. package/dist/utils/shell.js.map +1 -1
  359. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  360. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  361. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  362. package/examples/extensions/sandbox/package-lock.json +2 -2
  363. package/examples/extensions/sandbox/package.json +1 -1
  364. package/examples/extensions/with-deps/package-lock.json +2 -2
  365. package/examples/extensions/with-deps/package.json +1 -1
  366. package/examples/sdk/11-sessions.ts +8 -8
  367. package/examples/sdk/13-session-runtime.ts +1 -1
  368. package/npm-shrinkwrap.json +12 -12
  369. package/package.json +4 -4
  370. package/dist/core/compaction/branch-summarization.d.ts +0 -88
  371. package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
  372. package/dist/core/compaction/branch-summarization.js +0 -243
  373. package/dist/core/compaction/branch-summarization.js.map +0 -1
  374. package/dist/core/compaction/compaction.d.ts +0 -143
  375. package/dist/core/compaction/compaction.d.ts.map +0 -1
  376. package/dist/core/compaction/compaction.js +0 -659
  377. package/dist/core/compaction/compaction.js.map +0 -1
  378. package/dist/core/compaction/index.d.ts +0 -7
  379. package/dist/core/compaction/index.d.ts.map +0 -1
  380. package/dist/core/compaction/index.js +0 -7
  381. package/dist/core/compaction/index.js.map +0 -1
  382. package/dist/core/compaction/utils.d.ts +0 -38
  383. package/dist/core/compaction/utils.d.ts.map +0 -1
  384. package/dist/core/compaction/utils.js +0 -153
  385. package/dist/core/compaction/utils.js.map +0 -1
  386. package/dist/core/message-retention.d.ts +0 -26
  387. package/dist/core/message-retention.d.ts.map +0 -1
  388. package/dist/core/message-retention.js +0 -95
  389. package/dist/core/message-retention.js.map +0 -1
  390. package/dist/core/messages.d.ts +0 -77
  391. package/dist/core/messages.d.ts.map +0 -1
  392. package/dist/core/messages.js +0 -123
  393. package/dist/core/messages.js.map +0 -1
  394. package/dist/core/session-manager.d.ts +0 -337
  395. package/dist/core/session-manager.d.ts.map +0 -1
  396. package/dist/core/session-manager.js +0 -1328
  397. package/dist/core/session-manager.js.map +0 -1
  398. package/dist/core/tools/truncate.d.ts +0 -70
  399. package/dist/core/tools/truncate.d.ts.map +0 -1
  400. package/dist/core/tools/truncate.js +0 -215
  401. package/dist/core/tools/truncate.js.map +0 -1
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Resource-profile & external-source menu controller.
3
+ *
4
+ * Extracted verbatim from interactive-mode.ts (god-file decomposition). Owns the /profiles command
5
+ * and the resource-hub menu tree: active-profile selection, profile create/delete/persist, the
6
+ * library (per-profile resource grants) editor, and external-source root management. It holds NO
7
+ * state of its own — every profile/source fact lives in settingsManager / the profile registry /
8
+ * the session resourceLoader — so it takes narrow deps (a live session accessor plus a UI callback
9
+ * surface, including the editor-overlay-backed showSelector) rather than the whole InteractiveMode
10
+ * instance.
11
+ */
12
+ import type { Model } from "@caupulican/pi-ai";
13
+ import type { Component, SelectItem, TUI } from "@caupulican/pi-tui";
14
+ import type { AgentSession } from "../../core/agent-session.ts";
15
+ export interface ProfileMenuControllerUi {
16
+ showSelector(create: (done: () => void) => {
17
+ component: Component;
18
+ focus: Component;
19
+ }): void;
20
+ showStatus(message: string): void;
21
+ showError(message: string): void;
22
+ showWarning(message: string): void;
23
+ requestRender(): void;
24
+ readonly tui: TUI;
25
+ readonly footerDataProvider: {
26
+ setExtensionStatus(key: string, text: string | undefined): void;
27
+ };
28
+ invalidateFooter(): void;
29
+ updateEditorBorderColor(): void;
30
+ openEditorForPath(filePath: string): Promise<boolean>;
31
+ handleReloadCommand(): Promise<void>;
32
+ reconcileExtensionsAndRefreshUI(profileName: string): Promise<void>;
33
+ maybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): void;
34
+ checkDaxnutsEasterEgg(model: {
35
+ provider: string;
36
+ id: string;
37
+ }): void;
38
+ showSettingsSelector(): void;
39
+ getAutoLearnModelOptions(): SelectItem[];
40
+ }
41
+ export interface ProfileMenuControllerDeps {
42
+ getSession(): AgentSession;
43
+ ui: ProfileMenuControllerUi;
44
+ }
45
+ export declare class ProfileMenuController {
46
+ private readonly deps;
47
+ constructor(deps: ProfileMenuControllerDeps);
48
+ private get session();
49
+ private get sessionManager();
50
+ private get settingsManager();
51
+ private get ui();
52
+ handleResourcesHubAction(action: string): Promise<void>;
53
+ private openActiveProfileSelector;
54
+ private openManageProfilesFlow;
55
+ private openPersistProfileSelector;
56
+ private openDeleteProfileSelector;
57
+ private openSourcesManagerFlow;
58
+ private openLibraryManagerFlow;
59
+ private createProfileAndOpenLibraryFlow;
60
+ private selectProfileAndOpenLibraryFlow;
61
+ private getProfileResourceKinds;
62
+ private openLibraryEditorForProfile;
63
+ private promptScopeChangeForProfile;
64
+ handleProfilesCommand(profileName?: string): Promise<void>;
65
+ private applyProfile;
66
+ /** Map where a profile currently lives to the scope we should write it back to. */
67
+ private scopeForProfileSource;
68
+ refreshAfterProfileMutation(profileName: string): Promise<void>;
69
+ private createProfileFlow;
70
+ private selectProfileModelForCreate;
71
+ private openNewProfileEditor;
72
+ private persistActiveProfile;
73
+ private deleteProfileFromSource;
74
+ private addExternalResourceRootFlow;
75
+ private removeExternalResourceRootFlow;
76
+ }
77
+ //# sourceMappingURL=profile-menu-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-menu-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/profile-menu-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAgBhE,MAAM,WAAW,uBAAuB;IACvC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,aAAa,IAAI,IAAI,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,kBAAkB,EAAE;QAAE,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAA;KAAE,CAAC;IACjG,gBAAgB,IAAI,IAAI,CAAC;IACzB,uBAAuB,IAAI,IAAI,CAAC;IAChC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,+BAA+B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,uCAAuC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAClE,qBAAqB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,oBAAoB,IAAI,IAAI,CAAC;IAC7B,wBAAwB,IAAI,UAAU,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,yBAAyB;IACzC,UAAU,IAAI,YAAY,CAAC;IAC3B,EAAE,EAAE,uBAAuB,CAAC;CAC5B;AAED,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IAEjD,YAAY,IAAI,EAAE,yBAAyB,EAE1C;IAED,OAAO,KAAK,OAAO,GAElB;IACD,OAAO,KAAK,cAAc,GAEzB;IACD,OAAO,KAAK,eAAe,GAE1B;IACD,OAAO,KAAK,EAAE,GAEb;IAEK,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB5D;YAEa,yBAAyB;YAmCzB,sBAAsB;YA4DtB,0BAA0B;YAgC1B,yBAAyB;YA4BzB,sBAAsB;YAiDtB,sBAAsB;YAkDtB,+BAA+B;YAuD/B,+BAA+B;YAsC/B,uBAAuB;YA8IvB,2BAA2B;YAqF3B,2BAA2B;IAkCnC,qBAAqB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B/D;YAEa,YAAY;IA6E1B,mFAAmF;IACnF,OAAO,CAAC,qBAAqB;IAcvB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpE;YAEa,iBAAiB;YAuDjB,2BAA2B;YA+B3B,oBAAoB;IAwDlC,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,uBAAuB;YAgBjB,2BAA2B;YA+E3B,8BAA8B;CAiB5C","sourcesContent":["/**\n * Resource-profile & external-source menu controller.\n *\n * Extracted verbatim from interactive-mode.ts (god-file decomposition). Owns the /profiles command\n * and the resource-hub menu tree: active-profile selection, profile create/delete/persist, the\n * library (per-profile resource grants) editor, and external-source root management. It holds NO\n * state of its own — every profile/source fact lives in settingsManager / the profile registry /\n * the session resourceLoader — so it takes narrow deps (a live session accessor plus a UI callback\n * surface, including the editor-overlay-backed showSelector) rather than the whole InteractiveMode\n * instance.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Model } from \"@caupulican/pi-ai\";\nimport type { Component, SelectItem, TUI } from \"@caupulican/pi-tui\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { resolveCliModel } from \"../../core/model-resolver.ts\";\nimport { resourceProfileSettingsChangedKinds } from \"../../core/resource-profile-equality.ts\";\nimport { validateSkillName } from \"../../core/skills.ts\";\nimport { allToolNames } from \"../../core/tools/index.ts\";\nimport { parseFrontmatter } from \"../../utils/frontmatter.ts\";\nimport { ExtensionInputComponent } from \"./components/extension-input.ts\";\nimport {\n\tProfileResourceEditorComponent,\n\ttype ProfileResourceEditorKind,\n\tresolveResourceEditPath,\n} from \"./components/profile-resource-editor.ts\";\nimport { ProfileSelectorComponent } from \"./components/profile-selector.ts\";\nimport { SelectSubmenu } from \"./components/settings-selector.ts\";\nimport { getAvailableThemesWithPaths } from \"./theme/theme.ts\";\n\nexport interface ProfileMenuControllerUi {\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\tshowWarning(message: string): void;\n\trequestRender(): void;\n\treadonly tui: TUI;\n\treadonly footerDataProvider: { setExtensionStatus(key: string, text: string | undefined): void };\n\tinvalidateFooter(): void;\n\tupdateEditorBorderColor(): void;\n\topenEditorForPath(filePath: string): Promise<boolean>;\n\thandleReloadCommand(): Promise<void>;\n\treconcileExtensionsAndRefreshUI(profileName: string): Promise<void>;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): void;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n\tshowSettingsSelector(): void;\n\tgetAutoLearnModelOptions(): SelectItem[];\n}\n\nexport interface ProfileMenuControllerDeps {\n\tgetSession(): AgentSession;\n\tui: ProfileMenuControllerUi;\n}\n\nexport class ProfileMenuController {\n\tprivate readonly deps: ProfileMenuControllerDeps;\n\n\tconstructor(deps: ProfileMenuControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tprivate get session(): AgentSession {\n\t\treturn this.deps.getSession();\n\t}\n\tprivate get sessionManager() {\n\t\treturn this.deps.getSession().sessionManager;\n\t}\n\tprivate get settingsManager() {\n\t\treturn this.deps.getSession().settingsManager;\n\t}\n\tprivate get ui(): ProfileMenuControllerUi {\n\t\treturn this.deps.ui;\n\t}\n\n\tasync handleResourcesHubAction(action: string): Promise<void> {\n\t\tswitch (action) {\n\t\t\tcase \"nudge-add-source\":\n\t\t\t\tvoid this.addExternalResourceRootFlow().then(() => {\n\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"active-profile\":\n\t\t\t\tvoid this.openActiveProfileSelector();\n\t\t\t\tbreak;\n\t\t\tcase \"manage-library\":\n\t\t\t\tvoid this.openLibraryManagerFlow();\n\t\t\t\tbreak;\n\t\t\tcase \"manage-profiles\":\n\t\t\t\tvoid this.openManageProfilesFlow();\n\t\t\t\tbreak;\n\t\t\tcase \"sources\":\n\t\t\t\tvoid this.openSourcesManagerFlow();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate async openActiveProfileSelector(): Promise<void> {\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profiles = registry.listProfiles();\n\t\tconst activeNames = this.settingsManager.getActiveResourceProfileNames();\n\n\t\tconst options = [\n\t\t\t{ value: \"(none)\", label: \"(none)\", description: \"No active profile/situation (all resources enabled)\" },\n\t\t\t...profiles.map((p) => ({\n\t\t\t\tvalue: p.name,\n\t\t\t\tlabel: p.name,\n\t\t\t\tdescription: p.description || p.source,\n\t\t\t})),\n\t\t];\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Profile / Situation\",\n\t\t\t\t\"Select the active runtime profile/situation for this session. This is session-only unless saved elsewhere.\",\n\t\t\t\toptions,\n\t\t\t\tactiveNames[0] || \"(none)\",\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.applyProfile(value === \"(none)\" ? \"\" : value).then(() => {\n\t\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async openManageProfilesFlow(): Promise<void> {\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profiles = registry.listProfiles();\n\t\tconst editableProfiles = profiles.map((p) => ({\n\t\t\tvalue: p.name,\n\t\t\tlabel: p.name,\n\t\t\tdescription: p.description || p.source,\n\t\t}));\n\n\t\tconst options = [\n\t\t\t{\n\t\t\t\tvalue: \"create\",\n\t\t\t\tlabel: \"+ Create profile / situation...\",\n\t\t\t\tdescription: \"Create a new resource profile/situation definition.\",\n\t\t\t},\n\t\t];\n\n\t\tif (this.settingsManager.getActiveResourceProfileNames().length > 0) {\n\t\t\toptions.push({\n\t\t\t\tvalue: \"persist\",\n\t\t\t\tlabel: \"Persist active profile / situation to...\",\n\t\t\t\tdescription: \"Save the current active profile/situation selection so it survives restart.\",\n\t\t\t});\n\t\t}\n\n\t\tif (editableProfiles.length > 0) {\n\t\t\toptions.push({\n\t\t\t\tvalue: \"delete\",\n\t\t\t\tlabel: \"Delete profile / situation...\",\n\t\t\t\tdescription: \"Remove a profile/situation definition from where it is stored.\",\n\t\t\t});\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Manage Profiles / Situations\",\n\t\t\t\t\"Create, delete, or persist profile/situation definitions.\",\n\t\t\t\toptions,\n\t\t\t\t\"\",\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tif (value === \"create\") {\n\t\t\t\t\t\tvoid this.createProfileFlow().then(() => {\n\t\t\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (value === \"persist\") {\n\t\t\t\t\t\tvoid this.openPersistProfileSelector();\n\t\t\t\t\t} else if (value === \"delete\") {\n\t\t\t\t\t\tvoid this.openDeleteProfileSelector();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async openPersistProfileSelector(): Promise<void> {\n\t\tconst scopeOptions = [\n\t\t\t{ value: \"session\", label: \"session\", description: \"Runtime only (not written to disk)\" },\n\t\t\t{\n\t\t\t\tvalue: \"directory\",\n\t\t\t\tlabel: \"directory\",\n\t\t\t\tdescription: \"~/.pi/agent/resource-profiles/<hash>/settings.json\",\n\t\t\t},\n\t\t\t{ value: \"project\", label: \"project\", description: \".pi/settings.json\" },\n\t\t\t{ value: \"global\", label: \"global\", description: \"~/.pi/agent/settings.json\" },\n\t\t];\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Persist Active Profile / Situation\",\n\t\t\t\t\"Choose where to write the active profile/situation selection.\",\n\t\t\t\tscopeOptions,\n\t\t\t\t\"directory\",\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.persistActiveProfile(value as \"session\" | \"directory\" | \"project\" | \"global\");\n\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.openManageProfilesFlow();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async openDeleteProfileSelector(): Promise<void> {\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst editableProfiles = registry.listProfiles().map((p) => ({\n\t\t\tvalue: p.name,\n\t\t\tlabel: p.name,\n\t\t\tdescription: p.description || p.source,\n\t\t}));\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Delete Profile / Situation\",\n\t\t\t\t\"Pick a profile/situation to delete.\",\n\t\t\t\teditableProfiles,\n\t\t\t\t\"\",\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.deleteProfileFromSource(value);\n\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.openManageProfilesFlow();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async openSourcesManagerFlow(): Promise<void> {\n\t\tconst externalRoots = this.settingsManager.getExternalResourceRoots();\n\t\tconst trustedRoots = this.settingsManager.getTrustedResourceRoots();\n\n\t\tconst options = [\n\t\t\t{\n\t\t\t\tvalue: \"add\",\n\t\t\t\tlabel: \"+ Add external root...\",\n\t\t\t\tdescription: \"Register a new external directory root (requires trust)\",\n\t\t\t},\n\t\t];\n\n\t\tfor (const r of externalRoots) {\n\t\t\tconst isTrusted = trustedRoots.includes(r);\n\t\t\toptions.push({\n\t\t\t\tvalue: `remove:${r}`,\n\t\t\t\tlabel: `Remove: ${r}`,\n\t\t\t\tdescription: isTrusted ? \"Trusted external root\" : \"Untrusted external root\",\n\t\t\t});\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Sources\",\n\t\t\t\t\"Manage external resource roots. Adding a root requires trust confirmation.\",\n\t\t\t\toptions,\n\t\t\t\t\"\",\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tif (value === \"add\") {\n\t\t\t\t\t\tvoid this.addExternalResourceRootFlow().then(() => {\n\t\t\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (value.startsWith(\"remove:\")) {\n\t\t\t\t\t\tconst root = value.slice(\"remove:\".length);\n\t\t\t\t\t\tvoid this.removeExternalResourceRootFlow(root).then(() => {\n\t\t\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async openLibraryManagerFlow(): Promise<void> {\n\t\tconst activeNames = this.settingsManager.getActiveResourceProfileNames();\n\t\tconst activeName = activeNames[0];\n\n\t\tif (!activeName || activeName === \"(none)\") {\n\t\t\tthis.ui.showSelector((done) => {\n\t\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\t\"No Active Profile / Situation\",\n\t\t\t\t\t\"Select or create a profile/situation to manage the library.\",\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"select\",\n\t\t\t\t\t\t\tlabel: \"Select existing profile / situation...\",\n\t\t\t\t\t\t\tdescription: \"Choose an existing profile/situation to activate.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"create\",\n\t\t\t\t\t\t\tlabel: \"Create new profile / situation...\",\n\t\t\t\t\t\t\tdescription: \"Create a new profile/situation definition.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t\"select\",\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tif (value === \"create\") {\n\t\t\t\t\t\t\tvoid this.createProfileAndOpenLibraryFlow();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvoid this.selectProfileAndOpenLibraryFlow();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tvoid this.ui.showSettingsSelector();\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profile = registry.getProfile(activeName);\n\t\tif (!profile) {\n\t\t\tthis.ui.showError(`Active profile/situation \"${activeName}\" not found in registry.`);\n\t\t\treturn;\n\t\t}\n\t\tconst scope = this.scopeForProfileSource(profile.source);\n\t\tvoid this.openLibraryEditorForProfile(profile.name, scope);\n\t}\n\n\tprivate async createProfileAndOpenLibraryFlow(): Promise<void> {\n\t\tconst name = await new Promise<string | undefined>((resolve) => {\n\t\t\tthis.ui.showSelector((done) => {\n\t\t\t\tconst input = new ExtensionInputComponent(\n\t\t\t\t\t\"Create Profile / Situation\",\n\t\t\t\t\t\"Enter profile/situation name\",\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(value);\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t},\n\t\t\t\t\t{ tui: this.ui.tui },\n\t\t\t\t);\n\t\t\t\treturn { component: input, focus: input };\n\t\t\t});\n\t\t});\n\n\t\tif (name === undefined) {\n\t\t\tvoid this.openLibraryManagerFlow();\n\t\t\treturn;\n\t\t}\n\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) {\n\t\t\tthis.ui.showWarning(\"Profile/situation name cannot be empty.\");\n\t\t\tvoid this.openLibraryManagerFlow();\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst profileModel = await this.selectProfileModelForCreate();\n\t\t\tif (profileModel === undefined) {\n\t\t\t\tvoid this.openLibraryManagerFlow();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.settingsManager.setProfileDefinition(\n\t\t\t\ttrimmed,\n\t\t\t\t{\n\t\t\t\t\tname: trimmed,\n\t\t\t\t\tmodel: profileModel ?? undefined,\n\t\t\t\t\tresources: {},\n\t\t\t\t},\n\t\t\t\t\"directory\",\n\t\t\t);\n\t\t\tawait this.applyProfile(trimmed);\n\t\t\tvoid this.openLibraryEditorForProfile(trimmed, \"directory\");\n\t\t} catch (error) {\n\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t\tvoid this.openLibraryManagerFlow();\n\t\t}\n\t}\n\n\tprivate async selectProfileAndOpenLibraryFlow(): Promise<void> {\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profiles = registry.listProfiles();\n\t\tconst editableProfiles = profiles.map((p) => ({\n\t\t\tvalue: p.name,\n\t\t\tlabel: p.name,\n\t\t\tdescription: p.description || p.source,\n\t\t}));\n\n\t\tif (editableProfiles.length === 0) {\n\t\t\tthis.ui.showWarning(\"No existing profiles/situations to select. Please create one.\");\n\t\t\tvoid this.createProfileAndOpenLibraryFlow();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Select Profile / Situation\",\n\t\t\t\t\"Pick a profile/situation to activate and edit.\",\n\t\t\t\teditableProfiles,\n\t\t\t\t\"\",\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.applyProfile(value).then(() => {\n\t\t\t\t\t\tconst profile = registry.getProfile(value)!;\n\t\t\t\t\t\tconst scope = this.scopeForProfileSource(profile.source);\n\t\t\t\t\t\tvoid this.openLibraryEditorForProfile(value, scope);\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.openLibraryManagerFlow();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async getProfileResourceKinds(): Promise<ProfileResourceEditorKind[]> {\n\t\tconst loader = this.session.resourceLoader;\n\t\tconst base = (p: string) => p.split(/[\\\\/]/).pop() ?? p;\n\t\tconst allDiscoverableExtensions = await loader.getDiscoverableExtensionPaths();\n\t\t// Defined BEFORE the skills/prompts arrays below that call it (const = TDZ: defining it\n\t\t// later crashes the whole app with a ReferenceError when the library editor opens).\n\t\tconst getFrontmatterDescription = (filePath: string): string | undefined => {\n\t\t\ttry {\n\t\t\t\tconst content = fs.readFileSync(filePath, \"utf-8\");\n\t\t\t\tconst { frontmatter } = parseFrontmatter<Record<string, unknown>>(content);\n\t\t\t\tif (typeof frontmatter.description === \"string\") return frontmatter.description;\n\t\t\t} catch {}\n\t\t\treturn undefined;\n\t\t};\n\t\t// The editor's universe must be profile-INDEPENDENT (discovery, not loading): the loaded\n\t\t// getters are narrowed by the active profile, so building the lists from them makes\n\t\t// currently-blocked skills/prompts/context files ungrantable — including expanding the\n\t\t// very profile you are running under. Union the loaded (rich metadata) sets with the\n\t\t// full pre-filter discovery paths.\n\t\tconst loadedSkills = loader.getSkills().skills;\n\t\tconst loadedSkillPaths = new Set(loadedSkills.map((skill) => skill.filePath));\n\t\tconst skillIdFromPath = (skillPath: string): string => {\n\t\t\tconst parts = skillPath.split(/[\\\\/]/);\n\t\t\tconst last = parts.pop() ?? skillPath;\n\t\t\tif (/^skill\\.md$/i.test(last)) return parts.pop() ?? last;\n\t\t\treturn last.replace(/\\.md$/i, \"\");\n\t\t};\n\t\tconst skills = [\n\t\t\t...loadedSkills.map((skill) => ({ id: skill.name, path: skill.filePath, description: skill.description })),\n\t\t\t...loader\n\t\t\t\t.getDiscoverableSkillPaths()\n\t\t\t\t.filter((skillPath) => !loadedSkillPaths.has(skillPath))\n\t\t\t\t.map((skillPath) => ({\n\t\t\t\t\tid: skillIdFromPath(skillPath),\n\t\t\t\t\tpath: skillPath,\n\t\t\t\t\tdescription: getFrontmatterDescription(skillPath),\n\t\t\t\t})),\n\t\t];\n\t\tconst loadedPrompts = loader.getPrompts().prompts;\n\t\tconst loadedPromptPaths = new Set(loadedPrompts.map((prompt) => prompt.filePath));\n\t\tconst prompts = [\n\t\t\t...loadedPrompts.map((prompt) => ({\n\t\t\t\tid: prompt.name,\n\t\t\t\tpath: prompt.filePath,\n\t\t\t\tdescription: prompt.description,\n\t\t\t})),\n\t\t\t...loader\n\t\t\t\t.getDiscoverablePromptPaths()\n\t\t\t\t.filter((promptPath) => !loadedPromptPaths.has(promptPath))\n\t\t\t\t.map((promptPath) => ({\n\t\t\t\t\tid: (promptPath.split(/[\\\\/]/).pop() ?? promptPath).replace(/\\.md$/i, \"\"),\n\t\t\t\t\tpath: promptPath,\n\t\t\t\t\tdescription: getFrontmatterDescription(promptPath),\n\t\t\t\t})),\n\t\t];\n\t\tconst themes = getAvailableThemesWithPaths();\n\t\tconst loadedAgentPaths = new Set(loader.getAgentsFiles().agentsFiles.map((file) => file.path));\n\t\tconst agents = [\n\t\t\t...loader.getAgentsFiles().agentsFiles.map((file) => ({ path: file.path })),\n\t\t\t...loader\n\t\t\t\t.getDiscoverableAgentsFilePaths()\n\t\t\t\t.filter((agentPath) => !loadedAgentPaths.has(agentPath))\n\t\t\t\t.map((agentPath) => ({ path: agentPath })),\n\t\t];\n\n\t\tconst getAgentDescription = (filePath: string): string | undefined => {\n\t\t\ttry {\n\t\t\t\tconst content = fs.readFileSync(filePath, \"utf-8\");\n\t\t\t\tconst { frontmatter } = parseFrontmatter<Record<string, unknown>>(content);\n\t\t\t\tif (typeof frontmatter.description === \"string\") {\n\t\t\t\t\treturn frontmatter.description;\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t\treturn undefined;\n\t\t};\n\n\t\tconst getExtensionDescription = (filePath: string): string | undefined => {\n\t\t\ttry {\n\t\t\t\tlet dir = filePath;\n\t\t\t\tif (fs.existsSync(filePath) && !fs.statSync(filePath).isDirectory()) {\n\t\t\t\t\tdir = path.dirname(filePath);\n\t\t\t\t}\n\t\t\t\tconst pkgPath = path.join(dir, \"package.json\");\n\t\t\t\tif (fs.existsSync(pkgPath)) {\n\t\t\t\t\tconst pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n\t\t\t\t\tif (typeof pkg.description === \"string\") {\n\t\t\t\t\t\treturn pkg.description;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t\treturn undefined;\n\t\t};\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: \"tools\",\n\t\t\t\tlabel: \"Tools\",\n\t\t\t\t// Built-ins plus every currently registered tool (extension tools included), so\n\t\t\t\t// an extension tool can be granted by name without hand-editing settings JSON.\n\t\t\t\titems: [...new Set([...allToolNames, ...this.session.getAllTools().map((tool) => tool.name)])].map(\n\t\t\t\t\t(name: string) => ({ id: name }),\n\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\tkind: \"skills\",\n\t\t\t\tlabel: \"Skills\",\n\t\t\t\titems: skills,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkind: \"extensions\",\n\t\t\t\tlabel: \"Extensions\",\n\t\t\t\titems: allDiscoverableExtensions.map((e) => ({\n\t\t\t\t\tid: base(e),\n\t\t\t\t\tpath: e,\n\t\t\t\t\tdescription: getExtensionDescription(e),\n\t\t\t\t})),\n\t\t\t},\n\t\t\t{\n\t\t\t\tkind: \"agents\",\n\t\t\t\tlabel: \"Agents\",\n\t\t\t\titems: agents.map((f) => ({\n\t\t\t\t\tid: base(f.path),\n\t\t\t\t\tpath: f.path,\n\t\t\t\t\tdescription: getAgentDescription(f.path),\n\t\t\t\t})),\n\t\t\t},\n\t\t\t{\n\t\t\t\tkind: \"prompts\",\n\t\t\t\tlabel: \"Prompts\",\n\t\t\t\titems: prompts,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkind: \"themes\",\n\t\t\t\tlabel: \"Themes\",\n\t\t\t\titems: themes.map((t) => ({\n\t\t\t\t\tid: t.name,\n\t\t\t\t\tpath: t.path,\n\t\t\t\t})),\n\t\t\t},\n\t\t];\n\t}\n\n\tprivate async openLibraryEditorForProfile(\n\t\tprofileName: string,\n\t\tinitialScope: \"session\" | \"directory\" | \"project\" | \"global\" | \"reusable-file\",\n\t): Promise<void> {\n\t\tconst currentScope = initialScope;\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profile = registry.getProfile(profileName);\n\t\tif (!profile) {\n\t\t\tthis.ui.showError(`Profile not found: ${profileName}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst kinds = await this.getProfileResourceKinds();\n\t\tconst originalResources = profile.resources;\n\t\tconst isActiveProfile = this.settingsManager.getActiveResourceProfileNames().includes(profile.name);\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst editor = new ProfileResourceEditorComponent({\n\t\t\t\tprofileName: profile!.name,\n\t\t\t\tprofileScope: currentScope,\n\t\t\t\tinitialResources: profile!.resources,\n\t\t\t\tkinds,\n\t\t\t\tcwd: this.sessionManager.getCwd(),\n\t\t\t\tagentDir: getAgentDir(),\n\t\t\t\texternalResourceRoots: this.settingsManager.getExternalResourceRoots(),\n\t\t\t\tonSave: (resources) => {\n\t\t\t\t\tdone();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.settingsManager.setProfileDefinition(\n\t\t\t\t\t\t\tprofileName,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: profileName,\n\t\t\t\t\t\t\t\tdescription: profile!.description,\n\t\t\t\t\t\t\t\tmodel: profile!.model,\n\t\t\t\t\t\t\t\tthinking: profile!.thinking,\n\t\t\t\t\t\t\t\tresources,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tcurrentScope,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.ui.showStatus(`Saved profile \"${profileName}\" to ${currentScope}.`);\n\t\t\t\t\t\tif (isActiveProfile) {\n\t\t\t\t\t\t\tconst changedKinds = resourceProfileSettingsChangedKinds(originalResources, resources);\n\t\t\t\t\t\t\tif (changedKinds.size === 1 && changedKinds.has(\"extensions\")) {\n\t\t\t\t\t\t\t\tvoid this.ui.reconcileExtensionsAndRefreshUI(profileName);\n\t\t\t\t\t\t\t} else if (changedKinds.size > 0) {\n\t\t\t\t\t\t\t\tvoid this.refreshAfterProfileMutation(profileName);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonCancel: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.openLibraryManagerFlow();\n\t\t\t\t},\n\t\t\t\tonScopeChange: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.promptScopeChangeForProfile(profileName, currentScope);\n\t\t\t\t},\n\t\t\t\tonEdit: async (id, pathValue, kind) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tconst resolvedEditPath = resolveResourceEditPath(id, pathValue, kind);\n\t\t\t\t\tif (!resolvedEditPath) {\n\t\t\t\t\t\tthis.ui.showWarning(`Resource \"${id}\" of kind \"${kind}\" has no editable file path.`);\n\t\t\t\t\t\tvoid this.openLibraryEditorForProfile(profileName, currentScope);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!fs.existsSync(resolvedEditPath)) {\n\t\t\t\t\t\tthis.ui.showError(`Resolved path for \"${id}\" does not exist: ${resolvedEditPath}`);\n\t\t\t\t\t\tvoid this.openLibraryEditorForProfile(profileName, currentScope);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.ui.openEditorForPath(resolvedEditPath);\n\t\t\t\t\tawait this.ui.handleReloadCommand();\n\t\t\t\t\tvoid this.openLibraryEditorForProfile(profileName, currentScope);\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn { component: editor, focus: editor };\n\t\t});\n\t}\n\n\tprivate async promptScopeChangeForProfile(\n\t\tprofileName: string,\n\t\tcurrentScope: \"session\" | \"directory\" | \"project\" | \"global\" | \"reusable-file\",\n\t): Promise<void> {\n\t\tconst scopeOptions = [\n\t\t\t{ value: \"session\", label: \"session\", description: \"Runtime only (not written to disk)\" },\n\t\t\t{\n\t\t\t\tvalue: \"directory\",\n\t\t\t\tlabel: \"directory\",\n\t\t\t\tdescription: \"~/.pi/agent/resource-profiles/<hash>/settings.json\",\n\t\t\t},\n\t\t\t{ value: \"project\", label: \"project\", description: \".pi/settings.json\" },\n\t\t\t{ value: \"global\", label: \"global\", description: \"~/.pi/agent/settings.json\" },\n\t\t];\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\"Change Profile / Situation Scope\",\n\t\t\t\t`Select new scope for profile/situation \"${profileName}\".`,\n\t\t\t\tscopeOptions,\n\t\t\t\tcurrentScope,\n\t\t\t\t(value) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.openLibraryEditorForProfile(profileName, value as any);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.openLibraryEditorForProfile(profileName, currentScope);\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tasync handleProfilesCommand(profileName?: string): Promise<void> {\n\t\tif (profileName) {\n\t\t\tawait this.applyProfile(profileName);\n\t\t\treturn;\n\t\t}\n\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profiles = registry.listProfiles();\n\t\tif (profiles.length === 0) {\n\t\t\tthis.ui.showWarning(\n\t\t\t\t\"No profiles found. Add resourceProfiles to settings or JSON files under ~/.pi/agent/profiles/.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new ProfileSelectorComponent(\n\t\t\t\tprofiles,\n\t\t\t\tthis.settingsManager.getActiveResourceProfileNames(),\n\t\t\t\t(profile) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid this.applyProfile(profile);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t});\n\t}\n\n\tprivate async applyProfile(profileName: string): Promise<void> {\n\t\tconst normalizedName = profileName.trim();\n\t\tconst normalizedLower = normalizedName.toLowerCase();\n\t\tif (normalizedName.length === 0 || normalizedLower === \"none\" || normalizedLower === \"(none)\") {\n\t\t\ttry {\n\t\t\t\tthis.settingsManager.setRuntimeResourceProfiles([]);\n\t\t\t\t// Clearing must also survive restarts (otherwise the old global selection returns).\n\t\t\t\tthis.settingsManager.setActiveProfile(undefined, \"global\");\n\t\t\t\tthis.session.sessionManager.appendCustomEntry(\"pi.activeResourceProfiles\", {\n\t\t\t\t\tprofiles: [],\n\t\t\t\t});\n\t\t\t\tawait this.ui.handleReloadCommand();\n\t\t\t\tconst activeProfileName = this.settingsManager.getActiveResourceProfileNames()[0] ?? \"(none)\";\n\t\t\t\tthis.ui.footerDataProvider.setExtensionStatus(\"profile\", activeProfileName);\n\t\t\t\tthis.ui.invalidateFooter();\n\t\t\t\tthis.ui.updateEditorBorderColor();\n\t\t\t\tthis.ui.showStatus(`Profile: ${activeProfileName}`);\n\t\t\t} catch (error) {\n\t\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst registry = this.settingsManager.getProfileRegistry();\n\t\tconst profile =\n\t\t\tnormalizedName.startsWith(\"./\") || normalizedName.startsWith(\"../\")\n\t\t\t\t? registry.resolveProfileRef(normalizedName, this.sessionManager.getCwd())\n\t\t\t\t: registry.getProfile(normalizedName);\n\t\tif (!profile) {\n\t\t\tthis.ui.showError(`Profile not found: ${profileName}`);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tlet appliedModel: Model<any> | undefined;\n\t\t\tif (profile.model) {\n\t\t\t\tthis.session.modelRegistry.refresh();\n\t\t\t\tconst resolved = resolveCliModel({ cliModel: profile.model, modelRegistry: this.session.modelRegistry });\n\t\t\t\tif (resolved.error) {\n\t\t\t\t\tthis.ui.showError(resolved.error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (resolved.warning) {\n\t\t\t\t\tthis.ui.showWarning(resolved.warning);\n\t\t\t\t}\n\t\t\t\tif (resolved.model) {\n\t\t\t\t\tawait this.session.setModel(resolved.model, { persistSettings: false });\n\t\t\t\t\tappliedModel = resolved.model;\n\t\t\t\t}\n\t\t\t\tif (resolved.thinkingLevel && !profile.thinking) {\n\t\t\t\t\tthis.session.setThinkingLevel(resolved.thinkingLevel, { persistSettings: false });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (profile.thinking) {\n\t\t\t\tthis.session.setThinkingLevel(profile.thinking, { persistSettings: false });\n\t\t\t}\n\t\t\tthis.settingsManager.setRuntimeResourceProfiles([profile.name]);\n\t\t\t// Selection must survive pi restarts: persist globally (like model/theme selections).\n\t\t\t// Runtime + session-entry alone made every /profile choice evaporate on exit.\n\t\t\tthis.settingsManager.setActiveProfile(profile.name, \"global\");\n\t\t\tthis.session.sessionManager.appendCustomEntry(\"pi.activeResourceProfiles\", {\n\t\t\t\tprofiles: [profile.name],\n\t\t\t});\n\t\t\tawait this.ui.handleReloadCommand();\n\t\t\tthis.ui.footerDataProvider.setExtensionStatus(\"profile\", profile.name);\n\t\t\tthis.ui.invalidateFooter();\n\t\t\tthis.ui.updateEditorBorderColor();\n\t\t\tthis.ui.showStatus(`Profile: ${profile.name}`);\n\t\t\tif (appliedModel) {\n\t\t\t\tvoid this.ui.maybeWarnAboutAnthropicSubscriptionAuth(appliedModel);\n\t\t\t\tthis.ui.checkDaxnutsEasterEgg(appliedModel);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/** Map where a profile currently lives to the scope we should write it back to. */\n\tprivate scopeForProfileSource(source: string): \"session\" | \"directory\" | \"project\" | \"global\" | \"reusable-file\" {\n\t\tswitch (source) {\n\t\t\tcase \"profile-file\":\n\t\t\t\treturn \"reusable-file\";\n\t\t\tcase \"directory-overlay\":\n\t\t\tcase \"embedded\":\n\t\t\t\treturn \"directory\";\n\t\t\tcase \"inline\":\n\t\t\t\treturn \"session\";\n\t\t\tdefault:\n\t\t\t\treturn \"global\"; // \"settings\"\n\t\t}\n\t}\n\n\tasync refreshAfterProfileMutation(profileName: string): Promise<void> {\n\t\tif (this.settingsManager.getActiveResourceProfileNames().includes(profileName)) {\n\t\t\tawait this.ui.handleReloadCommand();\n\t\t\tconst active = this.settingsManager.getActiveResourceProfileNames()[0] ?? \"(none)\";\n\t\t\tthis.ui.footerDataProvider.setExtensionStatus(\"profile\", active);\n\t\t\tthis.ui.invalidateFooter();\n\t\t\tthis.ui.updateEditorBorderColor();\n\t\t}\n\t}\n\n\tprivate async createProfileFlow(): Promise<void> {\n\t\tconst name = await new Promise<string | undefined>((resolve) => {\n\t\t\tthis.ui.showSelector((done) => {\n\t\t\t\tconst input = new ExtensionInputComponent(\n\t\t\t\t\t\"Create Profile / Situation\",\n\t\t\t\t\t\"Enter profile/situation name\",\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(value);\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t},\n\t\t\t\t\t{ tui: this.ui.tui },\n\t\t\t\t);\n\t\t\t\treturn { component: input, focus: input };\n\t\t\t});\n\t\t});\n\n\t\tif (name === undefined) {\n\t\t\tthis.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) {\n\t\t\tthis.ui.showError(\"Profile/situation name cannot be empty\");\n\t\t\treturn this.createProfileFlow();\n\t\t}\n\n\t\t// Validate name rules using validateSkillName\n\t\tconst errors = validateSkillName(trimmed);\n\t\tif (errors.length > 0) {\n\t\t\tthis.ui.showError(`Invalid profile/situation name: ${errors.join(\", \")}`);\n\t\t\treturn this.createProfileFlow();\n\t\t}\n\n\t\t// Collision check\n\t\tconst existing = this.settingsManager.getProfileRegistry().getProfile(trimmed);\n\t\tif (existing) {\n\t\t\tthis.ui.showError(`Profile/situation \"${trimmed}\" already exists`);\n\t\t\treturn this.createProfileFlow();\n\t\t}\n\n\t\tconst profileModel = await this.selectProfileModelForCreate();\n\t\tif (profileModel === undefined) {\n\t\t\tthis.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\t// Open the resource editor on the NEW profile\n\t\tvoid this.openNewProfileEditor(trimmed, profileModel ?? undefined);\n\t}\n\n\tprivate async selectProfileModelForCreate(): Promise<string | null | undefined> {\n\t\tconst modelOptions = [\n\t\t\t{\n\t\t\t\tvalue: \"(none)\",\n\t\t\t\tlabel: \"(none)\",\n\t\t\t\tdescription: \"Do not pin a foreground profile model; use the session/default model\",\n\t\t\t},\n\t\t\t...this.ui.getAutoLearnModelOptions(),\n\t\t];\n\n\t\treturn await new Promise<string | null | undefined>((resolve) => {\n\t\t\tthis.ui.showSelector((done) => {\n\t\t\t\tconst selector = new SelectSubmenu(\n\t\t\t\t\t\"Profile Model\",\n\t\t\t\t\t\"Pick the foreground model for this profile from authenticated/configured providers.\",\n\t\t\t\t\tmodelOptions,\n\t\t\t\t\t\"(none)\",\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(value === \"(none)\" ? null : value);\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn { component: selector, focus: selector.getSelectList() };\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async openNewProfileEditor(profileName: string, profileModel?: string): Promise<void> {\n\t\tconst scope = \"reusable-file\";\n\t\tconst kinds = await this.getProfileResourceKinds();\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst editor = new ProfileResourceEditorComponent({\n\t\t\t\tprofileName,\n\t\t\t\tprofileScope: scope,\n\t\t\t\tinitialResources: {},\n\t\t\t\tkinds,\n\t\t\t\tcwd: this.sessionManager.getCwd(),\n\t\t\t\tagentDir: getAgentDir(),\n\t\t\t\texternalResourceRoots: this.settingsManager.getExternalResourceRoots(),\n\t\t\t\tonSave: (resources) => {\n\t\t\t\t\tdone();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.settingsManager.setProfileDefinition(\n\t\t\t\t\t\t\tprofileName,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: profileName,\n\t\t\t\t\t\t\t\tmodel: profileModel,\n\t\t\t\t\t\t\t\tresources,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tscope,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.ui.showStatus(`Saved profile \"${profileName}\" to ${scope}.`);\n\t\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonCancel: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t},\n\t\t\t\tonEdit: async (id, pathValue, kind) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tconst resolvedEditPath = resolveResourceEditPath(id, pathValue, kind);\n\t\t\t\t\tif (!resolvedEditPath) {\n\t\t\t\t\t\tthis.ui.showWarning(`Resource \"${id}\" of kind \"${kind}\" has no editable file path.`);\n\t\t\t\t\t\tvoid this.openNewProfileEditor(profileName, profileModel);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!fs.existsSync(resolvedEditPath)) {\n\t\t\t\t\t\tthis.ui.showError(`Resolved path for \"${id}\" does not exist: ${resolvedEditPath}`);\n\t\t\t\t\t\tvoid this.openNewProfileEditor(profileName, profileModel);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.ui.openEditorForPath(resolvedEditPath);\n\t\t\t\t\tawait this.ui.handleReloadCommand();\n\t\t\t\t\tvoid this.openNewProfileEditor(profileName, profileModel);\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { component: editor, focus: editor };\n\t\t});\n\t}\n\n\tprivate persistActiveProfile(scope: \"session\" | \"directory\" | \"project\" | \"global\"): void {\n\t\tconst active = this.settingsManager.getActiveResourceProfileNames()[0];\n\t\tif (!active) {\n\t\t\tthis.ui.showError(\"No active profile to persist. Select one with /profiles first.\");\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tif (scope === \"session\") {\n\t\t\t\tthis.settingsManager.setRuntimeResourceProfiles([active]);\n\t\t\t} else {\n\t\t\t\tthis.settingsManager.setActiveProfile(active, scope);\n\t\t\t}\n\t\t\tthis.ui.showStatus(`Active profile \"${active}\" persisted to ${scope}.`);\n\t\t} catch (error) {\n\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\tprivate deleteProfileFromSource(profileName: string): void {\n\t\tconst profile = this.settingsManager.getProfileRegistry().getProfile(profileName);\n\t\tif (!profile) {\n\t\t\tthis.ui.showError(`Profile not found: ${profileName}`);\n\t\t\treturn;\n\t\t}\n\t\tconst scope = this.scopeForProfileSource(profile.source);\n\t\ttry {\n\t\t\tthis.settingsManager.deleteProfile(profileName, scope);\n\t\t\tthis.ui.showStatus(`Deleted profile \"${profileName}\" from ${scope}.`);\n\t\t\tvoid this.refreshAfterProfileMutation(profileName);\n\t\t} catch (error) {\n\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\tprivate async addExternalResourceRootFlow(): Promise<void> {\n\t\tconst rootPath = await new Promise<string | undefined>((resolve) => {\n\t\t\tthis.ui.showSelector((done) => {\n\t\t\t\tconst input = new ExtensionInputComponent(\n\t\t\t\t\t\"Add External Root\",\n\t\t\t\t\t\"Enter external root directory path\",\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(value);\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(undefined);\n\t\t\t\t\t},\n\t\t\t\t\t{ tui: this.ui.tui },\n\t\t\t\t);\n\t\t\t\treturn { component: input, focus: input };\n\t\t\t});\n\t\t});\n\n\t\tif (rootPath === undefined) {\n\t\t\tthis.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst trimmed = rootPath.trim();\n\t\tif (!trimmed) {\n\t\t\tthis.ui.showError(\"Directory path cannot be empty\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst canonical = this.settingsManager.canonicalizePath(trimmed);\n\t\tif (!canonical) {\n\t\t\tthis.ui.showError(`Invalid path: ${trimmed}`);\n\t\t\treturn;\n\t\t}\n\n\t\t// Prompt for trust confirmation (Yes/No)\n\t\tconst trust = await new Promise<boolean>((resolve) => {\n\t\t\tthis.ui.showSelector((done) => {\n\t\t\t\tconst submenu = new SelectSubmenu(\n\t\t\t\t\t\"Trust external source?\",\n\t\t\t\t\t\"This directory can load custom extensions that execute arbitrary code on your machine.\",\n\t\t\t\t\t[\n\t\t\t\t\t\t{ value: \"yes\", label: \"Yes\", description: \"Trust this directory and enable loading resources.\" },\n\t\t\t\t\t\t{ value: \"no\", label: \"No\", description: \"Do not trust this directory. Skip loading resources.\" },\n\t\t\t\t\t],\n\t\t\t\t\t\"no\",\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(value === \"yes\");\n\t\t\t\t\t},\n\t\t\t\t\t() => {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\tresolve(false);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn { component: submenu, focus: submenu.getSelectList() };\n\t\t\t});\n\t\t});\n\n\t\tif (!trust) {\n\t\t\tthis.ui.showStatus(\"Aborted. External root was not trusted.\");\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst currentRoots = this.settingsManager.getExternalResourceRoots();\n\t\t\tif (!currentRoots.includes(canonical)) {\n\t\t\t\tthis.settingsManager.setExternalResourceRoots([...currentRoots, canonical], \"global\");\n\t\t\t}\n\t\t\tthis.settingsManager.addTrustedResourceRoot(canonical, \"global\");\n\t\t\tthis.ui.showStatus(`Added trusted external root: ${canonical}`);\n\t\t\tawait this.ui.handleReloadCommand();\n\t\t} catch (error) {\n\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\tprivate async removeExternalResourceRootFlow(root: string): Promise<void> {\n\t\ttry {\n\t\t\tconst currentRoots = this.settingsManager.getExternalResourceRoots();\n\t\t\tconst currentTrusted = this.settingsManager.getTrustedResourceRoots();\n\n\t\t\tconst newRoots = currentRoots.filter((r) => r !== root);\n\t\t\tconst newTrusted = currentTrusted.filter((r) => r !== root);\n\n\t\t\tthis.settingsManager.setExternalResourceRoots(newRoots, \"global\");\n\t\t\tthis.settingsManager.setTrustedResourceRoots(newTrusted, \"global\");\n\n\t\t\tthis.ui.showStatus(`Removed external root: ${root}`);\n\t\t\tawait this.ui.handleReloadCommand();\n\t\t} catch (error) {\n\t\t\tthis.ui.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n}\n"]}