@sayknow-cli/coding-agent 0.4.6 → 0.5.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 (428) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/dist/types/capability/index.d.ts +10 -20
  3. package/dist/types/capability/types.d.ts +3 -0
  4. package/dist/types/cli/args.d.ts +0 -2
  5. package/dist/types/cli/read-cli.d.ts +1 -0
  6. package/dist/types/cli.d.ts +9 -1
  7. package/dist/types/commands/daemon.d.ts +2 -2
  8. package/dist/types/commands/deep-interview.d.ts +9 -0
  9. package/dist/types/commands/harness.d.ts +22 -0
  10. package/dist/types/commands/read.d.ts +6 -0
  11. package/dist/types/commands/sdk.d.ts +20 -2
  12. package/dist/types/config/keybindings.d.ts +34 -4
  13. package/dist/types/config/model-profile-contract.d.ts +40 -0
  14. package/dist/types/config/model-profiles.d.ts +2 -3
  15. package/dist/types/config/model-registry.d.ts +5 -0
  16. package/dist/types/config/provider-auth-health.d.ts +14 -0
  17. package/dist/types/config/provider-ranking.d.ts +59 -0
  18. package/dist/types/config/settings-schema.d.ts +156 -10
  19. package/dist/types/config/settings.d.ts +3 -0
  20. package/dist/types/edit/modes/patch.d.ts +13 -0
  21. package/dist/types/edit/path-mutation-lock.d.ts +15 -0
  22. package/dist/types/eval/py/executor.d.ts +1 -1
  23. package/dist/types/eval/py/runner-artifact.d.ts +8 -0
  24. package/dist/types/eval/py/tool-bridge.d.ts +1 -2
  25. package/dist/types/extensibility/extensions/types.d.ts +43 -2
  26. package/dist/types/extensibility/shared-events.d.ts +6 -0
  27. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  28. package/dist/types/main.d.ts +33 -2
  29. package/dist/types/memories/index.d.ts +2 -0
  30. package/dist/types/modes/acp/acp-agent.d.ts +22 -9
  31. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  32. package/dist/types/modes/components/btw-panel.d.ts +1 -0
  33. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  34. package/dist/types/modes/components/queue-pane.d.ts +8 -0
  35. package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
  36. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  37. package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
  38. package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
  39. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  40. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  41. package/dist/types/modes/components/tool-status-header.d.ts +4 -2
  42. package/dist/types/modes/components/welcome.d.ts +5 -0
  43. package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
  44. package/dist/types/modes/controllers/command-controller.d.ts +2 -0
  45. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  46. package/dist/types/modes/interactive-mode.d.ts +13 -2
  47. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  48. package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
  49. package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
  50. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
  51. package/dist/types/modes/types.d.ts +6 -0
  52. package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
  53. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  54. package/dist/types/runtime/memory-domain.d.ts +9 -0
  55. package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
  56. package/dist/types/runtime/memory-guard.d.ts +39 -0
  57. package/dist/types/runtime/memory-limit.d.ts +11 -0
  58. package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
  59. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +1 -1
  60. package/dist/types/runtime-mcp/manager.d.ts +9 -1
  61. package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
  62. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
  63. package/dist/types/runtime-mcp/redaction.d.ts +2 -0
  64. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  65. package/dist/types/sdk/acp/final-text.d.ts +19 -0
  66. package/dist/types/sdk/acp/mcp.d.ts +23 -0
  67. package/dist/types/sdk/broker/broker.d.ts +2 -0
  68. package/dist/types/sdk/broker/lifecycle.d.ts +13 -0
  69. package/dist/types/sdk/bus/chat-daemon-control.d.ts +9 -1
  70. package/dist/types/sdk/bus/config-commands.d.ts +2 -2
  71. package/dist/types/sdk/bus/config.d.ts +2 -0
  72. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  73. package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
  74. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  75. package/dist/types/sdk/bus/index.d.ts +52 -4
  76. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
  77. package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
  78. package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
  79. package/dist/types/sdk/bus/notification-service.d.ts +34 -0
  80. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
  81. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +106 -0
  82. package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
  83. package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
  84. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +33 -9
  85. package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
  86. package/dist/types/sdk/bus/telegram-daemon.d.ts +286 -12
  87. package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
  88. package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
  89. package/dist/types/sdk/client/discovery.d.ts +2 -0
  90. package/dist/types/sdk/client/liveness.d.ts +7 -0
  91. package/dist/types/sdk/host/control/operations.d.ts +3 -2
  92. package/dist/types/sdk/host/host.d.ts +3 -1
  93. package/dist/types/sdk/host/query/handlers.d.ts +14 -0
  94. package/dist/types/sdk/index.d.ts +2 -0
  95. package/dist/types/sdk/lifecycle-session.d.ts +10 -1
  96. package/dist/types/sdk/prompt-status.d.ts +88 -0
  97. package/dist/types/sdk/session-directory.d.ts +1 -1
  98. package/dist/types/sdk/session.d.ts +7 -0
  99. package/dist/types/sdk/startup-capability.d.ts +9 -0
  100. package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
  101. package/dist/types/sdk/transport/index.d.ts +12 -0
  102. package/dist/types/sdk/transport/relay.d.ts +43 -0
  103. package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
  104. package/dist/types/sdk/transport/socket.d.ts +7 -0
  105. package/dist/types/sdk/transport/stdio.d.ts +3 -0
  106. package/dist/types/session/agent-session.d.ts +83 -24
  107. package/dist/types/session/btw-contract.d.ts +16 -0
  108. package/dist/types/session/fallback-chain-controller.d.ts +18 -2
  109. package/dist/types/session/internal/managed-session-scope.d.ts +70 -10
  110. package/dist/types/session/internal/managed-session-storage.d.ts +34 -12
  111. package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
  112. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  113. package/dist/types/session/session-manager.d.ts +89 -18
  114. package/dist/types/session/session-storage.d.ts +31 -0
  115. package/dist/types/session/streaming-output.d.ts +60 -5
  116. package/dist/types/setup/credential-import.d.ts +5 -1
  117. package/dist/types/setup/provider-onboarding.d.ts +2 -0
  118. package/dist/types/skc-runtime/deep-interview-runtime.d.ts +1 -1
  119. package/dist/types/skc-runtime/deep-interview-stage.d.ts +37 -0
  120. package/dist/types/skc-runtime/gc-runtime.d.ts +1 -1
  121. package/dist/types/skc-runtime/linux-proc.d.ts +22 -14
  122. package/dist/types/skc-runtime/memory-guard-owner-claims.d.ts +47 -0
  123. package/dist/types/skc-runtime/ralplan-runtime.d.ts +112 -1
  124. package/dist/types/skc-runtime/repository-binding.d.ts +63 -0
  125. package/dist/types/skc-runtime/state-runtime.d.ts +3 -1
  126. package/dist/types/skc-runtime/state-writer.d.ts +5 -1
  127. package/dist/types/skc-runtime/team-launch.d.ts +1 -1
  128. package/dist/types/skc-runtime/team-runtime.d.ts +9 -2
  129. package/dist/types/skc-runtime/team-store.d.ts +12 -0
  130. package/dist/types/skc-runtime/team-worker-memory-guard.d.ts +92 -0
  131. package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +7 -0
  132. package/dist/types/skc-runtime/ultragoal-guard.d.ts +6 -5
  133. package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +28 -0
  134. package/dist/types/skc-runtime/ultragoal-runtime.d.ts +43 -5
  135. package/dist/types/skill-state/workflow-hud.d.ts +3 -0
  136. package/dist/types/ssh/utils.d.ts +1 -0
  137. package/dist/types/task/discovery.d.ts +3 -1
  138. package/dist/types/task/executor.d.ts +6 -0
  139. package/dist/types/task/index.d.ts +3 -1
  140. package/dist/types/task/provider-retry-status.d.ts +13 -0
  141. package/dist/types/task/receipt.d.ts +2 -0
  142. package/dist/types/task/types.d.ts +133 -0
  143. package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
  144. package/dist/types/tools/browser/launch.d.ts +7 -0
  145. package/dist/types/tools/fetch.d.ts +22 -9
  146. package/dist/types/tools/image-gen.d.ts +63 -1
  147. package/dist/types/tools/index.d.ts +7 -1
  148. package/dist/types/tools/output-meta.d.ts +21 -1
  149. package/dist/types/tools/read-internals.d.ts +12 -0
  150. package/dist/types/tools/read.d.ts +45 -1
  151. package/dist/types/tools/resource-gc.d.ts +23 -0
  152. package/dist/types/tools/skill-discovery.d.ts +7 -0
  153. package/dist/types/tools/sqlite-reader.d.ts +7 -0
  154. package/dist/types/tools/tool-result.d.ts +7 -1
  155. package/dist/types/utils/prompt-suggestion.d.ts +33 -0
  156. package/dist/types/utils/shell-snapshot.d.ts +12 -0
  157. package/dist/types/web/insane/bridge.d.ts +1 -0
  158. package/dist/types/web/insane/url-guard.d.ts +17 -0
  159. package/package.json +8 -12
  160. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  161. package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
  162. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  163. package/scripts/compile-args.ts +0 -1
  164. package/scripts/dogfood-repository-binding.ts +209 -0
  165. package/scripts/generate-docs-index.ts +4 -1
  166. package/scripts/generate-sdk-operation-inventory.ts +9 -0
  167. package/scripts/run-test-manifest.ts +6 -4
  168. package/scripts/verify-skc-sdk-canonicalization.ts +122 -18
  169. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  170. package/src/capability/index.ts +58 -42
  171. package/src/capability/types.ts +3 -0
  172. package/src/cli/args.ts +16 -100
  173. package/src/cli/fast-help.ts +1 -1
  174. package/src/cli/mcp-cli.ts +4 -21
  175. package/src/cli/notify-cli.ts +6 -38
  176. package/src/cli/read-cli.ts +2 -1
  177. package/src/cli/setup-cli.ts +10 -4
  178. package/src/cli.ts +133 -11
  179. package/src/commands/daemon.ts +22 -5
  180. package/src/commands/deep-interview.ts +26 -1
  181. package/src/commands/harness.ts +35 -12
  182. package/src/commands/read.ts +11 -2
  183. package/src/commands/sdk.ts +134 -17
  184. package/src/commands/team.ts +1 -1
  185. package/src/commit/agentic/index.ts +3 -3
  186. package/src/commit/map-reduce/index.ts +2 -2
  187. package/src/config/keybindings.ts +158 -25
  188. package/src/config/model-profile-contract.ts +174 -0
  189. package/src/config/model-profiles.ts +51 -10
  190. package/src/config/model-registry.ts +24 -4
  191. package/src/config/model-resolver.ts +2 -2
  192. package/src/config/provider-auth-health.ts +42 -0
  193. package/src/config/provider-ranking.ts +119 -0
  194. package/src/config/settings-schema.ts +157 -10
  195. package/src/config/settings.ts +254 -108
  196. package/src/coordinator-mcp/model-preset.ts +21 -74
  197. package/src/defaults/skc/skills/deep-interview/SKILL.md +147 -24
  198. package/src/defaults/skc/skills/ralplan/SKILL.md +91 -34
  199. package/src/defaults/skc/skills/team/SKILL.md +1 -1
  200. package/src/defaults/skc/skills/ultragoal/SKILL.md +68 -17
  201. package/src/discovery/ssh.ts +12 -1
  202. package/src/edit/index.ts +3 -6
  203. package/src/edit/modes/patch.ts +38 -1
  204. package/src/edit/modes/replace.ts +42 -0
  205. package/src/edit/path-mutation-lock.ts +112 -0
  206. package/src/eval/js/tool-bridge.ts +1 -1
  207. package/src/eval/py/executor.ts +37 -13
  208. package/src/eval/py/kernel.ts +1 -21
  209. package/src/eval/py/prelude.py +2 -2
  210. package/src/eval/py/runner-artifact.ts +84 -0
  211. package/src/eval/py/tool-bridge.ts +34 -18
  212. package/src/extensibility/extensions/runner.ts +4 -0
  213. package/src/extensibility/extensions/types.ts +42 -4
  214. package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
  215. package/src/extensibility/shared-events.ts +5 -0
  216. package/src/extensibility/skc-plugins/runtime-adapters.ts +2 -1
  217. package/src/hooks/native-skill-hook.ts +17 -4
  218. package/src/internal-urls/docs-index.generated.ts +17 -16
  219. package/src/internal-urls/local-protocol.ts +87 -25
  220. package/src/internal-urls/local-root-gc.ts +127 -0
  221. package/src/internal-urls/mcp-protocol.ts +73 -11
  222. package/src/main.ts +120 -42
  223. package/src/memories/index.ts +10 -0
  224. package/src/modes/DESIGN.md +52 -0
  225. package/src/modes/acp/acp-agent.ts +647 -83
  226. package/src/modes/acp/acp-event-mapper.ts +106 -12
  227. package/src/modes/acp/acp-mode.ts +39 -3
  228. package/src/modes/action-registry.ts +1 -1
  229. package/src/modes/components/assistant-message.ts +123 -22
  230. package/src/modes/components/btw-panel.ts +82 -16
  231. package/src/modes/components/irc-sidebar.ts +176 -62
  232. package/src/modes/components/model-selector.ts +61 -4
  233. package/src/modes/components/notifications-settings-editor.ts +1 -1
  234. package/src/modes/components/oauth-selector.ts +42 -12
  235. package/src/modes/components/plan-preview-overlay.ts +1 -1
  236. package/src/modes/components/queue-pane.ts +55 -9
  237. package/src/modes/components/queued-message-selector.ts +53 -10
  238. package/src/modes/components/read-tool-group.ts +82 -14
  239. package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
  240. package/src/modes/components/sayknow-pet-widget.ts +27 -8
  241. package/src/modes/components/session-observer-overlay.ts +187 -32
  242. package/src/modes/components/settings-selector.ts +60 -18
  243. package/src/modes/components/tool-execution.ts +138 -27
  244. package/src/modes/components/tool-status-header.ts +26 -8
  245. package/src/modes/components/welcome.ts +50 -23
  246. package/src/modes/controllers/btw-controller.ts +119 -36
  247. package/src/modes/controllers/command-controller.ts +101 -54
  248. package/src/modes/controllers/event-controller.ts +119 -27
  249. package/src/modes/controllers/extension-ui-controller.ts +23 -12
  250. package/src/modes/controllers/input-controller.ts +100 -8
  251. package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
  252. package/src/modes/controllers/selector-controller.ts +4 -1
  253. package/src/modes/interactive-mode.ts +201 -60
  254. package/src/modes/irc-observation-ledger.ts +71 -15
  255. package/src/modes/prompt-action-autocomplete.ts +32 -13
  256. package/src/modes/prompt-suggestion-controller.ts +96 -0
  257. package/src/modes/runtime-init.ts +20 -2
  258. package/src/modes/shared/agent-wire/command-dispatch.ts +3 -3
  259. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
  260. package/src/modes/types.ts +6 -0
  261. package/src/modes/utils/hotkeys-markdown.ts +64 -36
  262. package/src/modes/utils/ui-helpers.ts +99 -4
  263. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  264. package/src/prompts/agents/architect.md +17 -3
  265. package/src/prompts/agents/critic.md +17 -2
  266. package/src/prompts/agents/executor.md +1 -1
  267. package/src/prompts/agents/planner.md +8 -1
  268. package/src/prompts/system/btw-user.md +3 -8
  269. package/src/prompts/system/prompt-suggestion-system.md +32 -0
  270. package/src/prompts/system/system-prompt.md +6 -3
  271. package/src/prompts/tools/cron.md +3 -1
  272. package/src/prompts/tools/read.md +4 -2
  273. package/src/prompts/tools/skill-discovery.md +1 -0
  274. package/src/runtime/memory-domain.ts +66 -0
  275. package/src/runtime/memory-guard-contract.ts +73 -0
  276. package/src/runtime/memory-guard.ts +292 -0
  277. package/src/runtime/memory-limit.ts +50 -0
  278. package/src/runtime-mcp/client.ts +41 -55
  279. package/src/runtime-mcp/content-limits.ts +71 -0
  280. package/src/runtime-mcp/discoverable-tool-metadata.ts +1 -1
  281. package/src/runtime-mcp/json-rpc.ts +28 -11
  282. package/src/runtime-mcp/manager.ts +77 -59
  283. package/src/runtime-mcp/oauth-flow.ts +0 -72
  284. package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
  285. package/src/runtime-mcp/redaction.ts +30 -0
  286. package/src/runtime-mcp/smithery-auth.ts +17 -2
  287. package/src/runtime-mcp/smithery-connect.ts +11 -1
  288. package/src/runtime-mcp/transports/http.ts +63 -22
  289. package/src/sdk/acp/adapter.ts +8 -1
  290. package/src/sdk/acp/final-text.ts +40 -0
  291. package/src/sdk/acp/mcp.ts +26 -0
  292. package/src/sdk/broker/broker.ts +34 -20
  293. package/src/sdk/broker/identity.ts +22 -12
  294. package/src/sdk/broker/lifecycle.ts +293 -43
  295. package/src/sdk/broker/session-index.ts +11 -1
  296. package/src/sdk/bus/chat-daemon-cli.ts +2 -2
  297. package/src/sdk/bus/chat-daemon-control.ts +22 -5
  298. package/src/sdk/bus/config-commands.ts +2 -2
  299. package/src/sdk/bus/config.ts +10 -2
  300. package/src/sdk/bus/control-drain-lease.ts +104 -0
  301. package/src/sdk/bus/conversation-store.ts +40 -6
  302. package/src/sdk/bus/daemon-paths.ts +2 -0
  303. package/src/sdk/bus/index.ts +793 -121
  304. package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
  305. package/src/sdk/bus/lifecycle-commands.ts +63 -10
  306. package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
  307. package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
  308. package/src/sdk/bus/notification-orchestration.ts +12 -0
  309. package/src/sdk/bus/notification-service.ts +87 -25
  310. package/src/sdk/bus/operator-runtime.ts +31 -5
  311. package/src/sdk/bus/prompt-reconciliation.ts +240 -0
  312. package/src/sdk/bus/rate-limit-pool.ts +8 -0
  313. package/src/sdk/bus/recent-activity.ts +90 -26
  314. package/src/sdk/bus/reconciliation-store.ts +224 -0
  315. package/src/sdk/bus/telegram-cli.ts +6 -13
  316. package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
  317. package/src/sdk/bus/telegram-daemon-contract.ts +34 -9
  318. package/src/sdk/bus/telegram-daemon-control.ts +161 -40
  319. package/src/sdk/bus/telegram-daemon.ts +3649 -593
  320. package/src/sdk/bus/telegram-reference.ts +20 -2
  321. package/src/sdk/bus/topic-registry.ts +451 -12
  322. package/src/sdk/cli/session-cli.ts +15 -2
  323. package/src/sdk/client/discovery.ts +19 -3
  324. package/src/sdk/client/liveness.ts +49 -0
  325. package/src/sdk/host/control/dispatch.ts +8 -2
  326. package/src/sdk/host/control/operations.ts +3 -2
  327. package/src/sdk/host/host.ts +27 -9
  328. package/src/sdk/host/query/handlers.ts +125 -5
  329. package/src/sdk/index.ts +12 -0
  330. package/src/sdk/lifecycle-session.ts +19 -3
  331. package/src/sdk/mcp/server.ts +46 -18
  332. package/src/sdk/prompt-status.ts +97 -0
  333. package/src/sdk/protocol/operation-inventory.generated.json +145 -0
  334. package/src/sdk/protocol/operation-registry.ts +24 -4
  335. package/src/sdk/session-directory.ts +5 -1
  336. package/src/sdk/session.ts +69 -8
  337. package/src/sdk/startup-capability.ts +15 -1
  338. package/src/sdk/transport/auth-preface.ts +82 -0
  339. package/src/sdk/transport/index.ts +18 -0
  340. package/src/sdk/transport/relay.ts +252 -0
  341. package/src/sdk/transport/serve-cli.ts +105 -0
  342. package/src/sdk/transport/socket.ts +197 -0
  343. package/src/sdk/transport/stdio.ts +17 -0
  344. package/src/session/agent-session.ts +1112 -314
  345. package/src/session/blob-store.ts +25 -7
  346. package/src/session/btw-contract.ts +59 -0
  347. package/src/session/fallback-chain-controller.ts +47 -8
  348. package/src/session/internal/managed-session-scope.ts +1426 -259
  349. package/src/session/internal/managed-session-storage.ts +414 -238
  350. package/src/session/internal/native-publish-outcome.ts +271 -0
  351. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  352. package/src/session/session-manager.ts +2079 -469
  353. package/src/session/session-storage.ts +151 -11
  354. package/src/session/streaming-output.ts +262 -43
  355. package/src/setup/credential-import.ts +28 -3
  356. package/src/setup/provider-onboarding.ts +49 -5
  357. package/src/setup/provider-presets.json +2 -1
  358. package/src/skc-runtime/deep-interview-runtime.ts +303 -36
  359. package/src/skc-runtime/deep-interview-stage.ts +1016 -0
  360. package/src/skc-runtime/deep-interview-state.ts +8 -5
  361. package/src/skc-runtime/gc-render.ts +1 -0
  362. package/src/skc-runtime/gc-runtime.ts +11 -1
  363. package/src/skc-runtime/linux-proc.ts +70 -36
  364. package/src/skc-runtime/managed-owner-supervisor.ts +83 -4
  365. package/src/skc-runtime/memory-guard-owner-claims.ts +389 -0
  366. package/src/skc-runtime/ralplan-runtime.ts +1057 -75
  367. package/src/skc-runtime/repository-binding.ts +267 -0
  368. package/src/skc-runtime/session-state-sidecar.ts +25 -9
  369. package/src/skc-runtime/state-runtime.ts +50 -12
  370. package/src/skc-runtime/state-writer.ts +68 -56
  371. package/src/skc-runtime/team-launch.ts +34 -5
  372. package/src/skc-runtime/team-runtime.ts +41 -1
  373. package/src/skc-runtime/team-store.ts +32 -0
  374. package/src/skc-runtime/team-worker-memory-guard.ts +363 -0
  375. package/src/skc-runtime/team-workers.ts +1 -0
  376. package/src/skc-runtime/tmux-common.ts +13 -2
  377. package/src/skc-runtime/tmux-owner-isolation.ts +20 -1
  378. package/src/skc-runtime/tmux-sessions.ts +45 -6
  379. package/src/skc-runtime/ultragoal-guard.ts +93 -15
  380. package/src/skc-runtime/ultragoal-receipt-freshness.ts +123 -0
  381. package/src/skc-runtime/ultragoal-runtime.ts +469 -38
  382. package/src/skc-runtime/workflow-manifest.generated.json +195 -5
  383. package/src/skc-runtime/workflow-manifest.ts +67 -3
  384. package/src/skill-state/workflow-hud.ts +25 -2
  385. package/src/skill-state/workflow-mutation-guard.ts +104 -12
  386. package/src/slash-commands/builtin-registry.ts +1 -1
  387. package/src/ssh/utils.ts +14 -0
  388. package/src/task/discovery.ts +8 -2
  389. package/src/task/executor.ts +165 -47
  390. package/src/task/index.ts +123 -15
  391. package/src/task/provider-retry-status.ts +88 -0
  392. package/src/task/receipt.ts +3 -0
  393. package/src/task/render.ts +45 -26
  394. package/src/task/skc-command.ts +2 -2
  395. package/src/task/types.ts +55 -10
  396. package/src/task/ultragoal-redteam-activation.ts +75 -0
  397. package/src/tools/ask.ts +1 -1
  398. package/src/tools/ast-edit.ts +2 -2
  399. package/src/tools/bash-allowed-prefixes.ts +45 -1
  400. package/src/tools/bash-pty-selection.ts +2 -2
  401. package/src/tools/browser/launch.ts +41 -6
  402. package/src/tools/browser/screenshot-format.ts +6 -1
  403. package/src/tools/cron.ts +1 -1
  404. package/src/tools/fetch.ts +127 -154
  405. package/src/tools/image-gen.ts +476 -23
  406. package/src/tools/index.ts +7 -1
  407. package/src/tools/output-meta.ts +176 -9
  408. package/src/tools/path-utils.ts +5 -1
  409. package/src/tools/read-internals.ts +44 -0
  410. package/src/tools/read.ts +1544 -310
  411. package/src/tools/resource-gc.ts +665 -125
  412. package/src/tools/skill-discovery.ts +39 -3
  413. package/src/tools/sqlite-reader.ts +63 -5
  414. package/src/tools/subagent-render.ts +74 -16
  415. package/src/tools/subagent.ts +2 -0
  416. package/src/tools/tool-result.ts +14 -1
  417. package/src/utils/edit-mode.ts +2 -2
  418. package/src/utils/pasted-image-path.ts +15 -6
  419. package/src/utils/prompt-suggestion.ts +265 -0
  420. package/src/utils/shell-snapshot.ts +173 -63
  421. package/src/utils/sixel.ts +3 -3
  422. package/src/web/insane/bridge.ts +5 -1
  423. package/src/web/insane/url-guard.ts +140 -27
  424. package/src/web/scrapers/docs-rs.ts +30 -5
  425. package/src/web/scrapers/types.ts +19 -49
  426. package/src/web/scrapers/utils.ts +12 -26
  427. package/src/web/search/providers/codex.ts +1 -1
  428. package/src/workflow/workflow-intent-diff.ts +4 -1
