@sayknow-cli/coding-agent 0.4.7 → 0.5.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 (428) hide show
  1. package/CHANGELOG.md +122 -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 +20 -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,10 +1,11 @@
1
+ import * as crypto from "node:crypto";
1
2
  import * as fs from "node:fs";
2
3
  import type { ToolResultMessage } from "@sayknow-cli/ai";
3
4
  import { matchesKey } from "@sayknow-cli/tui";
4
5
  import { formatDuration, formatNumber } from "@sayknow-cli/utils";
5
6
  import type { KeyId } from "../../config/keybindings";
6
7
  import { isSilentAbort } from "../../session/messages";
7
- import type { SessionMessageEntry } from "../../session/session-manager";
8
+ import type { FileEntry, SessionMessageEntry } from "../../session/session-manager";
8
9
  import { parseSessionEntries } from "../../session/session-manager";
9
10
  import type { ObservableSession, SessionObserverRegistry } from "../session-observer-registry";
10
11
  import { theme } from "../theme/theme";
@@ -15,13 +16,26 @@ import {
15
16
  } from "./tool-transcript-format";
16
17
  import { type TranscriptViewerEntry, TranscriptViewerOverlay } from "./transcript-viewer-overlay";
17
18
 
19
+ const FATAL_UTF8_DECODER = new TextDecoder("utf-8", { fatal: true });
20
+
21
+ type FileIdentity = { dev: bigint; ino: bigint };
22
+ type StableSnapshot = { identity: FileIdentity; size: number; prefix: Buffer; tail: Buffer };
23
+ type ObserverCache = {
24
+ path: string;
25
+ identity: FileIdentity;
26
+ completeOffset: number;
27
+ prefixDigest: string;
28
+ entries: SessionMessageEntry[];
29
+ model?: string;
30
+ };
31
+
18
32
  /** Session-observer adapter. The shared viewer owns navigation and fold state. */
