@gajae-code/coding-agent 0.11.11 → 0.12.1

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 (344) hide show
  1. package/CHANGELOG.md +131 -4
  2. package/dist/types/async/job-manager.d.ts +17 -3
  3. package/dist/types/cli/read-cli.d.ts +1 -0
  4. package/dist/types/commands/deep-interview.d.ts +9 -0
  5. package/dist/types/commands/harness.d.ts +22 -0
  6. package/dist/types/commands/read.d.ts +6 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/provider-auth-health.d.ts +14 -0
  9. package/dist/types/config/provider-ranking.d.ts +59 -0
  10. package/dist/types/config/settings-schema.d.ts +83 -1
  11. package/dist/types/config/settings.d.ts +2 -0
  12. package/dist/types/exa/mcp-client.d.ts +10 -1
  13. package/dist/types/exec/bash-executor.d.ts +45 -12
  14. package/dist/types/extensibility/extensions/types.d.ts +38 -4
  15. package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
  16. package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
  17. package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
  18. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
  19. package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
  20. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
  21. package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
  22. package/dist/types/extensibility/shared-events.d.ts +6 -0
  23. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
  24. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
  25. package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
  26. package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
  27. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  28. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  29. package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
  30. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +70 -1
  31. package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
  32. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  33. package/dist/types/gjc-runtime/team-runtime.d.ts +27 -1
  34. package/dist/types/gjc-runtime/team-store.d.ts +12 -0
  35. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
  36. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
  37. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +17 -0
  38. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
  39. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
  40. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
  41. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  42. package/dist/types/main.d.ts +1 -1
  43. package/dist/types/memories/index.d.ts +2 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +10 -19
  45. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  46. package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
  47. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  48. package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
  49. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  50. package/dist/types/modes/components/session-observer-overlay.d.ts +22 -0
  51. package/dist/types/modes/components/settings-selector.d.ts +11 -0
  52. package/dist/types/modes/components/status-line/gh.d.ts +5 -0
  53. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  54. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
  55. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  56. package/dist/types/modes/interactive-mode.d.ts +2 -0
  57. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  58. package/dist/types/modes/types.d.ts +2 -0
  59. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  60. package/dist/types/reminders/star-reminder.d.ts +3 -13
  61. package/dist/types/runtime-mcp/manager.d.ts +1 -0
  62. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +3 -1
  64. package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
  65. package/dist/types/sdk/broker/transport.d.ts +2 -0
  66. package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
  67. package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
  68. package/dist/types/sdk/bus/config.d.ts +6 -2
  69. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  70. package/dist/types/sdk/bus/index.d.ts +44 -1
  71. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +44 -0
  72. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  73. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
  74. package/dist/types/sdk/bus/reconciliation-store.d.ts +69 -0
  75. package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
  76. package/dist/types/sdk/bus/rich-render.d.ts +2 -0
  77. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
  78. package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
  79. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
  80. package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
  81. package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
  82. package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
  83. package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
  84. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  85. package/dist/types/sdk/host/host.d.ts +2 -0
  86. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  87. package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
  88. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  89. package/dist/types/sdk/prompt-status.d.ts +23 -3
  90. package/dist/types/sdk/session.d.ts +6 -0
  91. package/dist/types/session/agent-session.d.ts +82 -12
  92. package/dist/types/session/artifacts.d.ts +8 -0
  93. package/dist/types/session/blob-store.d.ts +57 -4
  94. package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
  95. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  96. package/dist/types/session/session-manager.d.ts +48 -19
  97. package/dist/types/session/session-storage.d.ts +4 -0
  98. package/dist/types/session/streaming-output.d.ts +96 -12
  99. package/dist/types/setup/credential-import.d.ts +12 -0
  100. package/dist/types/skill-state/active-state.d.ts +12 -4
  101. package/dist/types/skill-state/workflow-hud.d.ts +9 -0
  102. package/dist/types/task/executor.d.ts +3 -2
  103. package/dist/types/task/index.d.ts +3 -1
  104. package/dist/types/task/provider-retry-status.d.ts +8 -0
  105. package/dist/types/task/receipt.d.ts +7 -1
  106. package/dist/types/task/types.d.ts +23 -0
  107. package/dist/types/tools/ask-answer-registry.d.ts +2 -2
  108. package/dist/types/tools/bash-interactive.d.ts +4 -1
  109. package/dist/types/tools/bash.d.ts +3 -1
  110. package/dist/types/tools/browser/launch.d.ts +7 -0
  111. package/dist/types/tools/fetch.d.ts +17 -1
  112. package/dist/types/tools/image-gen.d.ts +4 -0
  113. package/dist/types/tools/index.d.ts +4 -0
  114. package/dist/types/tools/output-meta.d.ts +44 -3
  115. package/dist/types/tools/path-utils.d.ts +1 -0
  116. package/dist/types/tools/read-internals.d.ts +12 -0
  117. package/dist/types/tools/read.d.ts +45 -7
  118. package/dist/types/tools/resource-gc.d.ts +4 -0
  119. package/dist/types/tools/review.d.ts +5 -7
  120. package/dist/types/tools/subagent.d.ts +2 -0
  121. package/dist/types/tools/tool-result.d.ts +7 -1
  122. package/dist/types/utils/gh.d.ts +13 -0
  123. package/dist/types/utils/image-resize.d.ts +1 -0
  124. package/dist/types/web/search/providers/kimi.d.ts +2 -0
  125. package/dist/types/web/search/providers/searxng.d.ts +7 -0
  126. package/dist/types/web/search/providers/xai.d.ts +2 -0
  127. package/package.json +11 -13
  128. package/scripts/acp-conformance-agent.ts +218 -0
  129. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  130. package/scripts/capture-gjc-bundle-settings.ts +306 -0
  131. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  132. package/scripts/generate-sdk-operation-inventory.ts +5 -0
  133. package/scripts/resident-memory-bench.ts +1341 -0
  134. package/scripts/run-acp-conformance.ts +285 -0
  135. package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
  136. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  137. package/src/async/job-manager.ts +78 -20
  138. package/src/capability/index.ts +8 -0
  139. package/src/cli/fast-help.ts +1 -1
  140. package/src/cli/plugin-cli.ts +176 -18
  141. package/src/cli/read-cli.ts +2 -1
  142. package/src/cli.ts +1 -0
  143. package/src/commands/deep-interview.ts +29 -9
  144. package/src/commands/harness.ts +35 -12
  145. package/src/commands/read.ts +11 -2
  146. package/src/commands/team.ts +20 -2
  147. package/src/config/file-lock.ts +11 -2
  148. package/src/config/model-registry.ts +21 -2
  149. package/src/config/provider-auth-health.ts +42 -0
  150. package/src/config/provider-ranking.ts +119 -0
  151. package/src/config/settings-schema.ts +74 -1
  152. package/src/config/settings.ts +246 -108
  153. package/src/coordinator-mcp/question-gate-codec.ts +1 -1
  154. package/src/coordinator-mcp/server.ts +5 -12
  155. package/src/defaults/gjc/skills/deep-interview/SKILL.md +230 -82
  156. package/src/defaults/gjc/skills/ralplan/SKILL.md +77 -41
  157. package/src/defaults/gjc/skills/team/SKILL.md +3 -1
  158. package/src/defaults/gjc/skills/ultragoal/SKILL.md +62 -39
  159. package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
  160. package/src/defaults/gjc-defaults.ts +4 -4
  161. package/src/eval/py/executor.ts +7 -2
  162. package/src/exa/mcp-client.ts +12 -3
  163. package/src/exec/bash-executor.ts +144 -27
  164. package/src/extensibility/extensions/runner.ts +15 -0
  165. package/src/extensibility/extensions/types.ts +46 -5
  166. package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
  167. package/src/extensibility/gjc-plugins/index.ts +19 -2
  168. package/src/extensibility/gjc-plugins/installer.ts +189 -50
  169. package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
  170. package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
  171. package/src/extensibility/gjc-plugins/observability.ts +3 -3
  172. package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
  173. package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
  174. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
  175. package/src/extensibility/gjc-plugins/schema.ts +84 -12
  176. package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
  177. package/src/extensibility/gjc-plugins/types.ts +141 -0
  178. package/src/extensibility/gjc-plugins/validation.ts +9 -0
  179. package/src/extensibility/shared-events.ts +5 -0
  180. package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
  181. package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
  182. package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
  183. package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
  184. package/src/gjc-runtime/deep-interview-state.ts +12 -943
  185. package/src/gjc-runtime/gc-render.ts +1 -0
  186. package/src/gjc-runtime/gc-runtime.ts +11 -1
  187. package/src/gjc-runtime/launch-tmux.ts +25 -6
  188. package/src/gjc-runtime/managed-owner-admission.ts +1 -1
  189. package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
  190. package/src/gjc-runtime/ralplan-runtime.ts +1149 -98
  191. package/src/gjc-runtime/state-runtime.ts +2 -1
  192. package/src/gjc-runtime/state-writer.ts +70 -222
  193. package/src/gjc-runtime/team-launch.ts +42 -5
  194. package/src/gjc-runtime/team-runtime.ts +1085 -40
  195. package/src/gjc-runtime/team-store.ts +32 -0
  196. package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
  197. package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
  198. package/src/gjc-runtime/team-workers.ts +1 -0
  199. package/src/gjc-runtime/tmux-owner-isolation.ts +28 -0
  200. package/src/gjc-runtime/tmux-sessions.ts +58 -13
  201. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
  202. package/src/gjc-runtime/ultragoal-runtime.ts +414 -618
  203. package/src/gjc-runtime/workflow-manifest.generated.json +105 -449
  204. package/src/gjc-runtime/workflow-manifest.ts +38 -247
  205. package/src/hooks/native-skill-hook.ts +17 -4
  206. package/src/hooks/skill-state.ts +1 -23
  207. package/src/internal-urls/docs-index.generated.ts +21 -22
  208. package/src/internal-urls/local-root-gc.ts +127 -0
  209. package/src/main.ts +9 -5
  210. package/src/memories/index.ts +10 -0
  211. package/src/modes/DESIGN.md +98 -0
  212. package/src/modes/acp/acp-agent.ts +339 -191
  213. package/src/modes/acp/acp-event-mapper.ts +14 -7
  214. package/src/modes/acp/acp-mode.ts +39 -3
  215. package/src/modes/components/assistant-message.ts +123 -22
  216. package/src/modes/components/gjc-bundle-settings.ts +508 -0
  217. package/src/modes/components/irc-sidebar.ts +176 -62
  218. package/src/modes/components/model-selector.ts +61 -4
  219. package/src/modes/components/notifications-settings-editor.ts +12 -1
  220. package/src/modes/components/oauth-selector.ts +96 -28
  221. package/src/modes/components/read-tool-group.ts +82 -14
  222. package/src/modes/components/session-observer-overlay.ts +457 -83
  223. package/src/modes/components/settings-selector.ts +116 -23
  224. package/src/modes/components/status-line/gh.ts +16 -0
  225. package/src/modes/components/tool-execution.ts +138 -27
  226. package/src/modes/components/tool-status-header.ts +3 -14
  227. package/src/modes/components/transcript-viewer-overlay.ts +99 -24
  228. package/src/modes/controllers/command-controller.ts +4 -0
  229. package/src/modes/controllers/event-controller.ts +109 -27
  230. package/src/modes/controllers/extension-ui-controller.ts +26 -2
  231. package/src/modes/controllers/input-controller.ts +18 -3
  232. package/src/modes/controllers/selector-controller.ts +127 -36
  233. package/src/modes/interactive-mode.ts +62 -3
  234. package/src/modes/irc-observation-ledger.ts +71 -15
  235. package/src/modes/runtime-init.ts +22 -2
  236. package/src/modes/types.ts +2 -0
  237. package/src/modes/utils/ui-helpers.ts +94 -1
  238. package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
  239. package/src/prompts/agents/architect.md +9 -1
  240. package/src/prompts/agents/critic.md +9 -0
  241. package/src/prompts/system/eager-todo.md +8 -4
  242. package/src/prompts/system/system-prompt.md +11 -5
  243. package/src/prompts/tools/bash.md +5 -5
  244. package/src/prompts/tools/read.md +4 -2
  245. package/src/prompts/tools/search-tool-bm25.md +5 -0
  246. package/src/prompts/tools/task.md +1 -1
  247. package/src/reminders/star-reminder.ts +4 -42
  248. package/src/runtime-mcp/manager.ts +19 -4
  249. package/src/runtime-mcp/smithery-auth.ts +17 -2
  250. package/src/runtime-mcp/smithery-connect.ts +11 -1
  251. package/src/sdk/acp/adapter.ts +22 -6
  252. package/src/sdk/broker/lifecycle.ts +25 -6
  253. package/src/sdk/broker/transport.ts +35 -3
  254. package/src/sdk/bus/attachment-registry.ts +5 -1
  255. package/src/sdk/bus/chat-daemon-cli.ts +4 -39
  256. package/src/sdk/bus/chat-daemon-control.ts +6 -3
  257. package/src/sdk/bus/config.ts +18 -2
  258. package/src/sdk/bus/control-drain-lease.ts +104 -0
  259. package/src/sdk/bus/index.ts +984 -146
  260. package/src/sdk/bus/kind-aware-reconciliation.ts +317 -0
  261. package/src/sdk/bus/lifecycle-commands.ts +4 -1
  262. package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
  263. package/src/sdk/bus/prompt-reconciliation.ts +2 -1
  264. package/src/sdk/bus/reconciliation-store.ts +303 -0
  265. package/src/sdk/bus/rich-draft.ts +1 -1
  266. package/src/sdk/bus/rich-render.ts +2 -2
  267. package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
  268. package/src/sdk/bus/telegram-cli.ts +33 -8
  269. package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
  270. package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
  271. package/src/sdk/bus/telegram-daemon.ts +916 -23
  272. package/src/sdk/bus/telegram-reference.ts +40 -3
  273. package/src/sdk/bus/threaded-render.ts +48 -3
  274. package/src/sdk/bus/topic-registry.ts +20 -0
  275. package/src/sdk/host/control/dispatch.ts +5 -1
  276. package/src/sdk/host/control/operations.ts +1 -1
  277. package/src/sdk/host/host.ts +23 -1
  278. package/src/sdk/host/query/handlers.ts +55 -0
  279. package/src/sdk/host/query/revision-store.ts +36 -2
  280. package/src/sdk/host/reverse-leases.ts +44 -7
  281. package/src/sdk/mcp/server.ts +46 -18
  282. package/src/sdk/prompt-status.ts +16 -3
  283. package/src/sdk/protocol/operation-inventory.generated.json +51 -0
  284. package/src/sdk/protocol/operation-registry.ts +7 -2
  285. package/src/sdk/session.ts +101 -10
  286. package/src/session/agent-session.ts +1286 -220
  287. package/src/session/artifacts.ts +22 -0
  288. package/src/session/auth-broker-config.ts +10 -3
  289. package/src/session/blob-store.ts +915 -24
  290. package/src/session/internal/managed-session-scope.ts +44 -6
  291. package/src/session/internal/managed-session-storage.ts +48 -6
  292. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  293. package/src/session/session-manager.ts +2364 -438
  294. package/src/session/session-storage.ts +9 -1
  295. package/src/session/streaming-output.ts +500 -111
  296. package/src/setup/credential-import.ts +75 -13
  297. package/src/setup/provider-onboarding.ts +19 -4
  298. package/src/skill-state/active-state.ts +32 -10
  299. package/src/skill-state/workflow-hud.ts +42 -2
  300. package/src/skill-state/workflow-mutation-guard.ts +560 -8
  301. package/src/task/executor.ts +122 -39
  302. package/src/task/index.ts +23 -14
  303. package/src/task/provider-retry-status.ts +16 -0
  304. package/src/task/receipt.ts +23 -7
  305. package/src/task/render.ts +6 -2
  306. package/src/task/types.ts +108 -0
  307. package/src/tools/ask-answer-registry.ts +12 -6
  308. package/src/tools/ask.ts +169 -118
  309. package/src/tools/ast-edit.ts +1 -0
  310. package/src/tools/ast-grep.ts +1 -0
  311. package/src/tools/bash-interactive.ts +8 -3
  312. package/src/tools/bash.ts +503 -60
  313. package/src/tools/browser/launch.ts +41 -6
  314. package/src/tools/fetch.ts +114 -23
  315. package/src/tools/find.ts +1 -0
  316. package/src/tools/image-gen.ts +29 -5
  317. package/src/tools/index.ts +4 -0
  318. package/src/tools/output-meta.ts +281 -20
  319. package/src/tools/path-utils.ts +8 -3
  320. package/src/tools/read-internals.ts +44 -0
  321. package/src/tools/read.ts +1560 -310
  322. package/src/tools/resource-gc.ts +182 -18
  323. package/src/tools/review.ts +5 -7
  324. package/src/tools/search.ts +1 -0
  325. package/src/tools/subagent-render.ts +6 -2
  326. package/src/tools/subagent.ts +6 -0
  327. package/src/tools/telegram-send.ts +6 -3
  328. package/src/tools/tool-result.ts +14 -1
  329. package/src/utils/gh.ts +39 -0
  330. package/src/utils/image-resize.ts +3 -0
  331. package/src/web/search/providers/anthropic.ts +4 -4
  332. package/src/web/search/providers/codex.ts +1 -1
  333. package/src/web/search/providers/kimi.ts +15 -5
  334. package/src/web/search/providers/searxng.ts +47 -4
  335. package/src/web/search/providers/xai.ts +7 -2
  336. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
  337. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
  338. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
  339. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
  340. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
  341. package/src/gjc-runtime/deep-interview-draft.ts +0 -843
  342. package/src/gjc-runtime/deep-interview-payload.ts +0 -262
  343. package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
  344. package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