@@ -1,11 +1,12 @@
1
1
  import { Container, matchesKey, type SelectItem, SelectList, Spacer, Text } from "@sayknow-cli/tui";
2
+ import { formatKeyHint } from "../../config/keybindings";
2
3
  import type { QueuedMessageEditEntry } from "../../session/agent-session";
3
4
  import { getSelectListTheme, theme } from "../theme/theme";
4
5
  import { DynamicBorder } from "./dynamic-border";
5
6
 
6
7
  const MAX_VISIBLE_QUEUE_MESSAGES = 8;
7
- const RAW_UP = "\x1b[A";
8
- const RAW_DOWN = "\x1b[B";
8
+ type QueueSelectorAction = "tui.select.confirm" | "tui.select.cancel";
9
+ type QueueSelectorNavigationAction = "tui.select.up" | "tui.select.down" | "tui.select.pageUp" | "tui.select.pageDown";
9
10
 
10
11
  export class QueuePaneComponent extends Container {
11
12
  #selectList: SelectList;
@@ -13,11 +14,20 @@ export class QueuePaneComponent extends Container {
13
14
  #selectedIndex: number;
14
15
  #onDelete: (entry: QueuedMessageEditEntry, index: number) => void;
15
16
  #onMove: (entry: QueuedMessageEditEntry, index: number, direction: "up" | "down") => void;
16
-
17
+ #onSelect: (entry: QueuedMessageEditEntry) => void;
18
+ #onClose: () => void;
19
+ #entries: QueuedMessageEditEntry[];
20
+ #matchesSelectAction: (keyData: string, action: QueueSelectorAction) => boolean;
21
+ #resolveSelectNavigation: (keyData: string) => QueueSelectorNavigationAction | undefined;
17
22
  constructor(
18
23
  entries: QueuedMessageEditEntry[],
19
24
  options: {
20
25
  selectedIndex?: number;
26
+ formatKeyHint?: (key: string) => string;
27
+ formatSelectAction?: (action: QueueSelectorAction) => string;
28
+ matchesSelectAction?: (keyData: string, action: QueueSelectorAction) => boolean;
29
+ resolveSelectNavigation?: (keyData: string) => QueueSelectorNavigationAction | undefined;
30
+ onSelect: (entry: QueuedMessageEditEntry) => void;
21
31
  onDelete: (entry: QueuedMessageEditEntry, index: number) => void;
22
32
  onMove: (entry: QueuedMessageEditEntry, index: number, direction: "up" | "down") => void;
23
33
  onClose: () => void;
@@ -25,23 +35,46 @@ export class QueuePaneComponent extends Container {
25
35
  ) {
26
36
  super();
27
37
  this.#onDelete = options.onDelete;
38
+ this.#onSelect = options.onSelect;
28
39
  this.#onMove = options.onMove;
40
+ this.#onClose = options.onClose;
41
+ this.#entries = entries;
42
+ this.#matchesSelectAction =
43
+ options.matchesSelectAction ??
44
+ ((keyData, action) => matchesKey(keyData, action === "tui.select.confirm" ? "enter" : "escape"));
45
+ this.#resolveSelectNavigation = options.resolveSelectNavigation ?? (() => undefined);
29
46
  this.#selectedIndex = Math.max(0, Math.min(options.selectedIndex ?? 0, entries.length - 1));
30
47
  this.#selectedEntry = entries[this.#selectedIndex];
31
48
  const byId = new Map(entries.map(entry => [entry.id, entry]));
49
+ const displayKey = options.formatKeyHint ?? formatKeyHint;
50
+ const selectKeys = `${displayKey("alt+up")}/${displayKey("alt+down")}`;
51
+ const editKey = options.formatSelectAction
52
+ ? options.formatSelectAction("tui.select.confirm") || "Disabled"
53
+ : displayKey("enter");
54
+ const deleteKey = displayKey("delete");
55
+ const moveKeys = `${displayKey("ctrl+up")}/${displayKey("ctrl+down")}`;
56
+ const closeKey = options.formatSelectAction
57
+ ? options.formatSelectAction("tui.select.cancel") || "Disabled"
58
+ : displayKey("escape");
59
+ const itemHint = `${editKey} edit · ${deleteKey} remove · ${moveKeys} move`;
60
+ const controlsHint = `${selectKeys} select · ${itemHint} · ${closeKey} close`;
32
61
  const items: SelectItem[] = entries.map((entry, index) => ({
33
62
  value: entry.id,
34
63
  label: `${entry.label} ${index + 1}`,
35
64
  description: entry.text,
36
- hint: "Del remove · Ctrl+↑/↓ move",
65
+ hint: itemHint,
37
66
  }));
38
67
 
39
68
  this.addChild(new Spacer(1));
40
69
  this.addChild(new Text(theme.bold("Message queue"), 1, 0));
41
- this.addChild(new Text(theme.fg("muted", "Del remove · Ctrl+↑/↓ move · Esc close"), 1, 0));
70
+ this.addChild(new Text(theme.fg("muted", controlsHint), 1, 0));
42
71
  this.addChild(new Spacer(1));
43
72
  this.addChild(new DynamicBorder());
44
73
  this.#selectList = new SelectList(items, MAX_VISIBLE_QUEUE_MESSAGES, getSelectListTheme());
74
+ this.#selectList.onSelect = item => {
75
+ const entry = byId.get(item.value);
76
+ if (entry) this.#onSelect(entry);
77
+ };
45
78
  this.#selectList.onSelectionChange = item => {
46
79
  const index = entries.findIndex(entry => entry.id === item.value);
47
80
  this.#selectedIndex = index === -1 ? this.#selectedIndex : index;
@@ -54,12 +87,25 @@ export class QueuePaneComponent extends Container {
54
87
  }
55
88
 
56
89
  handleInput(keyData: string): void {
57
- if (matchesKey(keyData, "alt+up")) {
58
- this.#selectList.handleInput(RAW_UP);
90
+ if (this.#matchesSelectAction(keyData, "tui.select.confirm")) {
91
+ if (this.#selectedEntry) this.#onSelect(this.#selectedEntry);
92
+ return;
93
+ }
94
+ if (this.#matchesSelectAction(keyData, "tui.select.cancel")) {
95
+ this.#onClose();
96
+ return;
97
+ }
98
+ const navigation = this.#resolveSelectNavigation(keyData);
99
+ if (navigation) {
100
+ this.#selectList.handleNavigation(navigation);
59
101
  return;
60
102
  }
61
- if (matchesKey(keyData, "alt+down")) {
62
- this.#selectList.handleInput(RAW_DOWN);
103
+ if (matchesKey(keyData, "enter") || matchesKey(keyData, "escape")) return;
104
+ if (matchesKey(keyData, "alt+up") || matchesKey(keyData, "alt+down")) {
105
+ const direction = matchesKey(keyData, "alt+up") ? -1 : 1;
106
+ this.#selectedIndex = (this.#selectedIndex + direction + this.#entries.length) % this.#entries.length;
107
+ this.#selectedEntry = this.#entries[this.#selectedIndex];
108
+ this.#selectList.setSelectedIndex(this.#selectedIndex);
63
109
  return;
64
110
  }
65
111
  if (matchesKey(keyData, "ctrl+up") || matchesKey(keyData, "ctrl+shift+up")) {
@@ -1,12 +1,13 @@
1
1
  import { Container, matchesKey, type SelectItem, SelectList, Spacer, Text } from "@sayknow-cli/tui";
2
+ import { formatKeyHint } from "../../config/keybindings";
2
3
  import type { QueuedMessageEditEntry } from "../../session/agent-session";
3
4
  import { getSelectListTheme, theme } from "../theme/theme";
4
5
  import { DynamicBorder } from "./dynamic-border";
5
6
 
6
7
  const MAX_VISIBLE_QUEUED_MESSAGES = 8;
7
- const RAW_UP = "\x1b[A";
8
- const RAW_DOWN = "\x1b[B";
9
8
  type QueuedMessageMoveDirection = "up" | "down";
9
+ type QueueSelectorAction = "tui.select.confirm" | "tui.select.cancel";
10
+ type QueueSelectorNavigationAction = "tui.select.up" | "tui.select.down" | "tui.select.pageUp" | "tui.select.pageDown";
10
11
 
11
12
  export type { QueuedMessageMoveDirection };
12
13
 
@@ -16,32 +17,61 @@ export class QueuedMessageSelectorComponent extends Container {
16
17
  #selectedIndex = 0;
17
18
  #onDelete: (entry: QueuedMessageEditEntry, selectedIndex: number) => void;
18
19
  #onMove: (entry: QueuedMessageEditEntry, selectedIndex: number, direction: QueuedMessageMoveDirection) => void;
19
-
20
+ #onSelect: (entry: QueuedMessageEditEntry) => void;
21
+ #onCancel: () => void;
22
+ #entries: QueuedMessageEditEntry[];
23
+ #matchesSelectAction: (keyData: string, action: QueueSelectorAction) => boolean;
24
+ #resolveSelectNavigation: (keyData: string) => QueueSelectorNavigationAction | undefined;
20
25
  constructor(
21
26
  entries: QueuedMessageEditEntry[],
22
27
  onSelect: (entry: QueuedMessageEditEntry) => void,
23
28
  onDelete: (entry: QueuedMessageEditEntry, selectedIndex: number) => void,
24
29
  onMove: (entry: QueuedMessageEditEntry, selectedIndex: number, direction: QueuedMessageMoveDirection) => void,
25
30
  onCancel: () => void,
26
- options?: { selectedIndex?: number },
31
+ options?: {
32
+ selectedIndex?: number;
33
+ formatKeyHint?: (key: string) => string;
34
+ formatSelectAction?: (action: QueueSelectorAction) => string;
35
+ matchesSelectAction?: (keyData: string, action: QueueSelectorAction) => boolean;
36
+ resolveSelectNavigation?: (keyData: string) => QueueSelectorNavigationAction | undefined;
37
+ },
27
38
  ) {
28
39
  super();
29
40
 
30
41
  this.#onDelete = onDelete;
31
42
  this.#onMove = onMove;
43
+ this.#onSelect = onSelect;
44
+ this.#onCancel = onCancel;
45
+ this.#entries = entries;
46
+ this.#matchesSelectAction =
47
+ options?.matchesSelectAction ??
48
+ ((keyData, action) => matchesKey(keyData, action === "tui.select.confirm" ? "enter" : "escape"));
49
+ this.#resolveSelectNavigation = options?.resolveSelectNavigation ?? (() => undefined);
32
50
  const byId = new Map(entries.map(entry => [entry.id, entry]));
33
51
  this.#selectedIndex = Math.max(0, Math.min(options?.selectedIndex ?? 0, entries.length - 1));
34
52
  this.#selectedEntry = entries[this.#selectedIndex];
53
+ const displayKey = options?.formatKeyHint ?? formatKeyHint;
54
+ const selectKeys = `${displayKey("alt+up")}/${displayKey("alt+down")}`;
55
+ const editKey = options?.formatSelectAction
56
+ ? options.formatSelectAction("tui.select.confirm") || "Disabled"
57
+ : displayKey("enter");
58
+ const deleteKey = displayKey("delete");
59
+ const moveKeys = `${displayKey("ctrl+up")}/${displayKey("ctrl+down")}`;
60
+ const cancelKey = options?.formatSelectAction
61
+ ? options.formatSelectAction("tui.select.cancel") || "Disabled"
62
+ : displayKey("escape");
63
+ const itemHint = `${editKey} edit · ${deleteKey} remove · ${moveKeys} move`;
64
+ const controlsHint = `${selectKeys} select · ${itemHint} · ${cancelKey} cancel`;
35
65
  const items: SelectItem[] = entries.map((entry, index) => ({
36
66
  value: entry.id,
37
67
  label: `${entry.label} ${index + 1}`,
38
68
  description: entry.text,
39
- hint: "Enter edit · Del remove · Ctrl+↑/↓ move",
69
+ hint: itemHint,
40
70
  }));
41
71
 
42
72
  this.addChild(new Spacer(1));
43
73
  this.addChild(new Text(theme.bold("Queued messages"), 1, 0));
44
- this.addChild(new Text(theme.fg("muted", "Enter edit · Del remove · Ctrl+↑/↓ move · Esc cancel"), 1, 0));
74
+ this.addChild(new Text(theme.fg("muted", controlsHint), 1, 0));
45
75
  this.addChild(new Spacer(1));
46
76
  this.addChild(new DynamicBorder());
47
77
 
@@ -63,12 +93,25 @@ export class QueuedMessageSelectorComponent extends Container {
63
93
  }
64
94
 
65
95
  handleInput(keyData: string): void {
66
- if (matchesKey(keyData, "alt+up")) {
67
- this.#selectList.handleInput(RAW_UP);
96
+ if (this.#matchesSelectAction(keyData, "tui.select.confirm")) {
97
+ if (this.#selectedEntry) this.#onSelect(this.#selectedEntry);
98
+ return;
99
+ }
100
+ if (this.#matchesSelectAction(keyData, "tui.select.cancel")) {
101
+ this.#onCancel();
102
+ return;
103
+ }
104
+ const navigation = this.#resolveSelectNavigation(keyData);
105
+ if (navigation) {
106
+ this.#selectList.handleNavigation(navigation);
68
107
  return;
69
108
  }
70
- if (matchesKey(keyData, "alt+down")) {
71
- this.#selectList.handleInput(RAW_DOWN);
109
+ if (matchesKey(keyData, "enter") || matchesKey(keyData, "escape")) return;
110
+ if (matchesKey(keyData, "alt+up") || matchesKey(keyData, "alt+down")) {
111
+ const direction = matchesKey(keyData, "alt+up") ? -1 : 1;
112
+ this.#selectedIndex = (this.#selectedIndex + direction + this.#entries.length) % this.#entries.length;
113
+ this.#selectedEntry = this.#entries[this.#selectedIndex];
114
+ this.#selectList.setSelectedIndex(this.#selectedIndex);
72
115
  return;
73
116
  }
74
117
  if (matchesKey(keyData, "ctrl+up") || matchesKey(keyData, "ctrl+shift+up")) {
@@ -3,7 +3,7 @@ import { Container, Text } from "@sayknow-cli/tui";
3
3
  import { InternalUrlRouter } from "../../internal-urls";
4
4
  import { getLanguageFromPath, theme } from "../../modes/theme/theme";
5
5
  import { splitPathAndSel } from "../../tools/path-utils";
6
- import { PREVIEW_LIMITS, shortenPath } from "../../tools/render-utils";
6
+ import { PREVIEW_LIMITS, replaceTabs, shortenPath } from "../../tools/render-utils";
7
7
  import { renderCodeCell } from "../../tui";
8
8
  import type { ToolExecutionHandle } from "./tool-execution";
9
9
 
@@ -53,9 +53,16 @@ type ReadToolResultDetails = {
53
53
  conflictCount?: number;
54
54
  };
55
55
 
56
- type ReadToolGroupOptions = {
57
- showContentPreview?: boolean;
58
- };
56
+ type ReadToolVisibleProjection = ReadonlyArray<{
57
+ path: string;
58
+ status: ReadEntry["status"];
59
+ correctedFrom?: string;
60
+ conflictCount?: number;
61
+ preview?: {
62
+ lines: readonly string[];
63
+ hiddenLineCount: number;
64
+ };
65
+ }>;
59
66
 
60
67
  function getSuffixResolution(details: ReadToolResultDetails | undefined): ReadToolSuffixResolution | undefined {
61
68
  if (typeof details?.suffixResolution?.from !== "string" || typeof details.suffixResolution.to !== "string") {
@@ -82,13 +89,16 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
82
89
  #expanded = false;
83
90
  #manuallyExpanded: boolean | undefined;
84
91
  #showContentPreview: boolean;
92
+ #visibleTranscriptChanged = false;
93
+ #lastVisibleProjection: ReadToolVisibleProjection = [];
85
94
 
86
- constructor(options: ReadToolGroupOptions = {}) {
95
+ constructor(options: { showContentPreview?: boolean } = {}) {
87
96
  super();
88
97
  this.#showContentPreview = options.showContentPreview ?? false;
89
98
  this.#text = new Text("", 0, 0);
90
99
  this.addChild(this.#text);
91
100
  this.#updateDisplay();
101
+ this.#lastVisibleProjection = this.#visibleProjection();
92
102
  }
93
103
 
94
104
  updateArgs(args: ReadRenderArgs, toolCallId?: string): void {
@@ -102,7 +112,7 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
102
112
  };
103
113
  entry.path = rawPath;
104
114
  this.#entries.set(toolCallId, entry);
105
- this.#updateDisplay();
115
+ this.#updateDisplayAndNotify();
106
116
  }
107
117
 
108
118
  updateResult(
@@ -126,23 +136,20 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
126
136
  typeof details?.conflictCount === "number" && details.conflictCount > 0 ? details.conflictCount : undefined;
127
137
  entry.conflictCount = conflictCount;
128
138
  entry.status = result.isError ? "error" : suffixResolution ? "warning" : "success";
129
- // Store the text content for preview/expanded display
130
139
  const textContent = result.content?.find(c => c.type === "text")?.text;
131
- if (textContent !== undefined) {
132
- entry.contentText = textContent;
133
- }
134
- this.#updateDisplay();
140
+ entry.contentText = textContent;
141
+ this.#updateDisplayAndNotify();
135
142
  }
136
143
 
137
144
  setArgsComplete(_toolCallId?: string): void {
138
- this.#updateDisplay();
145
+ this.#updateDisplayAndNotify();
139
146
  }
140
147
 
141
148
  /** Applies automatic expansion unless this renderer instance has an explicit fold choice. */
142
149
  setExpanded(expanded: boolean): void {
143
150
  if (this.#manuallyExpanded !== undefined) return;
144
151
  this.#expanded = expanded;
145
- this.#updateDisplay();
152
+ this.#updateDisplayAndNotify();
146
153
  }
147
154
 
148
155
  /**
@@ -152,13 +159,74 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
152
159
  setManuallyExpanded(expanded: boolean): void {
153
160
  this.#manuallyExpanded = expanded;
154
161
  this.#expanded = expanded;
155
- this.#updateDisplay();
162
+ this.#updateDisplayAndNotify();
156
163
  }
157
164
 
158
165
  getComponent(): Component {
159
166
  return this;
160
167
  }
161
168
 
169
+ consumeVisibleTranscriptChange(): boolean {
170
+ const changed = this.#visibleTranscriptChanged;
171
+ this.#visibleTranscriptChanged = false;
172
+ return changed;
173
+ }
174
+
175
+ #visibleProjection(): ReadToolVisibleProjection {
176
+ return [...this.#entries.values()].map(entry => {
177
+ if (!this.#shouldRenderPreview(entry)) {
178
+ return {
179
+ path: entry.path,
180
+ status: entry.status,
181
+ correctedFrom: entry.correctedFrom,
182
+ conflictCount: entry.conflictCount,
183
+ };
184
+ }
185
+ const lines = replaceTabs(entry.contentText ?? "")
186
+ .split(/\r?\n/)
187
+ .map(line => line.slice(line.lastIndexOf("\r") + 1));
188
+ const visibleLineCount = this.#expanded ? lines.length : Math.min(lines.length, COLLAPSED_PREVIEW_LINES);
189
+ return {
190
+ path: entry.path,
191
+ status: entry.status,
192
+ correctedFrom: entry.correctedFrom,
193
+ preview: {
194
+ lines: lines.slice(0, visibleLineCount),
195
+ hiddenLineCount: lines.length - visibleLineCount,
196
+ },
197
+ };
198
+ });
199
+ }
200
+
201
+ #sameVisibleProjection(left: ReadToolVisibleProjection, right: ReadToolVisibleProjection): boolean {
202
+ if (left.length !== right.length) return false;
203
+ return left.every((entry, index) => {
204
+ const other = right[index];
205
+ if (
206
+ !other ||
207
+ entry.path !== other.path ||
208
+ entry.status !== other.status ||
209
+ entry.correctedFrom !== other.correctedFrom ||
210
+ (!entry.preview && entry.conflictCount !== other.conflictCount)
211
+ )
212
+ return false;
213
+ if (!entry.preview || !other.preview) return entry.preview === other.preview;
214
+ return (
215
+ entry.preview.hiddenLineCount === other.preview.hiddenLineCount &&
216
+ entry.preview.lines.length === other.preview.lines.length &&
217
+ entry.preview.lines.every((line, lineIndex) => line === other.preview!.lines[lineIndex])
218
+ );
219
+ });
220
+ }
221
+
222
+ #updateDisplayAndNotify(): void {
223
+ this.#updateDisplay();
224
+ const after = this.#visibleProjection();
225
+ if (this.#sameVisibleProjection(after, this.#lastVisibleProjection)) return;
226
+ this.#lastVisibleProjection = after;
227
+ this.#visibleTranscriptChanged = true;
228
+ }
229
+
162
230
  #updateDisplay(): void {
163
231
  const entries = [...this.#entries.values()];
164
232
 
@@ -60,6 +60,7 @@ type WizardStep =
60
60
  */
61
61
  export interface MCPAddWizardOAuthResult {
62
62
  credentialId: string;
63
+ tokenEndpoint: string;
63
64
  clientId?: string;
64
65
  clientSecret?: string;
65
66
  }
@@ -122,6 +123,7 @@ export class MCPAddWizard extends Container {
122
123
  #onCancelCallback: () => void;
123
124
  #onOAuthCallback:
124
125
  | ((
126
+ endpointUrl: string,
125
127
  authUrl: string,
126
128
  tokenUrl: string,
127
129
  clientId: string,
@@ -141,6 +143,7 @@ export class MCPAddWizard extends Container {
141
143
  onComplete: (name: string, config: MCPServerConfig, scope: Scope) => void,
142
144
  onCancel: () => void,
143
145
  onOAuth?: (
146
+ endpointUrl: string,
144
147
  authUrl: string,
145
148
  tokenUrl: string,
146
149
  clientId: string,
@@ -1189,6 +1192,7 @@ export class MCPAddWizard extends Container {
1189
1192
  try {
1190
1193
  // Call OAuth handler
1191
1194
  const oauthResult = await this.#onOAuthCallback(
1195
+ this.#state.url,
1192
1196
  this.#state.oauthAuthUrl,
1193
1197
  this.#state.oauthTokenUrl,
1194
1198
  this.#state.oauthClientId,
@@ -1200,6 +1204,7 @@ export class MCPAddWizard extends Container {
1200
1204
  // Store credential ID + any dynamically-registered client credentials,
1201
1205
  // so the final mcp.json entry persists everything needed for refresh.
1202
1206
  this.#state.oauthCredentialId = oauthResult.credentialId;
1207
+ this.#state.oauthTokenUrl = oauthResult.tokenEndpoint;
1203
1208
  if (oauthResult.clientId) this.#state.oauthClientId = oauthResult.clientId;
1204
1209
  if (oauthResult.clientSecret) this.#state.oauthClientSecret = oauthResult.clientSecret;
1205
1210
 
@@ -4,6 +4,7 @@ import {
4
4
  type Component,
5
5
  type Container,
6
6
  getCellDimensions,
7
+ isUnderTmux,
7
8
  PARA_PARA_STEPS,
8
9
  PET_SKINS,
9
10
  type PetMode,
@@ -14,6 +15,7 @@ import {
14
15
  type SayknowPixelFrameName,
15
16
  type SayknowPixelFrames,
16
17
  type TUI,
18
+ tmuxOwnsSixel,
17
19
  wrapTmuxPassthrough,
18
20
  } from "@sayknow-cli/tui";
19
21
  import type { CustomEditor } from "./custom-editor";
@@ -281,9 +283,6 @@ export class SayknowPetWidget {
281
283
  sixelTopPaddingPx: protocol === "sixel" ? PET_SIXEL_DROP_PX : 0,
282
284
  kittyCellYOffsetPx: protocol === "kitty" ? petKittyDropPx(cell.heightPx) : 0,
283
285
  kittyImageId: protocol === "kitty" ? this.#kittyImageId : undefined,
284
- // Forward the pet's sixel raster through tmux's DCS passthrough envelope
285
- // when under tmux (no-op otherwise), so the outer terminal renders it.
286
- wrapSixel: wrapTmuxPassthrough,
287
286
  });
288
287
  this.#framedEditor.setReserve(this.#pixel.columns + PET_SIDE_MARGIN);
289
288
  }
@@ -493,6 +492,7 @@ export class SayknowPetWidget {
493
492
  this.#frameCleanupAwaitingAck = false;
494
493
  const { x, y } = pos;
495
494
  let out = "";
495
+ const positioned = `\x1b[${y + 1};${x + 1}H${pixel.frames[this.#frame]}`;
496
496
 
497
497
  if (pixel.protocol === "sixel") {
498
498
  const footprint = { x, y, columns: pixel.columns, rows: pixel.rasterRows };
@@ -501,13 +501,32 @@ export class SayknowPetWidget {
501
501
  }
502
502
  if (clearPet) out += this.#clearSixelFootprint(footprint);
503
503
  this.#lastSixelFootprint = footprint;
504
- } else {
505
- // A kitty frame emitted below (re)places the image, so cleanup is
506
- // pending again even if a narrow-terminal pass consumed it earlier.
507
- this.#kittyCleanupPending = true;
504
+ // Two mutually exclusive delivery modes, and the erase above only works in
505
+ // the first one:
506
+ //
507
+ // tmux owns sixel (terminal-features advertises it): send the frame straight
508
+ // through. tmux parses it into its own screen model, so the ECH erase above
509
+ // actually removes the image, and scroll/resize/copy-mode stay consistent.
510
+ //
511
+ // tmux does NOT own sixel: the frame has to be smuggled past tmux with DCS
512
+ // passthrough, which writes pixels directly into the OUTER terminal's image
513
+ // plane. tmux never records them, so the erase reaches only its cell buffer
514
+ // and the pixels survive as residue. Passthrough is therefore a fallback,
515
+ // not the default. The save/restore pair must sit INSIDE the passthrough
516
+ // envelope: the sixel advances the outer terminal's cursor, and a bare
517
+ // \x1b7/\x1b8 would only reach tmux, scrolling the viewport every frame.
518
+ out += tmuxOwnsSixel()
519
+ ? positioned
520
+ : isUnderTmux()
521
+ ? wrapTmuxPassthrough(`\x1b7${positioned}\x1b8`)
522
+ : positioned;
523
+ return out;
508
524
  }
509
525
 
510
- out += `\x1b[${y + 1};${x + 1}H${pixel.frames[this.#frame]}`;
526
+ // A kitty frame (re)places the image cursor-neutrally, so cleanup is pending
527
+ // again even if a narrow-terminal pass consumed it earlier.
528
+ this.#kittyCleanupPending = true;
529
+ out += positioned;
511
530
  return out;
512
531
  }
513
532
  }