19
33
  export class SessionObserverOverlayComponent extends TranscriptViewerOverlay {
20
34
  #registry: SessionObserverRegistry;
21
35
  #onDone: () => void;
22
36
  #observeKeys: readonly KeyId[];
23
37
  #selectedSessionId?: string;
24
- #cache?: { path: string; bytesRead: number; entries: SessionMessageEntry[]; model?: string };
38
+ #cache?: ObserverCache;
25
39
 
26
40
  constructor(registry: SessionObserverRegistry, onDone: () => void, observeKeys: KeyId[]) {
27
41
  // The option closures run during the base constructor's initial refresh,
@@ -126,32 +140,81 @@ export class SessionObserverOverlayComponent extends TranscriptViewerOverlay {
126
140
  return stats.length ? [theme.fg("dim", stats.join(theme.sep.dot))] : [];
127
141
  }
128
142
  #load(filePath: string): SessionMessageEntry[] {
129
- if (this.#cache?.path !== filePath) this.#cache = undefined;
130
- const fromByte = this.#cache?.bytesRead ?? 0;
131
- const result = readFileIncremental(filePath, fromByte);
132
- if (!result) return this.#cache?.entries ?? [];
133
- if (result.newSize < fromByte) {
143
+ if (this.#cache && this.#cache.path !== filePath) {
134
144
  this.#cache = undefined;
135
- return this.#load(filePath);
145
+ this.resetSourceState();
136
146
  }
137
- if (!this.#cache) this.#cache = { path: filePath, bytesRead: 0, entries: [] };
138
- if (result.text) {
139
- const lastNewline = result.text.lastIndexOf("\n");
140
- if (lastNewline >= 0) {
141
- const complete = result.text.slice(0, lastNewline + 1);
142
- for (const entry of parseSessionEntries(complete)) {
143
- if (entry.type === "message") {
144
- this.#cache.entries.push(entry);
145
- if (!this.#cache.model && entry.message.role === "assistant") this.#cache.model = entry.message.model;
146
- } else if (entry.type === "model_change") this.#cache.model = entry.model;
147
- }
148
- this.#cache.bytesRead = fromByte + Buffer.byteLength(complete, "utf-8");
147
+
148
+ const cache = this.#cache;
149
+ const snapshot = readStableSnapshot(filePath, cache?.completeOffset ?? 0);
150
+ if (!snapshot) {
151
+ // An unreadable source is never allowed to keep presenting a prior file as current.
152
+ if (cache) this.#clearSource();
153
+ return [];
154
+ }
155
+
156
+ const canAppend =
157
+ cache &&
158
+ sameIdentity(cache.identity, snapshot.identity) &&
159
+ snapshot.size >= cache.completeOffset &&
160
+ digest(snapshot.prefix) === cache.prefixDigest;
161
+ if (canAppend) return this.#appendStable(cache, snapshot);
162
+
163
+ // A changed fd identity, changed committed bytes, or a shrink is a replacement.
164
+ // Validate the entire candidate before it replaces the visible transcript.
165
+ const replacement = readStableSnapshot(filePath, 0);
166
+ if (!replacement) {
167
+ this.#clearSource();
168
+ return [];
169
+ }
170
+ const candidate = cacheEntries(filePath, replacement);
171
+ if (!candidate) {
172
+ this.#clearSource();
173
+ return [];
174
+ }
175
+ this.#cache = candidate;
176
+ if (cache) this.resetSourceState();
177
+ return candidate.entries;
178
+ }
179
+ #appendStable(cache: ObserverCache, snapshot: StableSnapshot): SessionMessageEntry[] {
180
+ const complete = completePrefix(snapshot.tail);
181
+ if (!complete) {
182
+ if (!isValidUtf8Prefix(snapshot.tail)) {
183
+ this.#clearSource();
184
+ return [];
149
185
  }
186
+ return cache.entries;
187
+ }
188
+ const remainder = snapshot.tail.subarray(complete.bytes.length);
189
+ if (!isValidUtf8Prefix(remainder)) {
190
+ this.#clearSource();
191
+ return [];
150
192
  }
151
- return this.#cache.entries;
193
+ const parsed = parseCompleteEntries(complete.bytes);
194
+ if (!parsed) {
195
+ this.#clearSource();
196
+ return [];
197
+ }
198
+ const entries = [...cache.entries, ...parsed.entries];
199
+ this.#cache = {
200
+ ...cache,
201
+ completeOffset: cache.completeOffset + complete.bytes.length,
202
+ prefixDigest: digest(Buffer.concat([snapshot.prefix, complete.bytes])),
203
+ entries,
204
+ model: parsed.model ?? cache.model,
205
+ };
206
+ return entries;
207
+ }
208
+ #clearSource(): void {
209
+ if (this.#cache) this.resetSourceState();
210
+ this.#cache = undefined;
152
211
  }
153
212
  }
154
213
 
214
+ /**
215
+ * This deliberately remains the eager full-history projection. PR2 owns projection
216
+ * virtualization/incrementalization; source acquisition above only controls snapshot safety.
217
+ */
155
218
  export function entriesFromMessages(entries: readonly SessionMessageEntry[]): TranscriptViewerEntry[] {
156
219
  const results = new Map<string, ToolResultMessage>();
157
220
  for (const entry of entries)
@@ -259,19 +322,111 @@ function truncateThinking(text: string, expanded: boolean): string {
259
322
  return text.length > limit ? `${text.slice(0, limit)}...` : text;
260
323
  }
261
324
 
262
- function readFileIncremental(filePath: string, fromByte: number): { text: string; newSize: number } | null {
325
+ function readStableSnapshot(filePath: string, completeOffset: number): StableSnapshot | null {
326
+ let fd: number | undefined;
263
327
  try {
264
- const stat = fs.statSync(filePath);
265
- if (stat.size <= fromByte) return { text: "", newSize: stat.size };
266
- const buffer = Buffer.alloc(stat.size - fromByte);
267
- const fd = fs.openSync(filePath, "r");
268
- try {
269
- fs.readSync(fd, buffer, 0, buffer.length, fromByte);
270
- } finally {
271
- fs.closeSync(fd);
272
- }
273
- return { text: buffer.toString("utf-8"), newSize: stat.size };
328
+ fd = fs.openSync(filePath, "r");
329
+ const before = fs.fstatSync(fd, { bigint: true });
330
+ if (before.size > BigInt(Number.MAX_SAFE_INTEGER) || completeOffset > Number(before.size)) return null;
331
+ const size = Number(before.size);
332
+ const prefix = readExactly(fd, 0, completeOffset);
333
+ const tail = readExactly(fd, completeOffset, size - completeOffset);
334
+ const after = fs.fstatSync(fd, { bigint: true });
335
+ if (
336
+ before.dev !== after.dev ||
337
+ before.ino !== after.ino ||
338
+ before.size !== after.size ||
339
+ before.mtimeNs !== after.mtimeNs ||
340
+ before.ctimeNs !== after.ctimeNs
341
+ )
342
+ return null;
343
+ return { identity: { dev: before.dev, ino: before.ino }, size, prefix, tail };
344
+ } catch {
345
+ return null;
346
+ } finally {
347
+ if (fd !== undefined) fs.closeSync(fd);
348
+ }
349
+ }
350
+
351
+ function readExactly(fd: number, position: number, length: number): Buffer {
352
+ const buffer = Buffer.alloc(length);
353
+ let offset = 0;
354
+ while (offset < length) {
355
+ const bytesRead = fs.readSync(fd, buffer, offset, length - offset, position + offset);
356
+ if (bytesRead === 0) throw new Error("Short session file read");
357
+ offset += bytesRead;
358
+ }
359
+ return buffer;
360
+ }
361
+
362
+ function sameIdentity(left: FileIdentity, right: FileIdentity): boolean {
363
+ return left.dev === right.dev && left.ino === right.ino;
364
+ }
365
+
366
+ function digest(bytes: Buffer): string {
367
+ return crypto.createHash("sha256").update(bytes).digest("hex");
368
+ }
369
+
370
+ function completePrefix(bytes: Buffer): { bytes: Buffer } | undefined {
371
+ const newline = bytes.lastIndexOf(0x0a);
372
+ return newline < 0 ? undefined : { bytes: bytes.subarray(0, newline + 1) };
373
+ }
374
+
375
+ function parseCompleteEntries(bytes: Buffer): { entries: SessionMessageEntry[]; model?: string } | null {
376
+ try {
377
+ const text = FATAL_UTF8_DECODER.decode(bytes);
378
+ for (const line of text.split("\n")) if (line.trim()) JSON.parse(line);
379
+ const parsed = parseSessionEntries(text);
380
+ return {
381
+ entries: parsed.filter((entry): entry is SessionMessageEntry => entry.type === "message"),
382
+ model: modelFromEntries(parsed),
383
+ };
274
384
  } catch {
275
385
  return null;
276
386
  }
277
387
  }
388
+
389
+ function modelFromEntries(entries: readonly FileEntry[]): string | undefined {
390
+ let model: string | undefined;
391
+ for (const entry of entries) {
392
+ if (entry.type === "model_change") model = entry.model;
393
+ else if (entry.type === "message" && entry.message.role === "assistant" && entry.message.model)
394
+ model = entry.message.model;
395
+ }
396
+ return model;
397
+ }
398
+
399
+ function isValidUtf8Prefix(bytes: Buffer): boolean {
400
+ try {
401
+ new TextDecoder("utf-8", { fatal: true }).decode(bytes, { stream: true });
402
+ return true;
403
+ } catch {
404
+ return false;
405
+ }
406
+ }
407
+
408
+ function cacheEntries(filePath: string, snapshot: StableSnapshot): ObserverCache | null {
409
+ const complete = completePrefix(snapshot.tail);
410
+ if (!complete) {
411
+ if (!isValidUtf8Prefix(snapshot.tail)) return null;
412
+ return {
413
+ path: filePath,
414
+ identity: snapshot.identity,
415
+ completeOffset: 0,
416
+ prefixDigest: digest(Buffer.alloc(0)),
417
+ entries: [],
418
+ };
419
+ }
420
+ const remainder = snapshot.tail.subarray(complete.bytes.length);
421
+ if (!isValidUtf8Prefix(remainder)) return null;
422
+ const parsed = parseCompleteEntries(complete.bytes);
423
+ if (!parsed) return null;
424
+ return {
425
+ path: filePath,
426
+ identity: snapshot.identity,
427
+ completeOffset: complete.bytes.length,
428
+ prefixDigest: digest(complete.bytes),
429
+ entries: parsed.entries,
430
+ model: parsed.model,
431
+ };
432
+ }
@@ -250,18 +250,16 @@ function getSavedUsageMode(): UsageMode {
250
250
  return segmentOptions.usage?.mode === "remaining" ? "remaining" : "used";
251
251
  }
252
252
 
253
- function setSavedUsageMode(mode: string): StatusLineSegmentOptions {
253
+ function getUsageModeSettings(mode: string): StatusLineSegmentOptions {
254
254
  const normalizedMode: UsageMode = mode === "remaining" ? "remaining" : "used";
255
255
  const segmentOptions = settings.get("statusLine.segmentOptions") as StatusLineSegmentOptions;
256
- const nextOptions: StatusLineSegmentOptions = {
256
+ return {
257
257
  ...segmentOptions,
258
258
  usage: {
259
259
  ...(segmentOptions.usage ?? {}),
260
260
  mode: normalizedMode,
261
261
  },
262
262
  };
263
- settings.set("statusLine.segmentOptions", nextOptions as Record<string, unknown>);
264
- return nextOptions;
265
263
  }
266
264
 
267
265
  function statusSegmentLabel(id: StatusLineSegmentId): string {
@@ -625,14 +623,17 @@ class StatusLineCustomEditor extends Container {
625
623
  }
626
624
 
627
625
  #save(): void {
628
- settings.set("statusLine.preset", "custom");
629
- settings.set("statusLine.leftSegments", [...this.#draft.leftSegments]);
630
- settings.set("statusLine.rightSegments", [...this.#draft.rightSegments]);
631
- settings.set("statusLine.separator", this.#draft.separator);
632
- settings.set(
633
- "statusLine.segmentOptions",
634
- cloneSegmentOptions(this.#draft.segmentOptions) as Record<string, unknown>,
635
- );
626
+ const saved = commitInteractiveSettings(this.callbacks, () => {
627
+ settings.set("statusLine.preset", "custom");
628
+ settings.set("statusLine.leftSegments", [...this.#draft.leftSegments]);
629
+ settings.set("statusLine.rightSegments", [...this.#draft.rightSegments]);
630
+ settings.set("statusLine.separator", this.#draft.separator);
631
+ settings.set(
632
+ "statusLine.segmentOptions",
633
+ cloneSegmentOptions(this.#draft.segmentOptions) as Record<string, unknown>,
634
+ );
635
+ });
636
+ if (!saved) return;
636
637
  this.callbacks.onChange("statusLine.preset", "custom");
637
638
  this.callbacks.onChange("statusLine.leftSegments", [...this.#draft.leftSegments]);
638
639
  this.callbacks.onChange("statusLine.rightSegments", [...this.#draft.rightSegments]);
@@ -719,9 +720,29 @@ export interface SettingsCallbacks {
719
720
  getStatusLinePreview?: (width?: number) => string;
720
721
  /** Called when plugins change */
721
722
  onPluginsChanged?: () => void;
723
+ /** Called when an interactive setting cannot be committed. */
724
+ onError?: (message: string) => void;
722
725
  /** Called when settings panel is closed */
723
726
  onCancel: () => void;
724
727
  }
728
+ function commitInteractiveSettings(callbacks: SettingsCallbacks, commit: () => void): boolean {
729
+ if (!settings.canWriteDurableConfig()) {
730
+ callbacks.onError?.(
731
+ "Cannot change settings while config.yml has invalid YAML syntax. Repair config.yml and reload settings.",
732
+ );
733
+ return false;
734
+ }
735
+ try {
736
+ commit();
737
+ return true;
738
+ } catch (error) {
739
+ if (!settings.canWriteDurableConfig()) {
740
+ callbacks.onError?.(error instanceof Error ? error.message : String(error));
741
+ return false;
742
+ }
743
+ throw error;
744
+ }
745
+ }
725
746
 
726
747
  /**
727
748
  * Main tabbed settings selector component.
@@ -1008,11 +1029,18 @@ export class SettingsSelectorComponent extends Container {
1008
1029
  // The shared pet commit policy rechecks capability immediately
1009
1030
  // before mutation and persists only on acceptance; the settings
1010
1031
  // surface must not persist ahead of that result.
1011
- const accepted = this.callbacks.onPetCommit?.(value) ?? false;
1032
+ let accepted = false;
1033
+ if (
1034
+ !commitInteractiveSettings(this.callbacks, () => {
1035
+ accepted = this.callbacks.onPetCommit?.(value) ?? false;
1036
+ })
1037
+ ) {
1038
+ return;
1039
+ }
1012
1040
  done(accepted ? value : undefined);
1013
1041
  return;
1014
1042
  }
1015
- this.#setSettingValue(def.path, value);
1043
+ if (!commitInteractiveSettings(this.callbacks, () => this.#setSettingValue(def.path, value))) return;
1016
1044
  this.callbacks.onChange(def.path, value);
1017
1045
  done(value);
1018
1046
  },
@@ -1045,7 +1073,7 @@ export class SettingsSelectorComponent extends Container {
1045
1073
  value => {
1046
1074
  // Empty string clears the setting; undefined-typed string settings
1047
1075
  // store "" which the browser.ts expandPath ignores (no-op fallback).
1048
- this.#setSettingValue(def.path, value);
1076
+ if (!commitInteractiveSettings(this.callbacks, () => this.#setSettingValue(def.path, value))) return;
1049
1077
  this.callbacks.onChange(def.path, value);
1050
1078
  wrappedDone(value);
1051
1079
  },
@@ -1103,7 +1131,15 @@ export class SettingsSelectorComponent extends Container {
1103
1131
  getSettingsListTheme(),
1104
1132
  (id, newValue) => {
1105
1133
  if (id === STATUS_LINE_USAGE_MODE_ID) {
1106
- const segmentOptions = setSavedUsageMode(newValue);
1134
+ const segmentOptions = getUsageModeSettings(newValue);
1135
+ if (
1136
+ !commitInteractiveSettings(this.callbacks, () => {
1137
+ settings.set("statusLine.segmentOptions", segmentOptions as Record<string, unknown>);
1138
+ })
1139
+ ) {
1140
+ this.#refreshCurrentTabItems(defs);
1141
+ return;
1142
+ }
1107
1143
  this.callbacks.onChange("statusLine.segmentOptions", segmentOptions);
1108
1144
  if (tabId === "appearance") {
1109
1145
  this.#triggerStatusLinePreview();
@@ -1119,14 +1155,20 @@ export class SettingsSelectorComponent extends Container {
1119
1155
 
1120
1156
  if (def.type === "boolean") {
1121
1157
  const boolValue = newValue === "true";
1122
- settings.set(path, boolValue as never);
1158
+ if (!commitInteractiveSettings(this.callbacks, () => settings.set(path, boolValue as never))) {
1159
+ this.#refreshCurrentTabItems(defs);
1160
+ return;
1161
+ }
1123
1162
  this.callbacks.onChange(path, boolValue);
1124
1163
 
1125
1164
  if (tabId === "appearance") {
1126
1165
  this.#triggerStatusLinePreview();
1127
1166
  }
1128
1167
  } else if (def.type === "enum") {
1129
- settings.set(path, newValue as never);
1168
+ if (!commitInteractiveSettings(this.callbacks, () => settings.set(path, newValue as never))) {
1169
+ this.#refreshCurrentTabItems(defs);
1170
+ return;
1171
+ }
1130
1172
  this.callbacks.onChange(path, newValue);
1131
1173
  }
1132
1174
  // Submenu/text types already persisted the value inside their own