@@ -0,0 +1,508 @@
1
+ import { Container, type SelectItem, SelectList, Spacer, Text } from "@gajae-code/tui";
2
+ import {
3
+ applyGjcBundleUpdate,
4
+ type GjcLifecycleContext,
5
+ getGjcBundle,
6
+ listGjcBundles,
7
+ previewGjcBundleUpdate,
8
+ setGjcBundleEnabled,
9
+ setGjcBundleSurfaceEnabled,
10
+ } from "../../extensibility/gjc-plugins/lifecycle";
11
+ import { identityEquals, identityKey } from "../../extensibility/gjc-plugins/lifecycle-reconciliation";
12
+ import { findingsForBundle, type GjcRuntimeSnapshotProvider } from "../../extensibility/gjc-plugins/runtime-quarantine";
13
+ import type {
14
+ GjcBundleIdentity,
15
+ GjcBundleSummary,
16
+ GjcLifecycleResult,
17
+ GjcReviewedUpdateToken,
18
+ GjcToggleResult,
19
+ GjcUpdateApplyResult,
20
+ GjcUpdatePreview,
21
+ } from "../../extensibility/gjc-plugins/types";
22
+ import { getSelectListTheme, theme } from "../../modes/theme/theme";
23
+ import { DynamicBorder } from "./dynamic-border";
24
+
25
+ /** Injectable lifecycle boundary; Settings never reads registries or executes bundle code. */
26
+ export interface GjcBundleLifecyclePort {
27
+ listGjcBundles(ctx: GjcLifecycleContext): Promise<GjcBundleSummary[]>;
28
+ getGjcBundle(ctx: GjcLifecycleContext, identity: GjcBundleIdentity): Promise<GjcLifecycleResult<GjcBundleSummary>>;
29
+ previewGjcBundleUpdate(
30
+ ctx: GjcLifecycleContext,
31
+ identity: GjcBundleIdentity,
32
+ ): Promise<GjcLifecycleResult<GjcUpdatePreview>>;
33
+ applyGjcBundleUpdate(
34
+ ctx: GjcLifecycleContext,
35
+ token: GjcReviewedUpdateToken,
36
+ ): Promise<GjcLifecycleResult<GjcUpdateApplyResult>>;
37
+ setGjcBundleEnabled(
38
+ ctx: GjcLifecycleContext,
39
+ identity: GjcBundleIdentity,
40
+ enabled: boolean,
41
+ ): Promise<GjcLifecycleResult<GjcToggleResult>>;
42
+ setGjcBundleSurfaceEnabled(
43
+ ctx: GjcLifecycleContext,
44
+ identity: GjcBundleIdentity,
45
+ surfaceId: string,
46
+ enabled: boolean,
47
+ ): Promise<GjcLifecycleResult<GjcToggleResult>>;
48
+ }
49
+
50
+ export interface GjcBundleSettingsDependencies {
51
+ lifecycle?: GjcBundleLifecyclePort;
52
+ runtimeSnapshotProvider?: GjcRuntimeSnapshotProvider;
53
+ activationGeneration?: number;
54
+ }
55
+
56
+ export interface GjcBundleSettingsCallbacks {
57
+ onClose: () => void;
58
+ onBundlesChanged?: () => void;
59
+ }
60
+
61
+ export type GjcBundleSettingsState =
62
+ | "loading"
63
+ | "error"
64
+ | "empty"
65
+ | "list"
66
+ | "detail"
67
+ | "unsupported-source"
68
+ | "update-review"
69
+ | "update-confirm"
70
+ | "update-running"
71
+ | "update-result"
72
+ | "stale-result"
73
+ | "quarantined-blocked"
74
+ | "mutation-in-flight-locked";
75
+
76
+ const PRODUCTION_LIFECYCLE: GjcBundleLifecyclePort = {
77
+ listGjcBundles,
78
+ getGjcBundle,
79
+ previewGjcBundleUpdate,
80
+ applyGjcBundleUpdate,
81
+ setGjcBundleEnabled,
82
+ setGjcBundleSurfaceEnabled,
83
+ };
84
+
85
+ /** Scope-qualified, lifecycle-backed Settings UI for installed GJC bundles. */
86
+ export class GjcBundleSettingsComponent extends Container {
87
+ #input: SelectList | null = null;
88
+ #bundles: GjcBundleSummary[] = [];
89
+ #focused: GjcBundleIdentity | null = null;
90
+ #preview: GjcUpdatePreview | null = null;
91
+ #state: GjcBundleSettingsState = "loading";
92
+ #message: string | null = null;
93
+ #navigationLocked = false;
94
+ #disposed = false;
95
+
96
+ constructor(
97
+ cwd: string,
98
+ private readonly callbacks: GjcBundleSettingsCallbacks,
99
+ private readonly dependencies: GjcBundleSettingsDependencies = {},
100
+ ) {
101
+ super();
102
+ this.#context = { cwd };
103
+ void this.#load();
104
+ }
105
+
106
+ readonly #context: GjcLifecycleContext;
107
+
108
+ get stateId(): GjcBundleSettingsState {
109
+ return this.#state;
110
+ }
111
+
112
+ get navigationLocked(): boolean {
113
+ return this.#navigationLocked;
114
+ }
115
+
116
+ get #lifecycle(): GjcBundleLifecyclePort {
117
+ return this.dependencies.lifecycle ?? PRODUCTION_LIFECYCLE;
118
+ }
119
+
120
+ async #load(): Promise<void> {
121
+ this.#state = "loading";
122
+ this.#message = null;
123
+ this.#render();
124
+ try {
125
+ this.#bundles = await this.#lifecycle.listGjcBundles(this.#context);
126
+ if (this.#disposed) return;
127
+ this.#state = this.#bundles.length === 0 ? "empty" : "list";
128
+ } catch {
129
+ if (this.#disposed) return;
130
+ this.#state = "error";
131
+ this.#message = "Unable to load GJC bundles.";
132
+ }
133
+ this.#render();
134
+ }
135
+
136
+ #render(): void {
137
+ if (this.#disposed) return;
138
+ this.clear();
139
+ this.#input = null;
140
+ this.addChild(new DynamicBorder());
141
+ this.addChild(new Text(theme.bold(theme.fg("accent", " GJC Bundles")), 0, 0));
142
+ this.addChild(new Spacer(1));
143
+ switch (this.#state) {
144
+ case "loading":
145
+ this.addChild(new Text(theme.fg("muted", " Loading installed bundles…"), 0, 0));
146
+ this.#renderActionList([]);
147
+ break;
148
+ case "error":
149
+ this.#renderActionList([
150
+ { value: "retry", label: "Retry", description: this.#message ?? "Unable to load GJC bundles." },
151
+ ]);
152
+ break;
153
+ case "empty":
154
+ this.addChild(new Text(theme.fg("muted", " No GJC bundles installed"), 0, 0));
155
+ this.#renderActionList([]);
156
+ break;
157
+ case "list":
158
+ this.#renderList();
159
+ break;
160
+ case "detail":
161
+ case "unsupported-source":
162
+ case "quarantined-blocked":
163
+ case "update-result":
164
+ case "stale-result":
165
+ this.#renderDetail();
166
+ break;
167
+ case "update-review":
168
+ case "update-confirm":
169
+ this.#renderUpdateReview();
170
+ break;
171
+ case "update-running":
172
+ case "mutation-in-flight-locked":
173
+ this.addChild(new Text(theme.fg("muted", " Applying non-cancellable bundle change…"), 0, 0));
174
+ break;
175
+ }
176
+ this.addChild(new Spacer(1));
177
+ this.addChild(
178
+ new Text(
179
+ theme.fg(
180
+ "dim",
181
+ this.#navigationLocked
182
+ ? " Navigation locked while mutation runs"
183
+ : " Enter to select · Esc to go back",
184
+ ),
185
+ 0,
186
+ 0,
187
+ ),
188
+ );
189
+ this.addChild(new DynamicBorder());
190
+ }
191
+
192
+ #renderList(): void {
193
+ const items: SelectItem[] = this.#bundles.map(bundle => {
194
+ const runtime = findingsForBundle(
195
+ this.dependencies.runtimeSnapshotProvider,
196
+ bundle.identity,
197
+ this.dependencies.activationGeneration ?? 0,
198
+ );
199
+ const intent = bundle.enabled ? "enabled" : "disabled";
200
+ const quarantine = bundle.quarantined ? " · quarantined" : "";
201
+ const effective =
202
+ runtime.status === "unavailable"
203
+ ? "runtime unavailable"
204
+ : runtime.findings.length > 0
205
+ ? "runtime findings"
206
+ : "runtime current";
207
+ return {
208
+ value: identityKey(bundle.identity),
209
+ label: `${bundle.identity.name} (${bundle.identity.scope})`,
210
+ description: `v${bundle.version} · ${intent}${quarantine} · ${effective}`,
211
+ };
212
+ });
213
+ this.#renderActionList(items);
214
+ }
215
+
216
+ #renderDetail(): void {
217
+ const bundle = this.#bundleForFocus();
218
+ if (!bundle) {
219
+ this.#state = "list";
220
+ this.#render();
221
+ return;
222
+ }
223
+ this.addChild(
224
+ new Text(theme.fg("muted", ` ${bundle.identity.name} (${bundle.identity.scope}) · v${bundle.version}`), 0, 0),
225
+ );
226
+ if (bundle.description) this.addChild(new Text(theme.fg("muted", ` ${bundle.description}`), 0, 0));
227
+ this.addChild(new Text(theme.fg("dim", ` Source: ${bundle.source.display}`), 0, 0));
228
+ if (bundle.source.ref) this.addChild(new Text(theme.fg("dim", ` Ref: ${bundle.source.ref}`), 0, 0));
229
+ if (bundle.source.sha) this.addChild(new Text(theme.fg("dim", ` SHA: ${bundle.source.sha}`), 0, 0));
230
+ this.addChild(
231
+ new Text(theme.fg("dim", ` Installed: ${bundle.installedAt} · Updated: ${bundle.updatedAt}`), 0, 0),
232
+ );
233
+ if (!bundle.source.updatable) {
234
+ this.addChild(
235
+ new Text(
236
+ theme.fg(
237
+ "warning",
238
+ ` Update unsupported: ${bundle.source.unsupportedReason ?? "This source cannot be refreshed."}`,
239
+ ),
240
+ 0,
241
+ 0,
242
+ ),
243
+ );
244
+ }
245
+ if (this.#message) this.addChild(new Text(theme.fg("warning", ` ${this.#message}`), 0, 0));
246
+ const actions: SelectItem[] = [];
247
+ if (bundle.enabled || !bundle.quarantined) {
248
+ actions.push({
249
+ value: `bundle:${bundle.enabled ? "disable" : "enable"}`,
250
+ label: bundle.enabled ? "Disable bundle" : "Enable bundle",
251
+ });
252
+ } else {
253
+ actions.push({
254
+ value: "bundle:blocked",
255
+ label: "Enable bundle (blocked)",
256
+ description: "Quarantined bundles cannot be enabled.",
257
+ });
258
+ }
259
+ if (bundle.source.updatable) actions.push({ value: "update", label: "Review update" });
260
+ for (const surface of bundle.surfaces) {
261
+ const action = surface.enabled ? "disable" : surface.quarantined ? "blocked" : "enable";
262
+ actions.push({
263
+ value: `surface:${surface.extensionId}:${action}`,
264
+ label: `${surface.name} (${surface.kind})`,
265
+ description: `${surface.enabled ? "enabled" : "disabled"}${surface.quarantined ? " · quarantined" : ""}`,
266
+ });
267
+ }
268
+ this.#renderActionList(actions);
269
+ }
270
+
271
+ #renderUpdateReview(): void {
272
+ const preview = this.#preview;
273
+ if (!preview) return;
274
+ this.addChild(new Text(theme.fg("muted", ` ${preview.identity.name} (${preview.identity.scope})`), 0, 0));
275
+ this.addChild(new Text(theme.fg("muted", ` v${preview.current.version} → v${preview.candidateVersion}`), 0, 0));
276
+ this.addChild(
277
+ new Text(
278
+ theme.fg(
279
+ "dim",
280
+ ` Surfaces: +${preview.addedSurfaceIds.length} −${preview.removedSurfaceIds.length} =${preview.retainedSurfaceIds.length}`,
281
+ ),
282
+ 0,
283
+ 0,
284
+ ),
285
+ );
286
+ if (!preview.changed) this.addChild(new Text(theme.fg("muted", " No update changes were found."), 0, 0));
287
+ this.#renderActionList([
288
+ this.#state === "update-review"
289
+ ? { value: "continue-update", label: "Continue to confirmation" }
290
+ : { value: "apply-update", label: "Apply update", description: "This operation cannot be cancelled." },
291
+ ]);
292
+ }
293
+
294
+ #renderActionList(items: SelectItem[]): void {
295
+ this.#input = new SelectList(items, Math.min(Math.max(items.length, 1), 12), getSelectListTheme());
296
+ this.#input.onSelect = item => this.#select(item.value);
297
+ this.#input.onCancel = () => this.#back();
298
+ this.addChild(this.#input);
299
+ }
300
+
301
+ #select(value: string): void {
302
+ if (this.#navigationLocked) return;
303
+ if (value === "retry") {
304
+ void this.#load();
305
+ return;
306
+ }
307
+ if (this.#state === "list") {
308
+ const bundle = this.#bundles.find(candidate => identityKey(candidate.identity) === value);
309
+ if (bundle) {
310
+ this.#focused = bundle.identity;
311
+ this.#state = bundle.source.updatable ? "detail" : "unsupported-source";
312
+ this.#render();
313
+ }
314
+ return;
315
+ }
316
+ if (value === "update") {
317
+ void this.#reviewUpdate();
318
+ return;
319
+ }
320
+ if (value === "continue-update") {
321
+ this.#state = "update-confirm";
322
+ this.#render();
323
+ return;
324
+ }
325
+ if (value === "apply-update") {
326
+ void this.#applyUpdate();
327
+ return;
328
+ }
329
+ if (value === "bundle:blocked" || value.endsWith(":blocked")) {
330
+ this.#state = "quarantined-blocked";
331
+ this.#message = "quarantined: enable is blocked; disable remains available.";
332
+ this.#render();
333
+ return;
334
+ }
335
+ if (value.startsWith("bundle:")) {
336
+ void this.#toggleBundle(value === "bundle:enable");
337
+ return;
338
+ }
339
+ if (value.startsWith("surface:")) {
340
+ const encoded = value.slice("surface:".length);
341
+ const separator = encoded.lastIndexOf(":");
342
+ const surfaceId = encoded.slice(0, separator);
343
+ const action = encoded.slice(separator + 1);
344
+ if (separator > 0 && surfaceId && action) void this.#toggleSurface(surfaceId, action === "enable");
345
+ }
346
+ }
347
+
348
+ async #reviewUpdate(): Promise<void> {
349
+ const bundle = this.#bundleForFocus();
350
+ if (!bundle) return;
351
+ this.#message = null;
352
+ try {
353
+ const result = await this.#lifecycle.previewGjcBundleUpdate(this.#context, bundle.identity);
354
+ if (this.#disposed || !this.#isFocused(bundle.identity)) return;
355
+ if (!result.ok) {
356
+ this.#state = result.error.code === "source_unsupported" ? "unsupported-source" : "detail";
357
+ this.#message = result.error.message;
358
+ } else {
359
+ this.#preview = result.value;
360
+ this.#state = "update-review";
361
+ }
362
+ } catch {
363
+ if (this.#disposed || !this.#isFocused(bundle.identity)) return;
364
+ this.#state = "detail";
365
+ this.#message = "Unable to review this update.";
366
+ }
367
+ this.#render();
368
+ }
369
+
370
+ async #applyUpdate(): Promise<void> {
371
+ const preview = this.#preview;
372
+ if (!preview) return;
373
+ await this.#mutate(preview.identity, "update-running", async () => {
374
+ const result = await this.#lifecycle.applyGjcBundleUpdate(this.#context, preview.token);
375
+ if (this.#disposed || !this.#isFocused(preview.identity)) return;
376
+ if (!result.ok) {
377
+ if (result.error.code.startsWith("stale_")) {
378
+ this.#state = "stale-result";
379
+ this.#message = `${result.error.message} Re-review the update.`;
380
+ } else {
381
+ this.#state = "detail";
382
+ this.#message = result.error.message;
383
+ }
384
+ return;
385
+ }
386
+ this.#replaceSummary(result.value.summary);
387
+ this.#state = "update-result";
388
+ this.#message = result.value.status === "updated" ? "Update applied." : "Already up to date.";
389
+ this.callbacks.onBundlesChanged?.();
390
+ });
391
+ }
392
+
393
+ async #toggleBundle(enabled: boolean): Promise<void> {
394
+ const bundle = this.#bundleForFocus();
395
+ if (!bundle) return;
396
+ if (enabled && bundle.quarantined) {
397
+ this.#state = "quarantined-blocked";
398
+ this.#message = "quarantined: enable is blocked; disable remains available.";
399
+ this.#render();
400
+ return;
401
+ }
402
+ await this.#mutate(bundle.identity, "mutation-in-flight-locked", async () => {
403
+ const result = await this.#lifecycle.setGjcBundleEnabled(this.#context, bundle.identity, enabled);
404
+ if (this.#disposed || !this.#isFocused(bundle.identity)) return;
405
+ this.#applyToggleResult(result);
406
+ });
407
+ }
408
+
409
+ async #toggleSurface(surfaceId: string, enabled: boolean): Promise<void> {
410
+ const bundle = this.#bundleForFocus();
411
+ if (!bundle) return;
412
+ const surface = bundle.surfaces.find(candidate => candidate.extensionId === surfaceId);
413
+ if (enabled && surface?.quarantined) {
414
+ this.#state = "quarantined-blocked";
415
+ this.#message = "quarantined: enable is blocked; disable remains available.";
416
+ this.#render();
417
+ return;
418
+ }
419
+ await this.#mutate(bundle.identity, "mutation-in-flight-locked", async () => {
420
+ const result = await this.#lifecycle.setGjcBundleSurfaceEnabled(
421
+ this.#context,
422
+ bundle.identity,
423
+ surfaceId,
424
+ enabled,
425
+ );
426
+ if (this.#disposed || !this.#isFocused(bundle.identity)) return;
427
+ this.#applyToggleResult(result);
428
+ });
429
+ }
430
+
431
+ #applyToggleResult(result: GjcLifecycleResult<GjcToggleResult>): void {
432
+ if (!result.ok) {
433
+ this.#state = result.error.code === "quarantined" ? "quarantined-blocked" : "detail";
434
+ this.#message = result.error.message;
435
+ return;
436
+ }
437
+ this.#replaceSummary(result.value.summary);
438
+ this.#state = "detail";
439
+ this.#message = null;
440
+ this.callbacks.onBundlesChanged?.();
441
+ }
442
+
443
+ async #mutate(
444
+ identity: GjcBundleIdentity,
445
+ runningState: "update-running" | "mutation-in-flight-locked",
446
+ operation: () => Promise<void>,
447
+ ): Promise<void> {
448
+ if (this.#navigationLocked) return;
449
+ this.#navigationLocked = true;
450
+ this.#state = runningState;
451
+ this.#render();
452
+ try {
453
+ await operation();
454
+ } catch {
455
+ if (!this.#disposed && this.#isFocused(identity)) {
456
+ this.#state = "detail";
457
+ this.#message = "Unable to apply this bundle change.";
458
+ }
459
+ } finally {
460
+ if (!this.#disposed) {
461
+ this.#navigationLocked = false;
462
+ if (this.#isFocused(identity)) this.#render();
463
+ }
464
+ }
465
+ }
466
+
467
+ #replaceSummary(summary: GjcBundleSummary): void {
468
+ const index = this.#bundles.findIndex(bundle => identityEquals(bundle.identity, summary.identity));
469
+ if (index >= 0) this.#bundles[index] = summary;
470
+ }
471
+
472
+ #bundleForFocus(): GjcBundleSummary | undefined {
473
+ return this.#focused ? this.#bundles.find(bundle => identityEquals(bundle.identity, this.#focused!)) : undefined;
474
+ }
475
+
476
+ #isFocused(identity: GjcBundleIdentity): boolean {
477
+ return this.#focused !== null && identityEquals(this.#focused, identity);
478
+ }
479
+
480
+ #back(): void {
481
+ if (this.#navigationLocked) return;
482
+ if (this.#state === "list" || this.#state === "empty" || this.#state === "error") {
483
+ this.callbacks.onClose();
484
+ return;
485
+ }
486
+ if (this.#state === "update-review" || this.#state === "update-confirm") {
487
+ this.#state = "detail";
488
+ this.#preview = null;
489
+ } else {
490
+ this.#focused = null;
491
+ this.#preview = null;
492
+ this.#message = null;
493
+ this.#state = this.#bundles.length === 0 ? "empty" : "list";
494
+ }
495
+ this.#render();
496
+ }
497
+
498
+ override dispose(): void {
499
+ this.#disposed = true;
500
+ this.#input = null;
501
+ super.dispose();
502
+ }
503
+
504
+ handleInput(data: string): void {
505
+ if (this.#navigationLocked) return;
506
+ this.#input?.handleInput(data);
507
+ }
508
+ }