@pellux/goodvibes-tui 0.18.8 → 0.18.10

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 (555) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +1 -1
  3. package/docs/foundation-artifacts/operator-contract.json +1 -1
  4. package/package.json +2 -2
  5. package/src/acp/connection.ts +5 -5
  6. package/src/acp/index.ts +1 -1
  7. package/src/acp/manager.ts +1 -133
  8. package/src/adapters/bluebubbles/index.ts +1 -1
  9. package/src/adapters/discord/index.ts +2 -2
  10. package/src/adapters/github/index.ts +1 -1
  11. package/src/adapters/google-chat/index.ts +1 -1
  12. package/src/adapters/imessage/index.ts +1 -1
  13. package/src/adapters/index.ts +15 -15
  14. package/src/adapters/matrix/index.ts +1 -1
  15. package/src/adapters/mattermost/index.ts +1 -1
  16. package/src/adapters/msteams/index.ts +2 -2
  17. package/src/adapters/ntfy/index.ts +1 -1
  18. package/src/adapters/signal/index.ts +1 -1
  19. package/src/adapters/slack/index.ts +2 -2
  20. package/src/adapters/telegram/index.ts +1 -1
  21. package/src/adapters/types.ts +4 -4
  22. package/src/adapters/webhook/index.ts +1 -1
  23. package/src/adapters/whatsapp/index.ts +1 -1
  24. package/src/agents/message-bus-core.ts +2 -2
  25. package/src/agents/message-bus.ts +2 -2
  26. package/src/agents/orchestrator-prompts.ts +4 -4
  27. package/src/agents/orchestrator-runner.ts +11 -11
  28. package/src/agents/orchestrator.ts +14 -13
  29. package/src/agents/session.ts +1 -1
  30. package/src/agents/worktree.ts +1 -1
  31. package/src/agents/wrfc-config.ts +2 -2
  32. package/src/agents/wrfc-controller.ts +12 -12
  33. package/src/agents/wrfc-gate-runtime.ts +5 -5
  34. package/src/agents/wrfc-reporting.ts +1 -1
  35. package/src/agents/wrfc-runtime-events.ts +3 -3
  36. package/src/agents/wrfc-types.ts +1 -1
  37. package/src/automation/delivery-manager.ts +4 -4
  38. package/src/automation/index.ts +4 -4
  39. package/src/automation/manager-runtime-delivery.ts +1 -1
  40. package/src/automation/manager-runtime-events.ts +3 -3
  41. package/src/automation/manager-runtime-execution.ts +5 -5
  42. package/src/automation/manager-runtime-helpers.ts +2 -2
  43. package/src/automation/manager-runtime-job-mutations.ts +3 -3
  44. package/src/automation/manager-runtime-reconcile.ts +4 -4
  45. package/src/automation/manager-runtime-scheduling.ts +2 -2
  46. package/src/automation/manager-runtime.ts +18 -18
  47. package/src/automation/manager.ts +2 -2
  48. package/src/automation/service.ts +2 -2
  49. package/src/channels/builtin/account-actions.ts +5 -5
  50. package/src/channels/builtin/accounts.ts +2 -2
  51. package/src/channels/builtin/contracts.ts +3 -3
  52. package/src/channels/builtin/plugins.ts +5 -5
  53. package/src/channels/builtin/rendering.ts +4 -4
  54. package/src/channels/builtin/setup-schema.ts +1 -1
  55. package/src/channels/builtin/shared.ts +7 -7
  56. package/src/channels/builtin/surfaces.ts +2 -2
  57. package/src/channels/builtin/targets.ts +3 -3
  58. package/src/channels/builtin-runtime.ts +11 -11
  59. package/src/channels/delivery/shared.ts +2 -2
  60. package/src/channels/delivery/strategies-bridge.ts +3 -3
  61. package/src/channels/delivery/strategies-core.ts +5 -5
  62. package/src/channels/delivery/strategies-enterprise.ts +3 -3
  63. package/src/channels/delivery/types.ts +2 -2
  64. package/src/channels/delivery-router.ts +9 -9
  65. package/src/channels/index.ts +12 -12
  66. package/src/channels/plugin-registry.ts +1 -1
  67. package/src/channels/provider-runtime.ts +3 -3
  68. package/src/channels/reply-pipeline.ts +3 -3
  69. package/src/channels/route-manager.ts +2 -2
  70. package/src/channels/surface-registry.ts +2 -2
  71. package/src/config/helper-model.ts +1 -233
  72. package/src/config/index.ts +3 -3
  73. package/src/config/manager.ts +8 -404
  74. package/src/config/secrets.ts +21 -542
  75. package/src/config/service-registry.ts +1 -329
  76. package/src/config/tool-llm.ts +3 -3
  77. package/src/control-plane/approval-broker.ts +1 -1
  78. package/src/control-plane/gateway.ts +1 -713
  79. package/src/control-plane/index.ts +7 -7
  80. package/src/control-plane/media-contract-schemas.ts +1 -208
  81. package/src/control-plane/method-catalog-admin.ts +1 -136
  82. package/src/control-plane/method-catalog-channels.ts +1 -591
  83. package/src/control-plane/method-catalog-control-automation.ts +1 -475
  84. package/src/control-plane/method-catalog-control-core.ts +1 -594
  85. package/src/control-plane/method-catalog-control.ts +1 -8
  86. package/src/control-plane/method-catalog-events.ts +1 -74
  87. package/src/control-plane/method-catalog-knowledge.ts +1 -531
  88. package/src/control-plane/method-catalog-media.ts +1 -279
  89. package/src/control-plane/method-catalog-runtime.ts +1 -304
  90. package/src/control-plane/method-catalog-shared.ts +1 -223
  91. package/src/control-plane/method-catalog.ts +1 -242
  92. package/src/control-plane/operator-contract-schemas-admin.ts +1 -639
  93. package/src/control-plane/operator-contract-schemas-channels.ts +1 -375
  94. package/src/control-plane/operator-contract-schemas-control.ts +1 -226
  95. package/src/control-plane/operator-contract-schemas-domains.ts +1 -4
  96. package/src/control-plane/operator-contract-schemas-knowledge.ts +1 -582
  97. package/src/control-plane/operator-contract-schemas-media.ts +1 -297
  98. package/src/control-plane/operator-contract-schemas-permissions.ts +1 -100
  99. package/src/control-plane/operator-contract-schemas-remote.ts +1 -38
  100. package/src/control-plane/operator-contract-schemas-runtime.ts +1 -563
  101. package/src/control-plane/operator-contract-schemas-shared.ts +1 -85
  102. package/src/control-plane/operator-contract-schemas-telemetry.ts +1 -349
  103. package/src/control-plane/operator-contract-schemas.ts +1 -6
  104. package/src/control-plane/operator-contract.ts +5 -3
  105. package/src/control-plane/session-broker.ts +1 -1
  106. package/src/core/compaction-sections.ts +5 -5
  107. package/src/core/compaction-types.ts +3 -3
  108. package/src/core/composer-state.ts +1 -1
  109. package/src/core/context-compaction.ts +7 -7
  110. package/src/core/conversation-compaction.ts +4 -4
  111. package/src/core/conversation-diff.ts +1 -1
  112. package/src/core/conversation-rendering.ts +5 -5
  113. package/src/core/conversation-utils.ts +2 -2
  114. package/src/core/conversation.ts +10 -10
  115. package/src/core/event-replay.ts +1 -1
  116. package/src/core/orchestrator-context-runtime.ts +8 -8
  117. package/src/core/orchestrator-follow-up-runtime.ts +2 -2
  118. package/src/core/orchestrator-runtime.ts +4 -4
  119. package/src/core/orchestrator-tool-runtime.ts +7 -7
  120. package/src/core/orchestrator-turn-helpers.ts +7 -7
  121. package/src/core/orchestrator-turn-loop.ts +10 -10
  122. package/src/core/orchestrator.ts +17 -17
  123. package/src/core/plan-command-handler.ts +2 -2
  124. package/src/core/system-message-router.ts +2 -2
  125. package/src/core/transcript-events/classify.ts +1 -1
  126. package/src/core/transcript-events/index.ts +3 -3
  127. package/src/daemon/cli.ts +6 -6
  128. package/src/daemon/control-plane.ts +7 -7
  129. package/src/daemon/facade-composition.ts +16 -15
  130. package/src/daemon/facade.ts +17 -17
  131. package/src/daemon/helpers.ts +2 -2
  132. package/src/daemon/http/router-route-contexts.ts +11 -11
  133. package/src/daemon/http/router.ts +25 -25
  134. package/src/daemon/http-listener.ts +3 -3
  135. package/src/daemon/index.ts +1 -3
  136. package/src/daemon/service-manager.ts +1 -1
  137. package/src/daemon/surface-actions.ts +8 -8
  138. package/src/daemon/surface-delivery.ts +7 -7
  139. package/src/daemon/surface-policy.ts +1 -1
  140. package/src/daemon/transport-events.ts +4 -4
  141. package/src/daemon/types.ts +24 -24
  142. package/src/export/markdown.ts +1 -1
  143. package/src/export/session-export.ts +1 -633
  144. package/src/git/index.ts +1 -1
  145. package/src/git/service.ts +1 -1
  146. package/src/hooks/chain-engine.ts +1 -1
  147. package/src/hooks/dispatcher.ts +4 -4
  148. package/src/hooks/hook-api.ts +1 -1
  149. package/src/hooks/index.ts +8 -8
  150. package/src/hooks/runners/agent.ts +1 -1
  151. package/src/hooks/runners/prompt.ts +1 -1
  152. package/src/hooks/workbench.ts +2 -2
  153. package/src/input/command-registry.ts +24 -17
  154. package/src/input/commands/config.ts +1 -1
  155. package/src/input/commands/control-room-runtime.ts +2 -2
  156. package/src/input/commands/conversation-runtime.ts +1 -1
  157. package/src/input/commands/eval.ts +2 -2
  158. package/src/input/commands/git-runtime.ts +1 -1
  159. package/src/input/commands/guidance-runtime.ts +3 -3
  160. package/src/input/commands/health-runtime.ts +7 -7
  161. package/src/input/commands/incident-runtime.ts +1 -1
  162. package/src/input/commands/integration-runtime.ts +3 -3
  163. package/src/input/commands/local-provider-runtime.ts +1 -1
  164. package/src/input/commands/local-runtime.ts +1 -1
  165. package/src/input/commands/local-setup-review.ts +1 -1
  166. package/src/input/commands/local-setup.ts +1 -1
  167. package/src/input/commands/managed-runtime.ts +2 -2
  168. package/src/input/commands/marketplace-runtime.ts +1 -1
  169. package/src/input/commands/platform-access-runtime.ts +1 -1
  170. package/src/input/commands/policy-dispatch.ts +2 -2
  171. package/src/input/commands/product-runtime.ts +2 -2
  172. package/src/input/commands/profile-sync-runtime.ts +1 -1
  173. package/src/input/commands/provider-accounts-runtime.ts +1 -1
  174. package/src/input/commands/provider.ts +3 -3
  175. package/src/input/commands/quit-shared.ts +1 -1
  176. package/src/input/commands/recall-bundle.ts +1 -1
  177. package/src/input/commands/recall-capture.ts +2 -2
  178. package/src/input/commands/recall-query.ts +2 -2
  179. package/src/input/commands/recall-shared.ts +1 -1
  180. package/src/input/commands/remote-runtime-setup.ts +1 -1
  181. package/src/input/commands/remote-runtime.ts +1 -1
  182. package/src/input/commands/runtime-services.ts +13 -11
  183. package/src/input/commands/schedule-runtime.ts +2 -2
  184. package/src/input/commands/session-content.ts +1 -1
  185. package/src/input/commands/session-workflow.ts +4 -4
  186. package/src/input/commands/settings-sync-runtime.ts +1 -1
  187. package/src/input/commands/share-runtime.ts +9 -4
  188. package/src/input/commands/shell-core.ts +1 -1
  189. package/src/input/commands/skills-runtime.ts +1 -1
  190. package/src/input/commands/subscription-runtime.ts +1 -1
  191. package/src/input/commands/tasks-runtime.ts +1 -1
  192. package/src/input/commands/teamwork-runtime.ts +1 -1
  193. package/src/input/commands/worktree-runtime.ts +1 -1
  194. package/src/input/handler-command-route.ts +1 -1
  195. package/src/input/handler-content-actions.ts +3 -3
  196. package/src/input/handler-feed-routes.ts +2 -2
  197. package/src/input/handler-feed.ts +1 -1
  198. package/src/input/handler-shortcuts.ts +1 -1
  199. package/src/input/handler.ts +1 -1
  200. package/src/input/keybindings.ts +5 -0
  201. package/src/input/model-picker.ts +2 -2
  202. package/src/input/profile-picker-modal.ts +1 -1
  203. package/src/input/session-picker-modal.ts +1 -1
  204. package/src/input/settings-modal.ts +4 -4
  205. package/src/integrations/index.ts +1 -1
  206. package/src/integrations/notifier.ts +1 -1
  207. package/src/integrations/webhooks.ts +1 -177
  208. package/src/knowledge/consolidation.ts +2 -2
  209. package/src/knowledge/graphql.ts +1 -1
  210. package/src/knowledge/index.ts +5 -5
  211. package/src/knowledge/ingest-compile.ts +3 -3
  212. package/src/knowledge/ingest-context.ts +1 -1
  213. package/src/knowledge/ingest-inputs.ts +4 -4
  214. package/src/knowledge/ingest.ts +1 -20
  215. package/src/knowledge/internal.ts +1 -1
  216. package/src/knowledge/knowledge-api.ts +7 -7
  217. package/src/knowledge/lint.ts +3 -3
  218. package/src/knowledge/memory-sync.ts +2 -2
  219. package/src/knowledge/packet.ts +3 -3
  220. package/src/knowledge/scheduling.ts +2 -2
  221. package/src/knowledge/service.ts +10 -10
  222. package/src/main.ts +11 -10
  223. package/src/mcp/index.ts +4 -4
  224. package/src/mcp/mcp-api.ts +1 -1
  225. package/src/mcp/registry.ts +1 -506
  226. package/src/media/builtin-image-understanding.ts +2 -2
  227. package/src/media/builtin-providers.ts +2 -2
  228. package/src/media/index.ts +1 -1
  229. package/src/multimodal/index.ts +1 -1
  230. package/src/multimodal/service.ts +2 -2
  231. package/src/panels/agent-inspector-panel.ts +2 -2
  232. package/src/panels/agent-logs-panel.ts +3 -3
  233. package/src/panels/approval-panel.ts +2 -2
  234. package/src/panels/builtin/operations.ts +3 -1
  235. package/src/panels/builtin/shared.ts +13 -13
  236. package/src/panels/context-visualizer-panel.ts +2 -2
  237. package/src/panels/cost-tracker-panel.ts +2 -2
  238. package/src/panels/debug-panel.ts +3 -3
  239. package/src/panels/git-panel.ts +1 -1
  240. package/src/panels/hooks-panel.ts +4 -4
  241. package/src/panels/knowledge-panel.ts +1 -1
  242. package/src/panels/marketplace-panel.ts +1 -1
  243. package/src/panels/mcp-panel.ts +1 -1
  244. package/src/panels/memory-panel.ts +2 -2
  245. package/src/panels/ops-control-panel.ts +2 -2
  246. package/src/panels/ops-strategy-panel.ts +2 -2
  247. package/src/panels/plugins-panel.ts +1 -1
  248. package/src/panels/policy-panel.ts +1 -1
  249. package/src/panels/provider-health-panel.ts +3 -3
  250. package/src/panels/provider-stats-panel.ts +2 -2
  251. package/src/panels/sandbox-panel.ts +1 -1
  252. package/src/panels/schedule-panel.ts +1 -1
  253. package/src/panels/settings-sync-panel.ts +1 -1
  254. package/src/panels/system-messages-panel.ts +1 -1
  255. package/src/panels/tasks-panel.ts +1 -1
  256. package/src/panels/thinking-panel.ts +2 -2
  257. package/src/panels/token-budget-panel.ts +1 -1
  258. package/src/panels/tool-inspector-panel.ts +2 -2
  259. package/src/panels/worktree-panel.ts +1 -1
  260. package/src/panels/wrfc-panel.ts +4 -4
  261. package/src/permissions/briefs/build.ts +1 -1
  262. package/src/permissions/manager.ts +1 -356
  263. package/src/permissions/prompt.ts +1 -1
  264. package/src/plugins/api.ts +9 -9
  265. package/src/plugins/loader.ts +8 -8
  266. package/src/plugins/manager.ts +5 -5
  267. package/src/providers/amazon-bedrock-mantle.ts +1 -1
  268. package/src/providers/amazon-bedrock.ts +1 -1
  269. package/src/providers/anthropic-compat.ts +4 -4
  270. package/src/providers/anthropic-sdk-provider.ts +5 -5
  271. package/src/providers/anthropic-vertex.ts +1 -1
  272. package/src/providers/anthropic.ts +4 -4
  273. package/src/providers/auto-register.ts +6 -6
  274. package/src/providers/builtin-catalog.ts +2 -2
  275. package/src/providers/builtin-registry.ts +15 -15
  276. package/src/providers/cache-planner.ts +2 -2
  277. package/src/providers/capabilities.ts +1 -601
  278. package/src/providers/custom-loader.ts +6 -6
  279. package/src/providers/discovered-compat.ts +7 -18
  280. package/src/providers/discovered-factory.ts +7 -7
  281. package/src/providers/discovered-traits.ts +1 -1
  282. package/src/providers/gemini.ts +4 -4
  283. package/src/providers/github-copilot.ts +4 -4
  284. package/src/providers/index.ts +1 -47
  285. package/src/providers/interface.ts +1 -1
  286. package/src/providers/llama-cpp.ts +4 -4
  287. package/src/providers/lm-studio-helpers.ts +1 -1
  288. package/src/providers/lm-studio.ts +4 -4
  289. package/src/providers/model-catalog-cache.ts +1 -1
  290. package/src/providers/model-catalog-notifications.ts +1 -1
  291. package/src/providers/model-catalog-synthetic.ts +2 -2
  292. package/src/providers/model-catalog.ts +7 -7
  293. package/src/providers/model-limits.ts +1 -280
  294. package/src/providers/ollama.ts +4 -4
  295. package/src/providers/openai-codex.ts +2 -2
  296. package/src/providers/openai-compat.ts +4 -4
  297. package/src/providers/openai.ts +3 -3
  298. package/src/providers/optimizer.ts +1 -381
  299. package/src/providers/provider-api.ts +1 -553
  300. package/src/providers/registry-helpers.ts +1 -1
  301. package/src/providers/registry-models.ts +2 -2
  302. package/src/providers/registry-types.ts +5 -5
  303. package/src/providers/registry.ts +1 -729
  304. package/src/providers/runtime-metadata.ts +1 -1
  305. package/src/providers/runtime-snapshot.ts +3 -3
  306. package/src/providers/synthetic.ts +3 -3
  307. package/src/providers/tier-prompts.ts +1 -1
  308. package/src/providers/tool-formats.ts +1 -1
  309. package/src/renderer/agent-detail-modal.ts +2 -2
  310. package/src/renderer/block-actions.ts +1 -1
  311. package/src/renderer/context-inspector.ts +1 -1
  312. package/src/renderer/conversation-layout.ts +1 -1
  313. package/src/renderer/conversation-overlays.ts +1 -1
  314. package/src/renderer/git-status.ts +1 -1
  315. package/src/renderer/live-tail-modal.ts +1 -1
  316. package/src/renderer/process-modal.ts +2 -2
  317. package/src/runtime/bootstrap-background.ts +4 -4
  318. package/src/runtime/bootstrap-command-context.ts +23 -23
  319. package/src/runtime/bootstrap-command-parts.ts +23 -23
  320. package/src/runtime/bootstrap-core.ts +12 -10
  321. package/src/runtime/bootstrap-helpers.ts +2 -2
  322. package/src/runtime/bootstrap-hook-bridge.ts +9 -9
  323. package/src/runtime/bootstrap-runtime-events.ts +4 -4
  324. package/src/runtime/bootstrap-services.ts +4 -4
  325. package/src/runtime/bootstrap-shell.ts +11 -11
  326. package/src/runtime/bootstrap.ts +28 -10
  327. package/src/runtime/compaction/index.ts +1 -90
  328. package/src/runtime/compaction/lifecycle.ts +1 -167
  329. package/src/runtime/compaction/manager.ts +11 -11
  330. package/src/runtime/compaction/quality-score.ts +1 -279
  331. package/src/runtime/compaction/resume-repair.ts +1 -183
  332. package/src/runtime/compaction/strategies/autocompact.ts +1 -65
  333. package/src/runtime/compaction/strategies/boundary-commit.ts +1 -106
  334. package/src/runtime/compaction/strategies/collapse.ts +1 -90
  335. package/src/runtime/compaction/strategies/index.ts +1 -23
  336. package/src/runtime/compaction/strategies/microcompact.ts +1 -74
  337. package/src/runtime/compaction/strategies/reactive.ts +1 -89
  338. package/src/runtime/compaction/types.ts +1 -221
  339. package/src/runtime/context.ts +9 -9
  340. package/src/runtime/diagnostics/actions.ts +1 -1
  341. package/src/runtime/diagnostics/index.ts +5 -5
  342. package/src/runtime/diagnostics/panels/agents.ts +2 -2
  343. package/src/runtime/diagnostics/panels/events.ts +2 -2
  344. package/src/runtime/diagnostics/panels/health.ts +2 -2
  345. package/src/runtime/diagnostics/panels/ops.ts +2 -2
  346. package/src/runtime/diagnostics/panels/policy.ts +2 -2
  347. package/src/runtime/diagnostics/panels/tasks.ts +2 -2
  348. package/src/runtime/diagnostics/panels/tool-calls.ts +2 -2
  349. package/src/runtime/diagnostics/provider.ts +1 -1
  350. package/src/runtime/ecosystem/recommendations.ts +1 -1
  351. package/src/runtime/emitters/agents.ts +2 -2
  352. package/src/runtime/emitters/automation.ts +2 -2
  353. package/src/runtime/emitters/communication.ts +2 -2
  354. package/src/runtime/emitters/compaction.ts +2 -2
  355. package/src/runtime/emitters/control-plane.ts +2 -2
  356. package/src/runtime/emitters/deliveries.ts +2 -2
  357. package/src/runtime/emitters/forensics.ts +2 -2
  358. package/src/runtime/emitters/index.ts +27 -27
  359. package/src/runtime/emitters/knowledge.ts +2 -2
  360. package/src/runtime/emitters/mcp.ts +2 -2
  361. package/src/runtime/emitters/ops.ts +2 -2
  362. package/src/runtime/emitters/orchestration.ts +2 -2
  363. package/src/runtime/emitters/permissions.ts +2 -2
  364. package/src/runtime/emitters/planner.ts +2 -2
  365. package/src/runtime/emitters/plugins.ts +2 -2
  366. package/src/runtime/emitters/providers.ts +2 -2
  367. package/src/runtime/emitters/routes.ts +2 -2
  368. package/src/runtime/emitters/security.ts +2 -2
  369. package/src/runtime/emitters/session.ts +2 -2
  370. package/src/runtime/emitters/surfaces.ts +2 -2
  371. package/src/runtime/emitters/tasks.ts +2 -2
  372. package/src/runtime/emitters/tools.ts +2 -2
  373. package/src/runtime/emitters/transport.ts +2 -2
  374. package/src/runtime/emitters/turn.ts +3 -3
  375. package/src/runtime/emitters/ui.ts +2 -2
  376. package/src/runtime/emitters/watchers.ts +2 -2
  377. package/src/runtime/emitters/workflows.ts +3 -3
  378. package/src/runtime/eval/index.ts +3 -3
  379. package/src/runtime/eval/runner.ts +1 -1
  380. package/src/runtime/eval/suites.ts +1 -1
  381. package/src/runtime/events/domain-map.ts +2 -2
  382. package/src/runtime/events/index.ts +1 -194
  383. package/src/runtime/events/turn.ts +1 -60
  384. package/src/runtime/events/workflows.ts +1 -17
  385. package/src/runtime/forensics/collector.ts +4 -4
  386. package/src/runtime/forensics/index.ts +1 -1
  387. package/src/runtime/foundation-clients.ts +14 -14
  388. package/src/runtime/foundation-services.ts +8 -8
  389. package/src/runtime/guidance.ts +3 -3
  390. package/src/runtime/health/effect-handlers.ts +3 -3
  391. package/src/runtime/health/index.ts +4 -4
  392. package/src/runtime/health/wiring.ts +2 -2
  393. package/src/runtime/index.ts +29 -29
  394. package/src/runtime/integration/helpers.ts +12 -12
  395. package/src/runtime/lifecycle.ts +4 -4
  396. package/src/runtime/mcp/index.ts +3 -3
  397. package/src/runtime/mcp/manager.ts +1 -1
  398. package/src/runtime/network/inbound.ts +2 -2
  399. package/src/runtime/network/index.ts +5 -5
  400. package/src/runtime/network/outbound.ts +2 -2
  401. package/src/runtime/network/shared.ts +1 -1
  402. package/src/runtime/operator-client.ts +9 -9
  403. package/src/runtime/ops/control-plane.ts +2 -2
  404. package/src/runtime/ops/index.ts +3 -3
  405. package/src/runtime/ops/playbooks/index.ts +2 -2
  406. package/src/runtime/ops/playbooks/session-unrecoverable.ts +2 -2
  407. package/src/runtime/ops/playbooks/stuck-turn.ts +1 -1
  408. package/src/runtime/ops/runtime-context.ts +1 -1
  409. package/src/runtime/orchestration/spawn-policy.ts +1 -1
  410. package/src/runtime/peer-client.ts +3 -3
  411. package/src/runtime/perf/index.ts +1 -1
  412. package/src/runtime/perf/slo-collector.ts +1 -1
  413. package/src/runtime/permissions/index.ts +5 -5
  414. package/src/runtime/permissions/policy-runtime.ts +1 -175
  415. package/src/runtime/permissions/rule-suggestions.ts +1 -1
  416. package/src/runtime/plugins/hot-reload.ts +4 -4
  417. package/src/runtime/plugins/index.ts +13 -13
  418. package/src/runtime/plugins/lifecycle.ts +1 -1
  419. package/src/runtime/plugins/manager.ts +10 -10
  420. package/src/runtime/plugins/manifest.ts +2 -2
  421. package/src/runtime/plugins/quarantine.ts +2 -2
  422. package/src/runtime/plugins/trust.ts +2 -2
  423. package/src/runtime/plugins/types.ts +1 -1
  424. package/src/runtime/provider-accounts/registry.ts +2 -2
  425. package/src/runtime/remote/distributed-runtime-contract-schemas.ts +3 -3
  426. package/src/runtime/remote/index.ts +3 -3
  427. package/src/runtime/remote/runner-registry.ts +2 -2
  428. package/src/runtime/remote/supervisor.ts +1 -1
  429. package/src/runtime/runtime-hook-api.ts +1 -1
  430. package/src/runtime/runtime-knowledge-api.ts +1 -1
  431. package/src/runtime/runtime-mcp-api.ts +1 -1
  432. package/src/runtime/runtime-ops-api.ts +2 -2
  433. package/src/runtime/runtime-provider-api.ts +1 -1
  434. package/src/runtime/services.ts +35 -32
  435. package/src/runtime/session-maintenance.ts +1 -1
  436. package/src/runtime/session-persistence.ts +2 -2
  437. package/src/runtime/session-return-context.ts +3 -3
  438. package/src/runtime/settings/control-plane-store.ts +1 -1
  439. package/src/runtime/settings/control-plane.ts +2 -2
  440. package/src/runtime/shell-command-extensions.ts +7 -7
  441. package/src/runtime/shell-command-ops.ts +6 -6
  442. package/src/runtime/shell-command-platform.ts +1 -1
  443. package/src/runtime/shell-command-services.ts +17 -17
  444. package/src/runtime/shell-command-workspace.ts +1 -1
  445. package/src/runtime/store/domains/conversation.ts +1 -1
  446. package/src/runtime/store/domains/index.ts +4 -4
  447. package/src/runtime/store/domains/permissions.ts +1 -1
  448. package/src/runtime/store/helpers/reducers/conversation.ts +3 -3
  449. package/src/runtime/store/helpers/reducers/lifecycle.ts +3 -3
  450. package/src/runtime/store/helpers/reducers/shared.ts +2 -2
  451. package/src/runtime/store/helpers/reducers/sync.ts +1 -1
  452. package/src/runtime/store/helpers/reducers.ts +4 -4
  453. package/src/runtime/store/index.ts +4 -4
  454. package/src/runtime/store/selectors/index.ts +2 -2
  455. package/src/runtime/store/state.ts +4 -4
  456. package/src/runtime/tasks/adapters/acp-adapter.ts +1 -1
  457. package/src/runtime/tasks/adapters/index.ts +6 -6
  458. package/src/runtime/tasks/index.ts +3 -3
  459. package/src/runtime/tasks/manager.ts +3 -3
  460. package/src/runtime/telemetry/api-helpers.ts +2 -2
  461. package/src/runtime/telemetry/api.ts +2 -2
  462. package/src/runtime/telemetry/index.ts +5 -5
  463. package/src/runtime/telemetry/instrumentation/domain-bridge-agent-session.ts +1 -1
  464. package/src/runtime/telemetry/instrumentation/domain-bridge-plugin-mcp.ts +1 -1
  465. package/src/runtime/telemetry/instrumentation/domain-bridge-shared.ts +1 -1
  466. package/src/runtime/telemetry/instrumentation/domain-bridge-transport-task.ts +1 -1
  467. package/src/runtime/telemetry/instrumentation/domain-bridge.ts +5 -5
  468. package/src/runtime/telemetry/instrumentation/index.ts +3 -3
  469. package/src/runtime/tools/context.ts +3 -3
  470. package/src/runtime/tools/index.ts +4 -4
  471. package/src/runtime/tools/phased-executor.ts +3 -3
  472. package/src/runtime/tools/phases/budget.ts +1 -1
  473. package/src/runtime/tools/phases/execute.ts +1 -1
  474. package/src/runtime/tools/phases/index.ts +7 -7
  475. package/src/runtime/tools/phases/map-output.ts +1 -1
  476. package/src/runtime/tools/phases/permission.ts +2 -2
  477. package/src/runtime/tools/phases/posthook.ts +1 -1
  478. package/src/runtime/tools/phases/prehook.ts +1 -1
  479. package/src/runtime/tools/phases/validate.ts +1 -1
  480. package/src/runtime/transports/direct.ts +4 -4
  481. package/src/runtime/transports/http-helpers.ts +3 -3
  482. package/src/runtime/transports/http-types.ts +6 -6
  483. package/src/runtime/transports/http.ts +8 -8
  484. package/src/runtime/transports/realtime.ts +4 -4
  485. package/src/runtime/transports/remote-events.ts +1 -1
  486. package/src/runtime/transports/shared.ts +2 -2
  487. package/src/runtime/transports/ui-runtime-events.ts +2 -2
  488. package/src/runtime/ui/index.ts +7 -7
  489. package/src/runtime/ui/model-picker/data-provider.ts +4 -4
  490. package/src/runtime/ui/model-picker/health-enrichment.ts +3 -3
  491. package/src/runtime/ui/model-picker/index.ts +8 -8
  492. package/src/runtime/ui/provider-health/data-provider.ts +2 -2
  493. package/src/runtime/ui/provider-health/fallback-visualizer.ts +1 -1
  494. package/src/runtime/ui/provider-health/index.ts +5 -5
  495. package/src/runtime/ui-events.ts +1 -1
  496. package/src/runtime/ui-read-models-core.ts +2 -2
  497. package/src/runtime/ui-read-models-observability-maintenance.ts +4 -4
  498. package/src/runtime/ui-read-models-observability-options.ts +1 -1
  499. package/src/runtime/ui-read-models-observability-remote.ts +2 -2
  500. package/src/runtime/ui-read-models-observability-security.ts +3 -3
  501. package/src/runtime/ui-read-models-observability-system.ts +6 -6
  502. package/src/runtime/ui-read-models-observability.ts +10 -10
  503. package/src/runtime/ui-read-models-operations.ts +2 -2
  504. package/src/runtime/ui-read-models.ts +7 -7
  505. package/src/runtime/ui-service-queries.ts +2 -2
  506. package/src/runtime/ui-services.ts +7 -7
  507. package/src/runtime/worktree/registry.ts +1 -1
  508. package/src/scripts/process-messages.ts +1 -1
  509. package/src/sessions/manager.ts +9 -383
  510. package/src/shell/blocking-input.ts +3 -3
  511. package/src/shell/ui-openers.ts +3 -3
  512. package/src/state/file-watcher.ts +1 -1
  513. package/src/state/index.ts +10 -10
  514. package/src/state/knowledge-injection.ts +2 -2
  515. package/src/state/memory-embedding-http.ts +2 -2
  516. package/src/state/memory-embeddings.ts +1 -1
  517. package/src/state/memory-ingest.ts +3 -3
  518. package/src/state/memory-registry.ts +3 -3
  519. package/src/state/memory-store-helpers.ts +1 -1
  520. package/src/state/memory-store.ts +4 -4
  521. package/src/state/memory-vector-store.ts +3 -3
  522. package/src/tools/agent/index.ts +7 -7
  523. package/src/tools/agent/manager.ts +8 -8
  524. package/src/tools/analyze/git-modes.ts +2 -2
  525. package/src/tools/analyze/index.ts +2 -2
  526. package/src/tools/channel/agent-tools.ts +1 -1
  527. package/src/tools/channel/index.ts +2 -2
  528. package/src/tools/edit/core.ts +4 -4
  529. package/src/tools/edit/index.ts +2 -2
  530. package/src/tools/edit/phased.ts +2 -2
  531. package/src/tools/fetch/index.ts +2 -2
  532. package/src/tools/fetch/phased.ts +1 -1
  533. package/src/tools/index.ts +21 -21
  534. package/src/tools/mcp/index.ts +1 -1
  535. package/src/tools/remote-trigger/index.ts +1 -1
  536. package/src/tools/shared/auto-heal.ts +2 -2
  537. package/src/tools/state/index.ts +1 -1
  538. package/src/tools/web-search/index.ts +1 -1
  539. package/src/tools/write/index.ts +3 -3
  540. package/src/tools/write/phased.ts +1 -1
  541. package/src/version.ts +1 -1
  542. package/src/watchers/index.ts +2 -2
  543. package/src/watchers/registry.ts +2 -2
  544. package/src/web-search/index.ts +10 -10
  545. package/src/web-search/provider-registry.ts +8 -8
  546. package/src/web-search/providers/brave.ts +1 -1
  547. package/src/web-search/providers/duckduckgo.ts +1 -1
  548. package/src/web-search/providers/exa.ts +1 -1
  549. package/src/web-search/providers/firecrawl.ts +1 -1
  550. package/src/web-search/providers/perplexity.ts +1 -1
  551. package/src/web-search/providers/searxng.ts +1 -1
  552. package/src/web-search/providers/shared.ts +1 -1
  553. package/src/web-search/providers/tavily.ts +1 -1
  554. package/src/web-search/service.ts +2 -2
  555. package/src/runtime/ecosystem/catalog.ts +0 -606
@@ -1,547 +1,26 @@
1
- /**
2
- * SecretsManager — hierarchy-aware secret resolution and persistence.
3
- *
4
- * Resolution order:
5
- * 1. Environment variable (process.env[key])
6
- * 2. Project/ancestor secure stores (.goodvibes/tui/secrets.enc), nearest first
7
- * 3. Project/ancestor plaintext stores (.goodvibes/goodvibes.secrets.json), nearest first
8
- * 4. User secure store (~/.goodvibes/tui/secrets.enc)
9
- * 5. User plaintext store (~/.goodvibes/goodvibes.secrets.json)
10
- * 6. If a resolved value is a SecretRef, resolve through the referenced provider
11
- *
12
- * The active policy decides whether plaintext stores are eligible:
13
- * - plaintext_allowed read/write plaintext or secure
14
- * - preferred_secure → prefer secure, allow plaintext fallback with warning
15
- * - require_secure → never read/write plaintext
16
- *
17
- * Secret values are never logged.
18
- */
19
-
20
- import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'crypto';
21
- import { dirname, isAbsolute, join, resolve } from 'path';
22
- import { hostname, userInfo } from 'os';
23
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
24
- import type { ConfigManager } from './manager.ts';
25
- import { getSecretRefSource, isSecretRefInput, resolveSecretRef } from '@pellux/goodvibes-sdk/platform/config/secret-refs';
26
- import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
27
- import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
28
-
29
- export type SecretStorageMode = 'plaintext_allowed' | 'preferred_secure' | 'require_secure';
30
- export type SecretScope = 'project' | 'user';
31
- export type SecretStorageMedium = 'secure' | 'plaintext';
32
- export type SecretSource =
33
- | 'env'
34
- | 'project-secure'
35
- | 'project-plaintext'
36
- | 'user-secure'
37
- | 'user-plaintext';
38
-
39
- export interface SecretRecord {
40
- readonly key: string;
41
- readonly source: SecretSource;
42
- readonly scope: SecretScope | 'env';
43
- readonly secure: boolean;
44
- readonly path?: string;
45
- readonly overriddenByEnv: boolean;
46
- readonly refSource?: string;
47
- }
48
-
49
- export interface SecretWriteOptions {
50
- readonly scope?: SecretScope;
51
- readonly medium?: SecretStorageMedium;
52
- }
53
-
54
- export interface SecretDeleteOptions {
55
- readonly scope?: SecretScope;
56
- readonly medium?: SecretStorageMedium;
57
- }
58
-
59
- export interface SecretStorageReview {
60
- readonly policy: SecretStorageMode;
61
- readonly secureAvailable: boolean;
62
- readonly storedKeys: number;
63
- readonly envBackedKeys: number;
64
- readonly secureKeys: number;
65
- readonly plaintextKeys: number;
66
- readonly warnings: readonly string[];
67
- readonly locations: readonly {
68
- readonly source: Exclude<SecretSource, 'env'>;
69
- readonly path: string;
70
- readonly exists: boolean;
71
- readonly readable: boolean;
72
- }[];
73
- }
74
-
75
- interface EncryptedStore {
76
- iv: string;
77
- tag: string;
78
- data: string;
79
- }
80
-
81
- interface PlaintextStore {
82
- readonly version: 1;
83
- readonly secrets: Record<string, string>;
84
- }
85
-
86
- interface SecretStorePath {
87
- readonly source: Exclude<SecretSource, 'env'>;
88
- readonly path: string;
89
- readonly secure: boolean;
90
- readonly scope: SecretScope;
91
- }
92
-
93
- export interface SecretsManagerOptions {
94
- readonly projectRoot: string;
95
- readonly globalHome: string;
96
- readonly configManager?: Pick<ConfigManager, 'get'>;
97
- readonly policy?: SecretStorageMode;
98
- readonly secureProjectFilePath?: string;
99
- readonly secureUserFilePath?: string;
100
- readonly plaintextProjectFilePath?: string;
101
- readonly plaintextUserFilePath?: string;
102
- }
103
-
104
- function requireAbsoluteOwnedPath(path: string, name: string): string {
105
- const trimmed = path.trim();
106
- if (!trimmed) {
107
- throw new Error(`SecretsManager ${name} must be a non-empty absolute path.`);
108
- }
109
- if (!isAbsolute(trimmed)) {
110
- throw new Error(`SecretsManager ${name} must be an absolute path.`);
111
- }
112
- return resolve(trimmed);
113
- }
114
-
115
- function normalizeOptionalOwnedPath(path: string | undefined, name: string): string | undefined {
116
- return path === undefined ? undefined : requireAbsoluteOwnedPath(path, name);
117
- }
118
-
119
- function deriveEncryptionKey(): Buffer {
120
- const seed = hostname() + userInfo().username + 'goodvibes-secrets';
121
- return createHash('sha256').update(seed, 'utf8').digest();
122
- }
123
-
124
- function encrypt(plaintext: string, key: Buffer): EncryptedStore {
125
- const iv = randomBytes(12);
126
- const cipher = createCipheriv('aes-256-gcm', key, iv);
127
- const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
128
- const tag = cipher.getAuthTag();
129
- return { iv: iv.toString('hex'), tag: tag.toString('hex'), data: encrypted.toString('hex') };
130
- }
131
-
132
- function decrypt(store: EncryptedStore, key: Buffer): string {
133
- const iv = Buffer.from(store.iv, 'hex');
134
- const tag = Buffer.from(store.tag, 'hex');
135
- const data = Buffer.from(store.data, 'hex');
136
- const decipher = createDecipheriv('aes-256-gcm', key, iv);
137
- decipher.setAuthTag(tag);
138
- const decrypted = Buffer.concat([decipher.update(data), decipher.final()]);
139
- return decrypted.toString('utf8');
140
- }
141
-
142
- function loadConfiguredSecretPolicy(configManager?: Pick<ConfigManager, 'get'>): SecretStorageMode {
143
- try {
144
- return (configManager?.get('storage.secretPolicy') as SecretStorageMode | undefined) ?? 'preferred_secure';
145
- } catch {
146
- return 'preferred_secure';
147
- }
148
- }
149
-
150
- function uniquePaths(paths: readonly SecretStorePath[]): SecretStorePath[] {
151
- const seen = new Set<string>();
152
- const ordered: SecretStorePath[] = [];
153
- for (const path of paths) {
154
- const key = `${path.source}:${path.path}`;
155
- if (seen.has(key)) continue;
156
- seen.add(key);
157
- ordered.push(path);
158
- }
159
- return ordered;
160
- }
161
-
162
- function collectAncestorRoots(start: string): string[] {
163
- const roots: string[] = [];
164
- let current = resolve(start);
165
- while (true) {
166
- roots.push(current);
167
- const parent = dirname(current);
168
- if (parent === current) break;
169
- current = parent;
170
- }
171
- return roots;
172
- }
173
-
174
- export class SecretsManager {
175
- private readonly encKey: Buffer;
176
- private readonly options: SecretsManagerOptions;
177
-
1
+ export type {
2
+ SecretDeleteOptions,
3
+ SecretRecord,
4
+ SecretScope,
5
+ SecretSource,
6
+ SecretStorageMedium,
7
+ SecretStorageMode,
8
+ SecretStorageReview,
9
+ SecretWriteOptions,
10
+ } from '@pellux/goodvibes-sdk/platform/config/secrets';
11
+
12
+ import {
13
+ SecretsManager as SdkSecretsManager,
14
+ type SecretsManagerOptions as SdkSecretsManagerOptions,
15
+ } from '@pellux/goodvibes-sdk/platform/config/secrets';
16
+
17
+ export type SecretsManagerOptions = Omit<SdkSecretsManagerOptions, 'surfaceRoot'>;
18
+
19
+ export class SecretsManager extends SdkSecretsManager {
178
20
  constructor(options: SecretsManagerOptions) {
179
- this.encKey = deriveEncryptionKey();
180
- this.options = {
21
+ super({
181
22
  ...options,
182
- projectRoot: requireAbsoluteOwnedPath(options.projectRoot, 'projectRoot'),
183
- globalHome: requireAbsoluteOwnedPath(options.globalHome, 'globalHome'),
184
- secureProjectFilePath: normalizeOptionalOwnedPath(options.secureProjectFilePath, 'secureProjectFilePath'),
185
- secureUserFilePath: normalizeOptionalOwnedPath(options.secureUserFilePath, 'secureUserFilePath'),
186
- plaintextProjectFilePath: normalizeOptionalOwnedPath(options.plaintextProjectFilePath, 'plaintextProjectFilePath'),
187
- plaintextUserFilePath: normalizeOptionalOwnedPath(options.plaintextUserFilePath, 'plaintextUserFilePath'),
188
- };
189
- }
190
-
191
- getGlobalHome(): string {
192
- return this.options.globalHome;
193
- }
194
-
195
- async get(key: string): Promise<string | null> {
196
- return this.getInternal(key, new Set([key]));
197
- }
198
-
199
- private async getInternal(key: string, seen: Set<string>): Promise<string | null> {
200
- const envValue = process.env[key];
201
- if (envValue !== undefined) {
202
- logger.debug('SecretsManager: resolved from env', { key });
203
- return this.resolveMaybeReferencedValue(key, envValue, seen);
204
- }
205
-
206
- for (const path of this.getReadOrder()) {
207
- const secrets = path.secure
208
- ? this.readEncryptedFile(path.path)
209
- : this.readPlaintextFile(path.path);
210
- if (secrets !== null && key in secrets) {
211
- logger.debug('SecretsManager: resolved from store', { key, source: path.source });
212
- const value = secrets[key];
213
- return value === undefined ? null : this.resolveMaybeReferencedValue(key, value, seen);
214
- }
215
- }
216
-
217
- return null;
218
- }
219
-
220
- private async resolveMaybeReferencedValue(key: string, value: string, seen: Set<string>): Promise<string | null> {
221
- if (!isSecretRefInput(value)) return value;
222
-
223
- try {
224
- const resolved = await resolveSecretRef(value, {
225
- resolveLocalSecret: async (nextKey) => {
226
- if (seen.has(nextKey)) {
227
- throw new Error(`Recursive GoodVibes secret reference for ${nextKey}`);
228
- }
229
- const nextSeen = new Set(seen);
230
- nextSeen.add(nextKey);
231
- return this.getInternal(nextKey, nextSeen);
232
- },
233
- homeDirectory: this.options.globalHome,
234
- });
235
- logger.debug('SecretsManager: resolved secret reference', { key, refSource: resolved.source });
236
- return resolved.value;
237
- } catch (error) {
238
- logger.warn('SecretsManager: failed to resolve secret reference', {
239
- key,
240
- refSource: getSecretRefSource(value) ?? 'unknown',
241
- error: summarizeError(error),
242
- });
243
- return null;
244
- }
245
- }
246
-
247
- async set(key: string, value: string, options: SecretWriteOptions = {}): Promise<void> {
248
- const policy = this.getPolicy();
249
- const medium = options.medium ?? this.getDefaultWriteMedium(policy);
250
- const scope = options.scope ?? 'project';
251
-
252
- if (policy === 'require_secure' && medium === 'plaintext') {
253
- throw new Error('Secret policy require_secure forbids plaintext persistence');
254
- }
255
-
256
- const target = this.resolveWriteTarget(scope, medium);
257
- const existing = target.secure
258
- ? this.readEncryptedFile(target.path) ?? {}
259
- : this.readPlaintextFile(target.path) ?? {};
260
- existing[key] = value;
261
-
262
- try {
263
- if (target.secure) {
264
- this.writeEncryptedFile(target.path, existing);
265
- } else {
266
- this.writePlaintextFile(target.path, existing);
267
- }
268
- logger.debug('SecretsManager: stored secret', { key, source: target.source });
269
- return;
270
- } catch (error) {
271
- if (policy === 'preferred_secure' && target.secure) {
272
- const fallback = this.resolveWriteTarget(scope, 'plaintext');
273
- const fallbackExisting = this.readPlaintextFile(fallback.path) ?? {};
274
- fallbackExisting[key] = value;
275
- this.writePlaintextFile(fallback.path, fallbackExisting);
276
- logger.warn('SecretsManager: secure write failed, fell back to plaintext', {
277
- key,
278
- path: fallback.path,
279
- error: summarizeError(error),
280
- });
281
- return;
282
- }
283
- throw error;
284
- }
285
- }
286
-
287
- async list(): Promise<string[]> {
288
- const keys = new Set<string>();
289
- for (const path of this.getReadOrder()) {
290
- const values = path.secure
291
- ? this.readEncryptedFile(path.path)
292
- : this.readPlaintextFile(path.path);
293
- if (!values) continue;
294
- for (const key of Object.keys(values)) keys.add(key);
295
- }
296
- return [...keys].sort((a, b) => a.localeCompare(b));
297
- }
298
-
299
- async listDetailed(): Promise<SecretRecord[]> {
300
- const envKeys = new Set(Object.keys(process.env));
301
- const records: SecretRecord[] = [];
302
-
303
- for (const path of this.getReadOrder()) {
304
- const values = path.secure
305
- ? this.readEncryptedFile(path.path)
306
- : this.readPlaintextFile(path.path);
307
- if (!values) continue;
308
- for (const key of Object.keys(values)) {
309
- const refSource = getSecretRefSource(values[key]);
310
- records.push({
311
- key,
312
- source: path.source,
313
- scope: path.scope,
314
- secure: path.secure,
315
- path: path.path,
316
- overriddenByEnv: envKeys.has(key),
317
- ...(refSource ? { refSource } : {}),
318
- });
319
- }
320
- }
321
-
322
- for (const key of envKeys) {
323
- records.push({
324
- key,
325
- source: 'env',
326
- scope: 'env',
327
- secure: false,
328
- overriddenByEnv: false,
329
- });
330
- }
331
-
332
- return records.sort((a, b) => a.key.localeCompare(b.key) || a.source.localeCompare(b.source));
333
- }
334
-
335
- async inspect(): Promise<SecretStorageReview> {
336
- const policy = this.getPolicy();
337
- const records = await this.listDetailed();
338
- const storedRecords = records.filter((record) => record.source !== 'env');
339
- const locations = uniquePaths(this.getAllCandidateStores()).map((path) => ({
340
- source: path.source,
341
- path: path.path,
342
- exists: existsSync(path.path),
343
- readable: (path.secure ? this.readEncryptedFile(path.path) : this.readPlaintextFile(path.path)) !== null,
344
- }));
345
- const warnings: string[] = [];
346
- if (policy === 'preferred_secure' && storedRecords.some((record) => !record.secure)) {
347
- warnings.push('plaintext fallback secrets are present');
348
- }
349
- if (policy === 'require_secure' && storedRecords.some((record) => !record.secure)) {
350
- warnings.push('plaintext secrets exist but are ignored by current policy');
351
- }
352
-
353
- return {
354
- policy,
355
- secureAvailable: true,
356
- storedKeys: new Set(storedRecords.map((record) => record.key)).size,
357
- envBackedKeys: new Set(records.filter((record) => record.source === 'env').map((record) => record.key)).size,
358
- secureKeys: new Set(storedRecords.filter((record) => record.secure).map((record) => record.key)).size,
359
- plaintextKeys: new Set(storedRecords.filter((record) => !record.secure).map((record) => record.key)).size,
360
- warnings,
361
- locations,
362
- };
363
- }
364
-
365
- async delete(key: string, options: SecretDeleteOptions = {}): Promise<void> {
366
- const stores = this.getAllCandidateStores().filter((store) => {
367
- if (options.scope && store.scope !== options.scope) return false;
368
- if (options.medium && (options.medium === 'secure') !== store.secure) return false;
369
- return true;
370
- });
371
-
372
- for (const store of stores) {
373
- const values = store.secure
374
- ? this.readEncryptedFile(store.path)
375
- : this.readPlaintextFile(store.path);
376
- if (!values || !(key in values)) continue;
377
- delete values[key];
378
- if (store.secure) this.writeEncryptedFile(store.path, values);
379
- else this.writePlaintextFile(store.path, values);
380
- logger.debug('SecretsManager: deleted secret', { key, source: store.source });
381
- }
382
- }
383
-
384
- private getPolicy(): SecretStorageMode {
385
- return this.options.policy ?? loadConfiguredSecretPolicy(this.options.configManager);
386
- }
387
-
388
- private getReadOrder(): SecretStorePath[] {
389
- const policy = this.getPolicy();
390
- const includePlaintext = policy !== 'require_secure';
391
- const ordered: SecretStorePath[] = [];
392
- const projectRoot = this.options.projectRoot;
393
- const userHome = this.options.globalHome;
394
-
395
- for (const root of collectAncestorRoots(projectRoot)) {
396
- ordered.push({
397
- source: 'project-secure',
398
- path: this.options.secureProjectFilePath ?? join(root, '.goodvibes', 'tui', 'secrets.enc'),
399
- secure: true,
400
- scope: 'project',
401
- });
402
- if (includePlaintext) {
403
- ordered.push({
404
- source: 'project-plaintext',
405
- path: this.options.plaintextProjectFilePath ?? join(root, '.goodvibes', 'goodvibes.secrets.json'),
406
- secure: false,
407
- scope: 'project',
408
- });
409
- }
410
- }
411
-
412
- ordered.push({
413
- source: 'user-secure',
414
- path: this.options.secureUserFilePath ?? join(userHome, '.goodvibes', 'tui', 'secrets.enc'),
415
- secure: true,
416
- scope: 'user',
417
- });
418
-
419
- if (includePlaintext) {
420
- ordered.push({
421
- source: 'user-plaintext',
422
- path: this.options.plaintextUserFilePath ?? join(userHome, '.goodvibes', 'goodvibes.secrets.json'),
423
- secure: false,
424
- scope: 'user',
425
- });
426
- }
427
-
428
- return uniquePaths(ordered);
429
- }
430
-
431
- private getAllCandidateStores(): SecretStorePath[] {
432
- const projectRoot = this.options.projectRoot;
433
- const userHome = this.options.globalHome;
434
- const ordered: SecretStorePath[] = [];
435
- for (const root of collectAncestorRoots(projectRoot)) {
436
- ordered.push({
437
- source: 'project-secure',
438
- path: this.options.secureProjectFilePath ?? join(root, '.goodvibes', 'tui', 'secrets.enc'),
439
- secure: true,
440
- scope: 'project',
441
- });
442
- ordered.push({
443
- source: 'project-plaintext',
444
- path: this.options.plaintextProjectFilePath ?? join(root, '.goodvibes', 'goodvibes.secrets.json'),
445
- secure: false,
446
- scope: 'project',
447
- });
448
- }
449
- ordered.push({
450
- source: 'user-secure',
451
- path: this.options.secureUserFilePath ?? join(userHome, '.goodvibes', 'tui', 'secrets.enc'),
452
- secure: true,
453
- scope: 'user',
454
- });
455
- ordered.push({
456
- source: 'user-plaintext',
457
- path: this.options.plaintextUserFilePath ?? join(userHome, '.goodvibes', 'goodvibes.secrets.json'),
458
- secure: false,
459
- scope: 'user',
23
+ surfaceRoot: 'tui',
460
24
  });
461
- return uniquePaths(ordered);
462
- }
463
-
464
- private resolveWriteTarget(scope: SecretScope, medium: SecretStorageMedium): SecretStorePath {
465
- if (scope === 'project') {
466
- const root = this.options.projectRoot;
467
- return medium === 'secure'
468
- ? {
469
- source: 'project-secure',
470
- path: this.options.secureProjectFilePath ?? join(root, '.goodvibes', 'tui', 'secrets.enc'),
471
- secure: true,
472
- scope,
473
- }
474
- : {
475
- source: 'project-plaintext',
476
- path: this.options.plaintextProjectFilePath ?? join(root, '.goodvibes', 'goodvibes.secrets.json'),
477
- secure: false,
478
- scope,
479
- };
480
- }
481
-
482
- const userHome = this.options.globalHome;
483
- return medium === 'secure'
484
- ? {
485
- source: 'user-secure',
486
- path: this.options.secureUserFilePath ?? join(userHome, '.goodvibes', 'tui', 'secrets.enc'),
487
- secure: true,
488
- scope,
489
- }
490
- : {
491
- source: 'user-plaintext',
492
- path: this.options.plaintextUserFilePath ?? join(userHome, '.goodvibes', 'goodvibes.secrets.json'),
493
- secure: false,
494
- scope,
495
- };
496
- }
497
-
498
- private getDefaultWriteMedium(policy: SecretStorageMode): SecretStorageMedium {
499
- return policy === 'plaintext_allowed' ? 'plaintext' : 'secure';
500
- }
501
-
502
- private readEncryptedFile(filePath: string): Record<string, string> | null {
503
- try {
504
- const raw = readFileSync(filePath, 'utf-8');
505
- const store: EncryptedStore = JSON.parse(raw);
506
- return JSON.parse(decrypt(store, this.encKey)) as Record<string, string>;
507
- } catch (err) {
508
- const code = (err as NodeJS.ErrnoException).code;
509
- if (code !== 'ENOENT') {
510
- logger.error('SecretsManager: failed to read encrypted store', { path: filePath });
511
- }
512
- return null;
513
- }
514
- }
515
-
516
- private writeEncryptedFile(filePath: string, secrets: Record<string, string>): void {
517
- mkdirSync(dirname(filePath), { recursive: true });
518
- const plaintext = JSON.stringify(secrets);
519
- const store = encrypt(plaintext, this.encKey);
520
- writeFileSync(filePath, `${JSON.stringify(store, null, 2)}\n`, 'utf-8');
521
- }
522
-
523
- private readPlaintextFile(filePath: string): Record<string, string> | null {
524
- try {
525
- const raw = readFileSync(filePath, 'utf-8');
526
- const parsed = JSON.parse(raw) as unknown;
527
- if (!parsed || typeof parsed !== 'object') return null;
528
- if ('version' in parsed && 'secrets' in parsed) {
529
- const secrets = (parsed as PlaintextStore).secrets;
530
- return secrets && typeof secrets === 'object' ? secrets : null;
531
- }
532
- return parsed as Record<string, string>;
533
- } catch (err) {
534
- const code = (err as NodeJS.ErrnoException).code;
535
- if (code !== 'ENOENT') {
536
- logger.error('SecretsManager: failed to read plaintext store', { path: filePath });
537
- }
538
- return null;
539
- }
540
- }
541
-
542
- private writePlaintextFile(filePath: string, secrets: Record<string, string>): void {
543
- mkdirSync(dirname(filePath), { recursive: true });
544
- const payload: PlaintextStore = { version: 1, secrets };
545
- writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
546
25
  }
547
26
  }