salmon-loop 0.2.3

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 (655) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -0
  3. package/README.zh-CN.md +144 -0
  4. package/dist/cli/argv/headless-detection.js +60 -0
  5. package/dist/cli/argv/print-mode.js +60 -0
  6. package/dist/cli/authorization/allowlist.js +908 -0
  7. package/dist/cli/authorization/non-interactive.js +166 -0
  8. package/dist/cli/authorization/provider.js +416 -0
  9. package/dist/cli/chat-interface.js +83 -0
  10. package/dist/cli/chat.js +492 -0
  11. package/dist/cli/cli-runtime-context.js +12 -0
  12. package/dist/cli/commander-error-adapter.js +35 -0
  13. package/dist/cli/commander-error-meta.js +13 -0
  14. package/dist/cli/commands/allowlist.js +270 -0
  15. package/dist/cli/commands/chat.js +120 -0
  16. package/dist/cli/commands/config.js +250 -0
  17. package/dist/cli/commands/context.js +57 -0
  18. package/dist/cli/commands/dispatcher.js +53 -0
  19. package/dist/cli/commands/exit.js +9 -0
  20. package/dist/cli/commands/llm-output.js +135 -0
  21. package/dist/cli/commands/log-mode.js +143 -0
  22. package/dist/cli/commands/mode.js +136 -0
  23. package/dist/cli/commands/new.js +18 -0
  24. package/dist/cli/commands/parallel.js +256 -0
  25. package/dist/cli/commands/queue.js +130 -0
  26. package/dist/cli/commands/registry.js +85 -0
  27. package/dist/cli/commands/restore.js +26 -0
  28. package/dist/cli/commands/run/assistant-message.js +14 -0
  29. package/dist/cli/commands/run/config-resolution.js +37 -0
  30. package/dist/cli/commands/run/early-errors.js +108 -0
  31. package/dist/cli/commands/run/execute.js +73 -0
  32. package/dist/cli/commands/run/extensions-resolution.js +22 -0
  33. package/dist/cli/commands/run/handler.js +434 -0
  34. package/dist/cli/commands/run/headless-error-writer.js +182 -0
  35. package/dist/cli/commands/run/instruction-guard.js +24 -0
  36. package/dist/cli/commands/run/loop-params.js +46 -0
  37. package/dist/cli/commands/run/mode.js +8 -0
  38. package/dist/cli/commands/run/parse-options.js +67 -0
  39. package/dist/cli/commands/run/persist-session.js +35 -0
  40. package/dist/cli/commands/run/preflight.js +156 -0
  41. package/dist/cli/commands/run/reporter-factory.js +52 -0
  42. package/dist/cli/commands/run/runtime-llm.js +56 -0
  43. package/dist/cli/commands/run/runtime-options.js +30 -0
  44. package/dist/cli/commands/run/session.js +19 -0
  45. package/dist/cli/commands/run/structured-output.js +106 -0
  46. package/dist/cli/commands/run/types.js +2 -0
  47. package/dist/cli/commands/run/validate-options.js +28 -0
  48. package/dist/cli/commands/run/verbose.js +36 -0
  49. package/dist/cli/commands/run.js +2 -0
  50. package/dist/cli/commands/serve.js +323 -0
  51. package/dist/cli/commands/session.js +77 -0
  52. package/dist/cli/commands/snapshot-interactive.js +165 -0
  53. package/dist/cli/commands/snapshot.js +159 -0
  54. package/dist/cli/commands/status.js +17 -0
  55. package/dist/cli/commands/subagent.js +178 -0
  56. package/dist/cli/commands/subcommand-suggestions.js +63 -0
  57. package/dist/cli/commands/tool-names.js +155 -0
  58. package/dist/cli/commands/types.js +2 -0
  59. package/dist/cli/commands/utils.js +42 -0
  60. package/dist/cli/config.js +16 -0
  61. package/dist/cli/crash-reporter.js +5 -0
  62. package/dist/cli/headless/anthropic-stream-normalized-encoder.js +164 -0
  63. package/dist/cli/headless/anthropic-stream-protocol.js +62 -0
  64. package/dist/cli/headless/json-protocol.js +124 -0
  65. package/dist/cli/headless/native-stream-normalized-encoder.js +206 -0
  66. package/dist/cli/headless/openai-responses-canonical-applier.js +94 -0
  67. package/dist/cli/headless/openai-responses-state.js +294 -0
  68. package/dist/cli/headless/openai-stream-encoder.js +152 -0
  69. package/dist/cli/headless/stdout-writer.js +9 -0
  70. package/dist/cli/headless/stream-json-protocol.js +136 -0
  71. package/dist/cli/index.js +8 -0
  72. package/dist/cli/locales/en.js +409 -0
  73. package/dist/cli/locales/index.js +7 -0
  74. package/dist/cli/program-bootstrap.js +14 -0
  75. package/dist/cli/program-commands.js +106 -0
  76. package/dist/cli/program-options.js +15 -0
  77. package/dist/cli/program-output-mode.js +11 -0
  78. package/dist/cli/program-parse.js +24 -0
  79. package/dist/cli/reporters/anthropic-stream.js +77 -0
  80. package/dist/cli/reporters/base.js +2 -0
  81. package/dist/cli/reporters/json.js +69 -0
  82. package/dist/cli/reporters/openai-stream.js +72 -0
  83. package/dist/cli/reporters/standard.js +226 -0
  84. package/dist/cli/reporters/stderr-log-reporter.js +71 -0
  85. package/dist/cli/reporters/stream-json.js +111 -0
  86. package/dist/cli/run-cli.js +25 -0
  87. package/dist/cli/slash/runtime.js +240 -0
  88. package/dist/cli/ui/App.js +273 -0
  89. package/dist/cli/ui/authorization/bus.js +35 -0
  90. package/dist/cli/ui/components/CommandInput.js +200 -0
  91. package/dist/cli/ui/components/CommandSuggestionList.js +20 -0
  92. package/dist/cli/ui/components/Markdown.js +423 -0
  93. package/dist/cli/ui/components/MessageList.js +34 -0
  94. package/dist/cli/ui/components/StatusBannerLine.js +7 -0
  95. package/dist/cli/ui/components/TodoDrawer.js +60 -0
  96. package/dist/cli/ui/components/WelcomeMessage.js +14 -0
  97. package/dist/cli/ui/components/animations/StretchingThinking.js +51 -0
  98. package/dist/cli/ui/components/animations/ThinkingWave.js +15 -0
  99. package/dist/cli/ui/components/animations/TypeIndicator.js +30 -0
  100. package/dist/cli/ui/components/layout/SplitPane.js +11 -0
  101. package/dist/cli/ui/components/messageList/MessageItem.js +27 -0
  102. package/dist/cli/ui/components/messageList/QueuePreviewList.js +11 -0
  103. package/dist/cli/ui/components/messageList/items/EmphasisMessageItem.js +20 -0
  104. package/dist/cli/ui/components/messageList/items/InterruptMessageItem.js +10 -0
  105. package/dist/cli/ui/components/messageList/items/LightweightMessageItem.js +12 -0
  106. package/dist/cli/ui/components/messageList/items/StandardMessageItem.js +23 -0
  107. package/dist/cli/ui/components/messageList/items/WelcomeMessageItem.js +7 -0
  108. package/dist/cli/ui/components/messageList/messageListLayout.js +27 -0
  109. package/dist/cli/ui/components/messageList/streaming.js +51 -0
  110. package/dist/cli/ui/components/messageList/types.js +2 -0
  111. package/dist/cli/ui/components/messageList/utils.js +7 -0
  112. package/dist/cli/ui/components/sidebar/FileContext.js +8 -0
  113. package/dist/cli/ui/components/sidebar/MissionControl.js +8 -0
  114. package/dist/cli/ui/config.js +59 -0
  115. package/dist/cli/ui/hooks/useCommandLifecycle.js +110 -0
  116. package/dist/cli/ui/hooks/useCommandSuggestions.js +87 -0
  117. package/dist/cli/ui/hooks/useInputHistory.js +57 -0
  118. package/dist/cli/ui/hooks/useLoopEvents.js +382 -0
  119. package/dist/cli/ui/hooks/useLoopState.js +73 -0
  120. package/dist/cli/ui/hooks/useOnionExit.js +31 -0
  121. package/dist/cli/ui/hooks/useTerminalDimensions.js +34 -0
  122. package/dist/cli/ui/index.js +136 -0
  123. package/dist/cli/ui/selection/bus.js +35 -0
  124. package/dist/cli/ui/status/formatStatusBanner.js +8 -0
  125. package/dist/cli/ui/store/context.js +17 -0
  126. package/dist/cli/ui/store/reducer.js +264 -0
  127. package/dist/cli/ui/store/types.js +81 -0
  128. package/dist/cli/ui/styles/theme.js +295 -0
  129. package/dist/cli/ui/types.js +2 -0
  130. package/dist/cli/ui/utils/sanitizer.js +122 -0
  131. package/dist/cli/ui/utils/transcript.js +28 -0
  132. package/dist/cli/utils/asyncQueue.js +125 -0
  133. package/dist/cli/utils/audit-scope.js +10 -0
  134. package/dist/cli/utils/detectors/index.js +38 -0
  135. package/dist/cli/utils/llm-output.js +34 -0
  136. package/dist/cli/utils/outcome-reporter.js +17 -0
  137. package/dist/cli/utils/safe-fs.js +184 -0
  138. package/dist/cli/utils/verify-resolver.js +34 -0
  139. package/dist/cli/utils/worktree-prepare-resolver.js +18 -0
  140. package/dist/core/adapters/fs/atomic-file-writer.js +129 -0
  141. package/dist/core/adapters/fs/file-adapter.js +95 -0
  142. package/dist/core/adapters/fs/filesystem.js +31 -0
  143. package/dist/core/adapters/fs/index.js +5 -0
  144. package/dist/core/adapters/fs/node-fs.js +7 -0
  145. package/dist/core/adapters/fs/readonly-filesystem.js +23 -0
  146. package/dist/core/adapters/git/git-adapter.js +704 -0
  147. package/dist/core/adapters/git/git-runner.js +119 -0
  148. package/dist/core/adapters/git/lock-manager.js +314 -0
  149. package/dist/core/adapters/git/types.js +2 -0
  150. package/dist/core/adapters/path/index.js +2 -0
  151. package/dist/core/adapters/path/path-adapter.js +23 -0
  152. package/dist/core/ast/guard.js +116 -0
  153. package/dist/core/ast/index.js +4 -0
  154. package/dist/core/ast/parser.js +284 -0
  155. package/dist/core/ast/validator.js +46 -0
  156. package/dist/core/backends/salmon-loop/task-executor.js +68 -0
  157. package/dist/core/checkpoint-domain/manifest-store.js +379 -0
  158. package/dist/core/checkpoint-domain/service.js +84 -0
  159. package/dist/core/checkpoint-domain/types.js +2 -0
  160. package/dist/core/config/defaults.js +50 -0
  161. package/dist/core/config/errors.js +11 -0
  162. package/dist/core/config/file-format.js +108 -0
  163. package/dist/core/config/index.js +7 -0
  164. package/dist/core/config/limits.js +77 -0
  165. package/dist/core/config/load.js +34 -0
  166. package/dist/core/config/normalize.js +35 -0
  167. package/dist/core/config/paths.js +20 -0
  168. package/dist/core/config/redact.js +16 -0
  169. package/dist/core/config/resolve-env.js +43 -0
  170. package/dist/core/config/resolve-llm.js +130 -0
  171. package/dist/core/config/resolve.js +68 -0
  172. package/dist/core/config/resolvers/ast-validation.js +8 -0
  173. package/dist/core/config/resolvers/context.js +21 -0
  174. package/dist/core/config/resolvers/observability.js +45 -0
  175. package/dist/core/config/resolvers/output.js +8 -0
  176. package/dist/core/config/resolvers/permission-mode.js +6 -0
  177. package/dist/core/config/resolvers/security.js +14 -0
  178. package/dist/core/config/resolvers/server.js +36 -0
  179. package/dist/core/config/resolvers/tool-authorization.js +39 -0
  180. package/dist/core/config/resolvers/ui.js +26 -0
  181. package/dist/core/config/types/config-file.js +2 -0
  182. package/dist/core/config/types/primitives.js +9 -0
  183. package/dist/core/config/types/resolved.js +2 -0
  184. package/dist/core/config/types.js +4 -0
  185. package/dist/core/config/validate.js +852 -0
  186. package/dist/core/context/assembly/default-prompt-assembler.js +7 -0
  187. package/dist/core/context/assembly/prompt-assembler.js +2 -0
  188. package/dist/core/context/ast/import-extractor.js +28 -0
  189. package/dist/core/context/ast/module-resolver.js +61 -0
  190. package/dist/core/context/ast/source-outline.js +25 -0
  191. package/dist/core/context/audit-constants.js +23 -0
  192. package/dist/core/context/audit.js +54 -0
  193. package/dist/core/context/budget/dynamic-adjuster.js +149 -0
  194. package/dist/core/context/budget/example-integration.js +49 -0
  195. package/dist/core/context/budget/integration.js +93 -0
  196. package/dist/core/context/builder.js +289 -0
  197. package/dist/core/context/cache/errors.js +16 -0
  198. package/dist/core/context/cache/incremental-updater.js +131 -0
  199. package/dist/core/context/cache/index.js +25 -0
  200. package/dist/core/context/cache/path-resolver.js +127 -0
  201. package/dist/core/context/cache/prompt-caching.js +207 -0
  202. package/dist/core/context/cache/store-factory.js +63 -0
  203. package/dist/core/context/cache/store.js +193 -0
  204. package/dist/core/context/cache/types.js +15 -0
  205. package/dist/core/context/compression/js-like-comments.js +139 -0
  206. package/dist/core/context/compression/smart-compress.js +61 -0
  207. package/dist/core/context/compression/whitespace.js +26 -0
  208. package/dist/core/context/dependencies.js +102 -0
  209. package/dist/core/context/effectiveness/index.js +25 -0
  210. package/dist/core/context/effectiveness/tracker.js +253 -0
  211. package/dist/core/context/effectiveness/types.js +15 -0
  212. package/dist/core/context/formatters/index.js +7 -0
  213. package/dist/core/context/formatters/json-converter.js +662 -0
  214. package/dist/core/context/formatters/types.js +6 -0
  215. package/dist/core/context/formatters/xml-context.js +296 -0
  216. package/dist/core/context/gatherers/architecture-gatherer.js +75 -0
  217. package/dist/core/context/gatherers/artifact-gatherer.js +53 -0
  218. package/dist/core/context/gatherers/ast-gatherer.js +370 -0
  219. package/dist/core/context/gatherers/ghost-dependency-gatherer.js +46 -0
  220. package/dist/core/context/gatherers/git-diff-gatherer.js +91 -0
  221. package/dist/core/context/gatherers/git-history-gatherer.js +57 -0
  222. package/dist/core/context/gatherers/knowledge-gatherer.js +101 -0
  223. package/dist/core/context/gatherers/metadata-gatherer.js +59 -0
  224. package/dist/core/context/gatherers/primary-text-gatherer.js +36 -0
  225. package/dist/core/context/gatherers/ripgrep-gatherer.js +104 -0
  226. package/dist/core/context/hash.js +52 -0
  227. package/dist/core/context/index.js +3 -0
  228. package/dist/core/context/keywords.js +179 -0
  229. package/dist/core/context/policies/budget-policy.js +36 -0
  230. package/dist/core/context/policies/pack-until-full.js +419 -0
  231. package/dist/core/context/scoring/relevance.js +191 -0
  232. package/dist/core/context/service-deps.js +32 -0
  233. package/dist/core/context/service-helpers.js +32 -0
  234. package/dist/core/context/service.js +265 -0
  235. package/dist/core/context/steps/context-budget.js +157 -0
  236. package/dist/core/context/steps/context-gather.js +71 -0
  237. package/dist/core/context/steps/context-primary.js +19 -0
  238. package/dist/core/context/steps/context-promotion.js +78 -0
  239. package/dist/core/context/steps/context-targets.js +85 -0
  240. package/dist/core/context/steps/types.js +2 -0
  241. package/dist/core/context/summarization/index.js +27 -0
  242. package/dist/core/context/summarization/prompts.js +80 -0
  243. package/dist/core/context/summarization/summarizer.js +377 -0
  244. package/dist/core/context/summarization/types.js +29 -0
  245. package/dist/core/context/targeting/churn-policy.js +27 -0
  246. package/dist/core/context/targeting/target-resolver.js +491 -0
  247. package/dist/core/context/token/adaptive-budget.js +364 -0
  248. package/dist/core/context/token/cache.js +163 -0
  249. package/dist/core/context/token/counter.js +190 -0
  250. package/dist/core/context/token/encoding-registry.js +173 -0
  251. package/dist/core/context/token/index.js +31 -0
  252. package/dist/core/context/token/token-budget.js +213 -0
  253. package/dist/core/context/token/types.js +10 -0
  254. package/dist/core/context/truncation/index.js +23 -0
  255. package/dist/core/context/truncation/semantic-truncator.js +103 -0
  256. package/dist/core/context/truncation/strategies/error-stack.js +94 -0
  257. package/dist/core/context/truncation/strategies/generic.js +48 -0
  258. package/dist/core/context/truncation/strategies/git-diff.js +99 -0
  259. package/dist/core/context/truncation/strategies/index.js +10 -0
  260. package/dist/core/context/truncation/strategies/json.js +142 -0
  261. package/dist/core/context/truncation/strategies/log.js +131 -0
  262. package/dist/core/context/truncation/strategies/test-result.js +140 -0
  263. package/dist/core/context/truncation/type-detector.js +133 -0
  264. package/dist/core/context/truncation/types.js +16 -0
  265. package/dist/core/context/types.js +2 -0
  266. package/dist/core/extensions/index.js +118 -0
  267. package/dist/core/extensions/load.js +36 -0
  268. package/dist/core/extensions/merge.js +29 -0
  269. package/dist/core/extensions/paths.js +40 -0
  270. package/dist/core/extensions/redact.js +37 -0
  271. package/dist/core/extensions/schemas.js +70 -0
  272. package/dist/core/extensions/types.js +2 -0
  273. package/dist/core/facades/cli-authorization-allowlist.js +3 -0
  274. package/dist/core/facades/cli-authorization-non-interactive.js +3 -0
  275. package/dist/core/facades/cli-authorization-provider.js +2 -0
  276. package/dist/core/facades/cli-chat.js +11 -0
  277. package/dist/core/facades/cli-command-allowlist.js +3 -0
  278. package/dist/core/facades/cli-command-chat.js +8 -0
  279. package/dist/core/facades/cli-command-checkpoint.js +3 -0
  280. package/dist/core/facades/cli-command-config.js +10 -0
  281. package/dist/core/facades/cli-command-dispatcher.js +2 -0
  282. package/dist/core/facades/cli-command-parallel.js +8 -0
  283. package/dist/core/facades/cli-command-session.js +2 -0
  284. package/dist/core/facades/cli-command-tool-names.js +6 -0
  285. package/dist/core/facades/cli-context.js +8 -0
  286. package/dist/core/facades/cli-headless.js +3 -0
  287. package/dist/core/facades/cli-observability.js +3 -0
  288. package/dist/core/facades/cli-program-bootstrap.js +2 -0
  289. package/dist/core/facades/cli-reporters.js +5 -0
  290. package/dist/core/facades/cli-run-execute.js +3 -0
  291. package/dist/core/facades/cli-run-handler.js +7 -0
  292. package/dist/core/facades/cli-run-headless-error-writer.js +2 -0
  293. package/dist/core/facades/cli-run-loop-params.js +2 -0
  294. package/dist/core/facades/cli-run-persist-session.js +2 -0
  295. package/dist/core/facades/cli-run-runtime-llm.js +5 -0
  296. package/dist/core/facades/cli-serve.js +21 -0
  297. package/dist/core/facades/cli-slash-runtime.js +9 -0
  298. package/dist/core/facades/cli-subagent.js +2 -0
  299. package/dist/core/facades/cli-ui.js +5 -0
  300. package/dist/core/facades/cli-utils-llm-output.js +3 -0
  301. package/dist/core/facades/cli-utils-path.js +2 -0
  302. package/dist/core/facades/cli-utils-worktree.js +2 -0
  303. package/dist/core/failure/diagnostics.js +221 -0
  304. package/dist/core/feedback/index.js +28 -0
  305. package/dist/core/feedback/parsers.js +59 -0
  306. package/dist/core/feedback/patterns.js +26 -0
  307. package/dist/core/feedback/types.js +2 -0
  308. package/dist/core/grizzco/domain/grizzco-types.js +41 -0
  309. package/dist/core/grizzco/dsl/DecisionEngine.js +149 -0
  310. package/dist/core/grizzco/dsl/MicroTaskRunner.js +39 -0
  311. package/dist/core/grizzco/dsl/llm-strategy.js +80 -0
  312. package/dist/core/grizzco/dsl/strategies.js +69 -0
  313. package/dist/core/grizzco/dsl/types.js +2 -0
  314. package/dist/core/grizzco/engine/observability/event-adapter.js +41 -0
  315. package/dist/core/grizzco/engine/observability/index.js +3 -0
  316. package/dist/core/grizzco/engine/observability/loop-telemetry.js +51 -0
  317. package/dist/core/grizzco/engine/outcome/index.js +2 -0
  318. package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +167 -0
  319. package/dist/core/grizzco/engine/pipeline/pipeline.js +335 -0
  320. package/dist/core/grizzco/engine/pipeline/types.js +2 -0
  321. package/dist/core/grizzco/engine/transaction/attempt-failure.js +242 -0
  322. package/dist/core/grizzco/engine/transaction/authorization-summary.js +44 -0
  323. package/dist/core/grizzco/engine/transaction/index.js +3 -0
  324. package/dist/core/grizzco/engine/transaction/report-mapper.js +50 -0
  325. package/dist/core/grizzco/engine/transaction/retry-policy.js +19 -0
  326. package/dist/core/grizzco/engine/transaction/runner-builder.js +45 -0
  327. package/dist/core/grizzco/engine/transaction/session.js +58 -0
  328. package/dist/core/grizzco/engine/transaction/transaction-runner.js +193 -0
  329. package/dist/core/grizzco/engine/transaction/types.js +2 -0
  330. package/dist/core/grizzco/execution/Executor.js +58 -0
  331. package/dist/core/grizzco/execution/RejectionManager.js +71 -0
  332. package/dist/core/grizzco/execution/WorkerFactory.js +31 -0
  333. package/dist/core/grizzco/flows/SalmonLoopFlow.js +102 -0
  334. package/dist/core/grizzco/runtime/apply-back-runtime.js +136 -0
  335. package/dist/core/grizzco/runtime/apply-back-utils.js +13 -0
  336. package/dist/core/grizzco/runtime/host/host-runner.js +99 -0
  337. package/dist/core/grizzco/runtime/host/index.js +2 -0
  338. package/dist/core/grizzco/runtime/host/types.js +2 -0
  339. package/dist/core/grizzco/services/CachedService.js +42 -0
  340. package/dist/core/grizzco/services/implementations/default/GitConfigService.js +38 -0
  341. package/dist/core/grizzco/services/implementations/mock/MockLockService.js +11 -0
  342. package/dist/core/grizzco/services/implementations/mock/MockUserQuotaService.js +11 -0
  343. package/dist/core/grizzco/services/registry.js +30 -0
  344. package/dist/core/grizzco/services/types.js +2 -0
  345. package/dist/core/grizzco/steps/answer.js +75 -0
  346. package/dist/core/grizzco/steps/apply-back.js +46 -0
  347. package/dist/core/grizzco/steps/apply.js +136 -0
  348. package/dist/core/grizzco/steps/ast-validate.js +37 -0
  349. package/dist/core/grizzco/steps/audit.js +311 -0
  350. package/dist/core/grizzco/steps/context.js +74 -0
  351. package/dist/core/grizzco/steps/display-answer.js +6 -0
  352. package/dist/core/grizzco/steps/display-report.js +158 -0
  353. package/dist/core/grizzco/steps/display-research.js +6 -0
  354. package/dist/core/grizzco/steps/displayReview.js +6 -0
  355. package/dist/core/grizzco/steps/explore.js +245 -0
  356. package/dist/core/grizzco/steps/extractIssues.js +27 -0
  357. package/dist/core/grizzco/steps/generateFixPlan.js +13 -0
  358. package/dist/core/grizzco/steps/generateReview.js +71 -0
  359. package/dist/core/grizzco/steps/patch.js +220 -0
  360. package/dist/core/grizzco/steps/plan.js +191 -0
  361. package/dist/core/grizzco/steps/preflight.js +93 -0
  362. package/dist/core/grizzco/steps/prepare-deps.js +49 -0
  363. package/dist/core/grizzco/steps/read-only-shrink.js +4 -0
  364. package/dist/core/grizzco/steps/research.js +188 -0
  365. package/dist/core/grizzco/steps/rollback.js +138 -0
  366. package/dist/core/grizzco/steps/shrink.js +64 -0
  367. package/dist/core/grizzco/steps/validate.js +40 -0
  368. package/dist/core/grizzco/steps/verify.js +136 -0
  369. package/dist/core/grizzco/validation/AstValidationService.js +133 -0
  370. package/dist/core/grizzco/validation/ContextValidator.js +17 -0
  371. package/dist/core/grizzco/validation/ast-validation-policy.js +11 -0
  372. package/dist/core/grizzco/workers/direct-write-worker.js +44 -0
  373. package/dist/core/grizzco/workers/git-apply-worker.js +75 -0
  374. package/dist/core/grizzco/workers/i-merge-worker.js +2 -0
  375. package/dist/core/grizzco/workers/mm-three-way-worker.js +117 -0
  376. package/dist/core/grizzco/workers/no-op-worker.js +18 -0
  377. package/dist/core/grizzco/workers/overwrite-binary-worker.js +29 -0
  378. package/dist/core/grizzco/workers/strata-sync-worker.js +69 -0
  379. package/dist/core/grizzco/workers/three-way-merge-worker.js +84 -0
  380. package/dist/core/grizzco/workers/three-way-staged-worker.js +93 -0
  381. package/dist/core/grizzco/workers/union-merge-worker.js +71 -0
  382. package/dist/core/history/input-history.js +55 -0
  383. package/dist/core/intent/chat-intent.js +250 -0
  384. package/dist/core/interaction/events/bus.js +52 -0
  385. package/dist/core/interaction/model/events.js +2 -0
  386. package/dist/core/interaction/model/index.js +3 -0
  387. package/dist/core/interaction/model/task-state.js +9 -0
  388. package/dist/core/interaction/model/transition-policy.js +50 -0
  389. package/dist/core/interaction/model/types.js +2 -0
  390. package/dist/core/interaction/orchestration/facade.js +190 -0
  391. package/dist/core/interaction/orchestration/index.js +2 -0
  392. package/dist/core/interaction/orchestration/store.js +32 -0
  393. package/dist/core/interaction/sync/task-sync-engine.js +57 -0
  394. package/dist/core/interaction/turn-stop-reason.js +27 -0
  395. package/dist/core/language-support/index.js +3 -0
  396. package/dist/core/language-support/orchestrator.js +37 -0
  397. package/dist/core/language-support/strategies/extension-candidate-strategy.js +27 -0
  398. package/dist/core/language-support/strategies/index.js +3 -0
  399. package/dist/core/language-support/strategies/language-query-strategy.js +26 -0
  400. package/dist/core/llm/ai-sdk/chat-executor.js +88 -0
  401. package/dist/core/llm/ai-sdk/langfuse-headers.js +28 -0
  402. package/dist/core/llm/ai-sdk/message-mapper.js +240 -0
  403. package/dist/core/llm/ai-sdk/observation-context.js +16 -0
  404. package/dist/core/llm/ai-sdk/provider-factory.js +29 -0
  405. package/dist/core/llm/ai-sdk/request-params.js +18 -0
  406. package/dist/core/llm/ai-sdk/request-runtime.js +168 -0
  407. package/dist/core/llm/ai-sdk/result-mapper.js +31 -0
  408. package/dist/core/llm/ai-sdk/retry-classifier.js +82 -0
  409. package/dist/core/llm/ai-sdk/retry-executor.js +38 -0
  410. package/dist/core/llm/ai-sdk.js +92 -0
  411. package/dist/core/llm/audit.js +2 -0
  412. package/dist/core/llm/base-url.js +18 -0
  413. package/dist/core/llm/contracts/repair.js +68 -0
  414. package/dist/core/llm/errors.js +172 -0
  415. package/dist/core/llm/factory.js +21 -0
  416. package/dist/core/llm/http/index.js +2 -0
  417. package/dist/core/llm/index.js +6 -0
  418. package/dist/core/llm/message-composition.js +25 -0
  419. package/dist/core/llm/openai.js +69 -0
  420. package/dist/core/llm/output-policy.js +192 -0
  421. package/dist/core/llm/phase-router.js +55 -0
  422. package/dist/core/llm/redact.js +37 -0
  423. package/dist/core/llm/registry.js +81 -0
  424. package/dist/core/llm/retry-utils.js +114 -0
  425. package/dist/core/llm/stream-utils.js +87 -0
  426. package/dist/core/llm/utils.js +82 -0
  427. package/dist/core/observability/audit-file.js +199 -0
  428. package/dist/core/observability/audit-trail.js +125 -0
  429. package/dist/core/observability/authorization-decisions.js +54 -0
  430. package/dist/core/observability/debug-artifacts.js +61 -0
  431. package/dist/core/observability/error-envelope.js +63 -0
  432. package/dist/core/observability/error-mapping.js +271 -0
  433. package/dist/core/observability/ignored-error.js +6 -0
  434. package/dist/core/observability/logger.js +457 -0
  435. package/dist/core/observability/loop-event-reporter.js +46 -0
  436. package/dist/core/observability/monitor.js +240 -0
  437. package/dist/core/observability/run-outcome-reporter.js +15 -0
  438. package/dist/core/observability/token-usage.js +36 -0
  439. package/dist/core/observability/ui-log-sanitize.js +35 -0
  440. package/dist/core/patch/aggregator.js +93 -0
  441. package/dist/core/patch/diff.js +298 -0
  442. package/dist/core/permission-gate/default-gate.js +115 -0
  443. package/dist/core/permission-gate/gate.js +2 -0
  444. package/dist/core/permission-gate/types.js +2 -0
  445. package/dist/core/plan/index.js +2 -0
  446. package/dist/core/plan/manager.js +123 -0
  447. package/dist/core/plan/markdown-editor.js +238 -0
  448. package/dist/core/plan/storage.js +75 -0
  449. package/dist/core/plan/types.js +2 -0
  450. package/dist/core/plugin/interface.js +2 -0
  451. package/dist/core/plugin/loader.js +130 -0
  452. package/dist/core/plugin/registry.js +90 -0
  453. package/dist/core/plugin/validator.js +98 -0
  454. package/dist/core/prompts/registry.js +189 -0
  455. package/dist/core/prompts/runtime.js +69 -0
  456. package/dist/core/prompts/schema.js +2 -0
  457. package/dist/core/prompts/templates/phases/explore_user.hbs +26 -0
  458. package/dist/core/prompts/templates/phases/patch_user.hbs +57 -0
  459. package/dist/core/prompts/templates/phases/plan_user.hbs +33 -0
  460. package/dist/core/prompts/templates/system/_context_json_legend.hbs +21 -0
  461. package/dist/core/prompts/templates/system/_tool_defs.hbs +60 -0
  462. package/dist/core/prompts/templates/system/explore_system.hbs +26 -0
  463. package/dist/core/prompts/templates/system/main_system.hbs +18 -0
  464. package/dist/core/prompts/templates/system/patch_system.hbs +10 -0
  465. package/dist/core/prompts/templates/system/plan_system.hbs +1 -0
  466. package/dist/core/prompts/templates/system/reflection.hbs +39 -0
  467. package/dist/core/protocols/a2a/agent-card.js +30 -0
  468. package/dist/core/protocols/a2a/mapper.js +14 -0
  469. package/dist/core/protocols/a2a/sdk/auth-middleware.js +31 -0
  470. package/dist/core/protocols/a2a/sdk/executor.js +301 -0
  471. package/dist/core/protocols/a2a/sdk/server.js +24 -0
  472. package/dist/core/protocols/a2a/task-projection.js +45 -0
  473. package/dist/core/protocols/acp/acp-command-runner.js +204 -0
  474. package/dist/core/protocols/acp/acp-filesystem.js +43 -0
  475. package/dist/core/protocols/acp/checkpoint-meta.js +2 -0
  476. package/dist/core/protocols/acp/formal-agent.js +1201 -0
  477. package/dist/core/protocols/acp/handlers.js +51 -0
  478. package/dist/core/protocols/acp/permission-provider.js +122 -0
  479. package/dist/core/protocols/acp/stdio-server.js +116 -0
  480. package/dist/core/reflection/engine.js +55 -0
  481. package/dist/core/reflection/types.js +2 -0
  482. package/dist/core/runtime/agent-server-runtime.js +88 -0
  483. package/dist/core/runtime/bun-runtime.js +26 -0
  484. package/dist/core/runtime/command-runner-context.js +16 -0
  485. package/dist/core/runtime/exit-codes.js +11 -0
  486. package/dist/core/runtime/fastify-fetch-bridge.js +51 -0
  487. package/dist/core/runtime/fastify-server-bundle.js +26 -0
  488. package/dist/core/runtime/initialize.js +132 -0
  489. package/dist/core/runtime/loop-finalize.js +71 -0
  490. package/dist/core/runtime/loop-run-lifecycle.js +73 -0
  491. package/dist/core/runtime/loop-run-reporter.js +19 -0
  492. package/dist/core/runtime/loop-runtime-config.js +26 -0
  493. package/dist/core/runtime/loop-session-runner.js +30 -0
  494. package/dist/core/runtime/loop.js +84 -0
  495. package/dist/core/runtime/paths.js +84 -0
  496. package/dist/core/runtime/process-runner.js +16 -0
  497. package/dist/core/runtime/process-types.js +2 -0
  498. package/dist/core/runtime/semaphore.js +41 -0
  499. package/dist/core/runtime/sidecar-fastify-plugin.js +35 -0
  500. package/dist/core/runtime/sidecar-paths.js +47 -0
  501. package/dist/core/runtime/sidecar-route-catalog.js +103 -0
  502. package/dist/core/runtime/spawn-command.js +392 -0
  503. package/dist/core/runtime/spawn-interactive.js +71 -0
  504. package/dist/core/security/redaction.js +160 -0
  505. package/dist/core/session/compression.js +323 -0
  506. package/dist/core/session/flow.js +85 -0
  507. package/dist/core/session/manager.js +313 -0
  508. package/dist/core/session/pruning-strategy.js +153 -0
  509. package/dist/core/session/session-context-builder.js +122 -0
  510. package/dist/core/session/summary-sync.js +82 -0
  511. package/dist/core/session/token-tracker.js +82 -0
  512. package/dist/core/session/types.js +2 -0
  513. package/dist/core/skills/bridge.js +33 -0
  514. package/dist/core/skills/index.js +8 -0
  515. package/dist/core/skills/loader.js +80 -0
  516. package/dist/core/skills/parser.js +66 -0
  517. package/dist/core/skills/runtime/MicroTaskRunner.js +102 -0
  518. package/dist/core/skills/runtime/SkillRunner.js +108 -0
  519. package/dist/core/skills/strategy.js +29 -0
  520. package/dist/core/skills/types.js +2 -0
  521. package/dist/core/slash/index.js +6 -0
  522. package/dist/core/slash/parser.js +33 -0
  523. package/dist/core/slash/registry.js +78 -0
  524. package/dist/core/slash/router.js +76 -0
  525. package/dist/core/slash/steps/slash-decide.js +19 -0
  526. package/dist/core/slash/steps/slash-execute.js +73 -0
  527. package/dist/core/slash/steps/types.js +2 -0
  528. package/dist/core/slash/strategy.js +33 -0
  529. package/dist/core/slash/types.js +2 -0
  530. package/dist/core/strata/checkpoint/manager.js +492 -0
  531. package/dist/core/strata/checkpoint/snapshot-audit.js +88 -0
  532. package/dist/core/strata/checkpoint/snapshot-create.js +79 -0
  533. package/dist/core/strata/checkpoint/snapshot-write-tree.js +72 -0
  534. package/dist/core/strata/engine/shadow-merge-engine.js +394 -0
  535. package/dist/core/strata/index.js +15 -0
  536. package/dist/core/strata/interaction/content-guardian.js +59 -0
  537. package/dist/core/strata/interaction/file-system-provider.js +89 -0
  538. package/dist/core/strata/layers/file-state-resolver.js +157 -0
  539. package/dist/core/strata/layers/immutable-git-layer.js +42 -0
  540. package/dist/core/strata/layers/shadow-driver/copy-backend.js +114 -0
  541. package/dist/core/strata/layers/shadow-driver/env.js +29 -0
  542. package/dist/core/strata/layers/shadow-driver/error-classifier.js +41 -0
  543. package/dist/core/strata/layers/shadow-driver/index.js +17 -0
  544. package/dist/core/strata/layers/shadow-driver/readonly-lock.js +221 -0
  545. package/dist/core/strata/layers/shadow-driver/shadow-driver.js +234 -0
  546. package/dist/core/strata/layers/shadow-driver/strategy.js +86 -0
  547. package/dist/core/strata/layers/sidecar-layer.js +96 -0
  548. package/dist/core/strata/layers/worktree.js +240 -0
  549. package/dist/core/strata/runtime/environment.js +377 -0
  550. package/dist/core/strata/runtime/synchronizer.js +819 -0
  551. package/dist/core/strata/types.js +46 -0
  552. package/dist/core/streaming/canonical/canonical-responses-event-emitter.js +326 -0
  553. package/dist/core/streaming/canonical/function-call-item-id.js +13 -0
  554. package/dist/core/streaming/canonical/parts-from-llm-stream-chunk.js +54 -0
  555. package/dist/core/streaming/canonical/responses-event-emitter.js +127 -0
  556. package/dist/core/streaming/canonical/responses-events.js +2 -0
  557. package/dist/core/streaming/normalized-events.js +9 -0
  558. package/dist/core/streaming/normalized-from-text.js +47 -0
  559. package/dist/core/streaming/stream-assembler.js +347 -0
  560. package/dist/core/structured-output/index.js +3 -0
  561. package/dist/core/structured-output/json-extract.js +70 -0
  562. package/dist/core/structured-output/json-schema-validator.js +90 -0
  563. package/dist/core/structured-output/types.js +2 -0
  564. package/dist/core/sub-agent/artifacts/store.js +141 -0
  565. package/dist/core/sub-agent/artifacts/types.js +2 -0
  566. package/dist/core/sub-agent/controller.js +69 -0
  567. package/dist/core/sub-agent/core/loop.js +79 -0
  568. package/dist/core/sub-agent/core/manager.js +246 -0
  569. package/dist/core/sub-agent/registry-defaults.js +52 -0
  570. package/dist/core/sub-agent/registry.js +35 -0
  571. package/dist/core/sub-agent/tools/task-spawn.js +29 -0
  572. package/dist/core/sub-agent/types.js +23 -0
  573. package/dist/core/target-runtime/command-resolver.js +42 -0
  574. package/dist/core/target-runtime/index.js +3 -0
  575. package/dist/core/target-runtime/profile.js +73 -0
  576. package/dist/core/testgen/detector.js +17 -0
  577. package/dist/core/testgen/index.js +38 -0
  578. package/dist/core/testgen/templates.js +46 -0
  579. package/dist/core/tools/audit.js +140 -0
  580. package/dist/core/tools/authorization/types.js +2 -0
  581. package/dist/core/tools/budget.js +118 -0
  582. package/dist/core/tools/builtin/artifact.js +29 -0
  583. package/dist/core/tools/builtin/ast-grep.js +107 -0
  584. package/dist/core/tools/builtin/ast.js +62 -0
  585. package/dist/core/tools/builtin/code-search/backends/powershell.js +84 -0
  586. package/dist/core/tools/builtin/code-search/backends/rg.js +85 -0
  587. package/dist/core/tools/builtin/code-search/executor.js +87 -0
  588. package/dist/core/tools/builtin/code-search/parse/plain-grep.js +59 -0
  589. package/dist/core/tools/builtin/code-search/parse/rg-json.js +31 -0
  590. package/dist/core/tools/builtin/code-search/spec.js +82 -0
  591. package/dist/core/tools/builtin/fs.js +243 -0
  592. package/dist/core/tools/builtin/git.js +118 -0
  593. package/dist/core/tools/builtin/index.js +80 -0
  594. package/dist/core/tools/builtin/interaction.js +120 -0
  595. package/dist/core/tools/builtin/knowledge.js +98 -0
  596. package/dist/core/tools/builtin/plan.js +148 -0
  597. package/dist/core/tools/builtin/proposal.js +207 -0
  598. package/dist/core/tools/builtin/shell.js +71 -0
  599. package/dist/core/tools/builtin/verify.js +41 -0
  600. package/dist/core/tools/capability/executor.js +84 -0
  601. package/dist/core/tools/capability/runner.js +50 -0
  602. package/dist/core/tools/capability/types.js +2 -0
  603. package/dist/core/tools/dispatcher.js +80 -0
  604. package/dist/core/tools/headless-payload.js +37 -0
  605. package/dist/core/tools/loader.js +100 -0
  606. package/dist/core/tools/mapper.js +142 -0
  607. package/dist/core/tools/mcp/client.js +308 -0
  608. package/dist/core/tools/mcp/loader.js +110 -0
  609. package/dist/core/tools/mcp/schema.js +54 -0
  610. package/dist/core/tools/mcp/streamable-http.js +101 -0
  611. package/dist/core/tools/mcp/types.js +26 -0
  612. package/dist/core/tools/parallel/isolation.js +25 -0
  613. package/dist/core/tools/parallel/lock-manager.js +124 -0
  614. package/dist/core/tools/parallel/persistence.js +126 -0
  615. package/dist/core/tools/parallel/plan-builder.js +66 -0
  616. package/dist/core/tools/parallel/plan.js +2 -0
  617. package/dist/core/tools/parallel/refs.js +7 -0
  618. package/dist/core/tools/parallel/resolve-args.js +50 -0
  619. package/dist/core/tools/parallel/resource-helpers.js +35 -0
  620. package/dist/core/tools/parallel/resources.js +2 -0
  621. package/dist/core/tools/parallel/scheduler.js +372 -0
  622. package/dist/core/tools/parser.js +89 -0
  623. package/dist/core/tools/permissions/permission-rules.js +503 -0
  624. package/dist/core/tools/plugins/loader.js +102 -0
  625. package/dist/core/tools/policy.js +87 -0
  626. package/dist/core/tools/registry.js +29 -0
  627. package/dist/core/tools/router.js +514 -0
  628. package/dist/core/tools/sanitize.js +78 -0
  629. package/dist/core/tools/schema-utils.js +71 -0
  630. package/dist/core/tools/session.js +1105 -0
  631. package/dist/core/tools/streaming/ToolCallAccumulator.js +64 -0
  632. package/dist/core/tools/types.js +2 -0
  633. package/dist/core/types/authorization.js +2 -0
  634. package/dist/core/types/context.js +2 -0
  635. package/dist/core/types/errors.js +29 -0
  636. package/dist/core/types/execution.js +65 -0
  637. package/dist/core/types/index.js +9 -0
  638. package/dist/core/types/llm.js +9 -0
  639. package/dist/core/types/loop.js +2 -0
  640. package/dist/core/types/planning.js +2 -0
  641. package/dist/core/types/runtime.js +2 -0
  642. package/dist/core/types/usage.js +2 -0
  643. package/dist/core/ui/kaomoji.js +5 -0
  644. package/dist/core/utils/path.js +116 -0
  645. package/dist/core/utils/platform-shell.js +10 -0
  646. package/dist/core/utils/sanitizer.js +107 -0
  647. package/dist/core/verification/runner.js +265 -0
  648. package/dist/integrations/langfuse/litellm-langfuse-outcome-reporter.js +272 -0
  649. package/dist/integrations/langfuse/outcome-proxy.js +68 -0
  650. package/dist/interfaces/cli/task-runner.js +11 -0
  651. package/dist/languages/typescript/index.js +178 -0
  652. package/dist/locales/en.js +679 -0
  653. package/dist/locales/index.js +11 -0
  654. package/dist/utils/eol.js +35 -0
  655. package/package.json +153 -0
@@ -0,0 +1,313 @@
1
+ import { randomBytes } from 'crypto';
2
+ import { join } from 'path';
3
+ import { FileAdapter } from '../adapters/fs/index.js';
4
+ import { SessionCompressor, CompressedSessionStore } from './compression.js';
5
+ import { SessionPruningEngine } from './pruning-strategy.js';
6
+ /**
7
+ * Manages chat session persistence and lifecycle.
8
+ * Storage: .salmonloop/chat-sessions/<id>.json
9
+ * Features: Auto-pruning, compression, intelligent cleanup
10
+ */
11
+ export class ChatSessionManager {
12
+ storageDir;
13
+ currentSession = null;
14
+ fileAdapter = new FileAdapter();
15
+ pruningEngine;
16
+ compressor;
17
+ compressedStore;
18
+ constructor(repoPath, pruningStrategy) {
19
+ this.storageDir = join(repoPath, '.salmonloop', 'chat-sessions');
20
+ this.pruningEngine = new SessionPruningEngine(pruningStrategy);
21
+ this.compressor = new SessionCompressor();
22
+ this.compressedStore = new CompressedSessionStore(repoPath);
23
+ }
24
+ /**
25
+ * Initialize storage directory
26
+ */
27
+ async init() {
28
+ await this.fileAdapter.mkdir(this.storageDir);
29
+ }
30
+ /**
31
+ * Create new chat session
32
+ */
33
+ async create(name) {
34
+ const id = randomBytes(8).toString('hex');
35
+ const now = Date.now();
36
+ const session = {
37
+ meta: {
38
+ id,
39
+ name: name || `Chat ${new Date().toLocaleString()}`,
40
+ repoPath: this.storageDir.replace(/\.salmonloop.*/, ''),
41
+ createdAt: now,
42
+ updatedAt: now,
43
+ totalIterations: 0,
44
+ successfulIterations: 0,
45
+ totalTokens: { input: 0, output: 0 },
46
+ snapshots: [],
47
+ },
48
+ messages: [],
49
+ iterations: [],
50
+ };
51
+ this.currentSession = session;
52
+ await this.save();
53
+ return session;
54
+ }
55
+ /**
56
+ * Load most recent session (by modification time)
57
+ */
58
+ async loadLast() {
59
+ const files = await this.fileAdapter.readdir(this.storageDir).catch(() => []);
60
+ const jsonFiles = files.filter((f) => f.endsWith('.json'));
61
+ if (jsonFiles.length === 0)
62
+ return null;
63
+ // Sort by modification time (descending)
64
+ const fileStats = await Promise.all(jsonFiles.map(async (f) => {
65
+ const filePath = join(this.storageDir, f);
66
+ const stats = await this.fileAdapter.stat(filePath);
67
+ return { name: f, mtime: stats.mtime.getTime() };
68
+ }));
69
+ fileStats.sort((a, b) => b.mtime - a.mtime);
70
+ const latestFile = fileStats[0].name;
71
+ return this.load(latestFile.replace('.json', ''));
72
+ }
73
+ /**
74
+ * Load session by ID (supports short ID prefix)
75
+ */
76
+ async load(id) {
77
+ let targetId = id;
78
+ // Support short ID matching
79
+ if (id.length < 16) {
80
+ const files = await this.fileAdapter.readdir(this.storageDir).catch(() => []);
81
+ const match = files.find((f) => f.startsWith(id) && f.endsWith('.json'));
82
+ if (match) {
83
+ targetId = match.replace('.json', '');
84
+ }
85
+ }
86
+ const filePath = join(this.storageDir, `${targetId}.json`);
87
+ try {
88
+ const data = await this.fileAdapter.readFile(filePath);
89
+ this.currentSession = JSON.parse(data);
90
+ return this.currentSession;
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ /**
97
+ * Resume a session (alias for load, with explicit name)
98
+ */
99
+ async resumeSession(id) {
100
+ const session = await this.load(id);
101
+ if (!session) {
102
+ throw new Error(`Session ${id} not found`);
103
+ }
104
+ return session;
105
+ }
106
+ /**
107
+ * Save current session to disk
108
+ */
109
+ async save() {
110
+ if (!this.currentSession)
111
+ return;
112
+ this.currentSession.meta.updatedAt = Date.now();
113
+ const filePath = join(this.storageDir, `${this.currentSession.meta.id}.json`);
114
+ await this.fileAdapter.writeFile(filePath, JSON.stringify(this.currentSession, null, 2));
115
+ }
116
+ /**
117
+ * Add message to current session
118
+ */
119
+ addMessage(message) {
120
+ if (!this.currentSession)
121
+ throw new Error('No active session');
122
+ this.currentSession.messages.push(message);
123
+ }
124
+ /**
125
+ * Add execution iteration to current session
126
+ */
127
+ addIteration(iteration, snapshotHash) {
128
+ if (!this.currentSession)
129
+ throw new Error('No active session');
130
+ const id = randomBytes(4).toString('hex');
131
+ this.currentSession.iterations.push({ ...iteration, id });
132
+ this.currentSession.meta.totalIterations++;
133
+ if (snapshotHash) {
134
+ this.currentSession.meta.snapshots.push({
135
+ id: snapshotHash,
136
+ iterationId: id,
137
+ timestamp: Date.now(),
138
+ });
139
+ }
140
+ return id;
141
+ }
142
+ /**
143
+ * Get conversation history (for LLM context)
144
+ */
145
+ getMessages() {
146
+ return this.currentSession?.messages || [];
147
+ }
148
+ /**
149
+ * Get messages with IDs for summarization.
150
+ * Ensures all messages have IDs.
151
+ */
152
+ getMessagesWithIds() {
153
+ const messages = this.currentSession?.messages || [];
154
+ return messages.map((m, i) => ({
155
+ ...m,
156
+ id: m.id || `msg-${i}-${m.timestamp}`,
157
+ }));
158
+ }
159
+ /**
160
+ * Get current session (throws if none)
161
+ */
162
+ getCurrent() {
163
+ if (!this.currentSession)
164
+ throw new Error('No active session');
165
+ return this.currentSession;
166
+ }
167
+ /**
168
+ * Get summary state for summarization.
169
+ */
170
+ getSummaryState() {
171
+ return this.currentSession?.meta.summaryState;
172
+ }
173
+ /**
174
+ * Update summary state after summarization.
175
+ */
176
+ updateSummaryState(state) {
177
+ if (!this.currentSession)
178
+ throw new Error('No active session');
179
+ this.currentSession.meta.summaryState = state;
180
+ }
181
+ /**
182
+ * Clear summary state (e.g., on session reset).
183
+ */
184
+ clearSummaryState() {
185
+ if (!this.currentSession)
186
+ return;
187
+ this.currentSession.meta.summaryState = undefined;
188
+ }
189
+ /**
190
+ * List all sessions (sorted by update time)
191
+ */
192
+ async listSessions() {
193
+ const files = await this.fileAdapter.readdir(this.storageDir).catch(() => []);
194
+ const sessions = [];
195
+ for (const file of files) {
196
+ if (!file.endsWith('.json'))
197
+ continue;
198
+ const filePath = join(this.storageDir, file);
199
+ const data = await this.fileAdapter.readFile(filePath);
200
+ const session = JSON.parse(data);
201
+ sessions.push({
202
+ id: session.meta.id,
203
+ name: session.meta.name,
204
+ updatedAt: session.meta.updatedAt,
205
+ });
206
+ }
207
+ return sessions.sort((a, b) => b.updatedAt - a.updatedAt);
208
+ }
209
+ /**
210
+ * Perform automatic session cleanup based on pruning strategy
211
+ */
212
+ async performAutoCleanup() {
213
+ const sessions = await this.loadAllSessions();
214
+ const analysis = this.pruningEngine.analyzeSessions(sessions);
215
+ let deleted = 0;
216
+ let archived = 0;
217
+ // Delete low-priority sessions
218
+ for (const sessionId of analysis.sessionsToDelete) {
219
+ await this.deleteSession(sessionId);
220
+ deleted++;
221
+ }
222
+ // Archive medium-priority sessions
223
+ for (const sessionId of analysis.sessionsToArchive) {
224
+ const session = sessions.find((s) => s.meta.id === sessionId);
225
+ if (session) {
226
+ await this.archiveSession(session);
227
+ await this.deleteSession(sessionId);
228
+ archived++;
229
+ }
230
+ }
231
+ return {
232
+ deleted,
233
+ archived,
234
+ kept: analysis.sessionsToKeep.length,
235
+ };
236
+ }
237
+ /**
238
+ * Archive a session with compression
239
+ */
240
+ async archiveSession(session) {
241
+ const importanceScore = this.pruningEngine.getSessionScore(session);
242
+ return await this.compressedStore.saveCompressed(session, importanceScore);
243
+ }
244
+ /**
245
+ * Load all sessions from storage
246
+ */
247
+ async loadAllSessions() {
248
+ const files = await this.fileAdapter.readdir(this.storageDir).catch(() => []);
249
+ const sessions = [];
250
+ for (const file of files) {
251
+ if (!file.endsWith('.json'))
252
+ continue;
253
+ try {
254
+ const filePath = join(this.storageDir, file);
255
+ const data = await this.fileAdapter.readFile(filePath);
256
+ const session = JSON.parse(data);
257
+ sessions.push(session);
258
+ }
259
+ catch (error) {
260
+ // Skip corrupted session files
261
+ console.warn(`Failed to load session file ${file}:`, error);
262
+ }
263
+ }
264
+ return sessions;
265
+ }
266
+ /**
267
+ * Delete a session file
268
+ */
269
+ async deleteSession(sessionId) {
270
+ const filePath = join(this.storageDir, `${sessionId}.json`);
271
+ try {
272
+ await this.fileAdapter.deleteFile(filePath);
273
+ }
274
+ catch (error) {
275
+ console.warn(`Failed to delete session ${sessionId}:`, error);
276
+ }
277
+ }
278
+ /**
279
+ * Get session importance score
280
+ */
281
+ getSessionScore(session) {
282
+ return this.pruningEngine.getSessionScore(session);
283
+ }
284
+ /**
285
+ * Update pruning strategy
286
+ */
287
+ updatePruningStrategy(strategy) {
288
+ this.pruningEngine.updateStrategy(strategy);
289
+ }
290
+ /**
291
+ * Get current pruning strategy
292
+ */
293
+ getPruningStrategy() {
294
+ return this.pruningEngine.getStrategy();
295
+ }
296
+ /**
297
+ * List archived sessions
298
+ */
299
+ async listArchivedSessions() {
300
+ // Implement archived session list functionality
301
+ // This needs to access the compressed storage
302
+ return [];
303
+ }
304
+ /**
305
+ * Restore session from archive
306
+ */
307
+ async restoreFromArchive(_archiveId) {
308
+ // Implement session restoration from archive functionality
309
+ // This needs to access the compressed storage and decompress
310
+ return null;
311
+ }
312
+ }
313
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Default memory pruning strategy configuration
3
+ */
4
+ export const DEFAULT_PRUNING_STRATEGY = {
5
+ maxAgeDays: 30,
6
+ maxSessions: 50,
7
+ autoPrune: true,
8
+ gracePeriodDays: 7,
9
+ importanceScoring: calculateDefaultImportanceScore,
10
+ lowScoreThreshold: 10,
11
+ };
12
+ /**
13
+ * Default importance scoring algorithm
14
+ */
15
+ export function calculateDefaultImportanceScore(session) {
16
+ let score = 0;
17
+ // Score based on successful iterations
18
+ score += session.meta.successfulIterations * 8;
19
+ // Score based on snapshot count
20
+ score += session.meta.snapshots.length * 3;
21
+ // Score based on recent activity (time decay)
22
+ const daysSinceUpdate = (Date.now() - session.meta.updatedAt) / (1000 * 60 * 60 * 24);
23
+ const recencyScore = Math.max(0, 12 - daysSinceUpdate);
24
+ score += recencyScore;
25
+ // Score based on message count
26
+ score += Math.min(session.messages.length * 0.5, 10);
27
+ // Score based on token usage
28
+ const totalTokens = session.meta.totalTokens.input + session.meta.totalTokens.output;
29
+ score += Math.min(totalTokens / 2000, 10); // Reduced token weight
30
+ return Math.round(score * 100) / 100; // Keep two decimal places
31
+ }
32
+ /**
33
+ * Session pruning engine
34
+ */
35
+ export class SessionPruningEngine {
36
+ strategy;
37
+ constructor(strategy = {}) {
38
+ this.strategy = { ...DEFAULT_PRUNING_STRATEGY, ...strategy };
39
+ }
40
+ /**
41
+ * Analyze sessions and determine pruning strategy
42
+ */
43
+ analyzeSessions(sessions) {
44
+ const now = Date.now();
45
+ const sessionsWithScores = sessions.map((session) => ({
46
+ session,
47
+ score: this.strategy.importanceScoring(session),
48
+ ageInDays: (now - session.meta.createdAt) / (1000 * 60 * 60 * 24),
49
+ }));
50
+ // Sort by importance score descending
51
+ sessionsWithScores.sort((a, b) => b.score - a.score);
52
+ const result = {
53
+ sessionsToDelete: [],
54
+ sessionsToArchive: [],
55
+ sessionsToKeep: [],
56
+ summary: {
57
+ totalSessions: sessions.length,
58
+ deletedCount: 0,
59
+ archivedCount: 0,
60
+ keptCount: 0,
61
+ },
62
+ };
63
+ for (const { session, score, ageInDays } of sessionsWithScores) {
64
+ const isExpired = ageInDays > this.strategy.maxAgeDays;
65
+ const isInGracePeriod = ageInDays <= this.strategy.maxAgeDays + this.strategy.gracePeriodDays;
66
+ const hasLowScore = score < this.strategy.lowScoreThreshold;
67
+ if (isExpired && hasLowScore && !isInGracePeriod) {
68
+ // Expired and low importance sessions to delete directly
69
+ result.sessionsToDelete.push(session.meta.id);
70
+ }
71
+ else if (isExpired && hasLowScore) {
72
+ // Low importance sessions within grace period to archive
73
+ result.sessionsToArchive.push(session.meta.id);
74
+ }
75
+ else {
76
+ // Important sessions or unexpired sessions to keep
77
+ result.sessionsToKeep.push(session.meta.id);
78
+ }
79
+ }
80
+ // If sessions to keep exceed maximum limit, archive excess sessions
81
+ if (result.sessionsToKeep.length > this.strategy.maxSessions) {
82
+ const excessSessions = result.sessionsToKeep.slice(this.strategy.maxSessions);
83
+ result.sessionsToKeep = result.sessionsToKeep.slice(0, this.strategy.maxSessions);
84
+ result.sessionsToArchive.push(...excessSessions);
85
+ }
86
+ // Update statistics
87
+ result.summary.deletedCount = result.sessionsToDelete.length;
88
+ result.summary.archivedCount = result.sessionsToArchive.length;
89
+ result.summary.keptCount = result.sessionsToKeep.length;
90
+ return result;
91
+ }
92
+ /**
93
+ * Get session importance score
94
+ */
95
+ getSessionScore(session) {
96
+ return this.strategy.importanceScoring(session);
97
+ }
98
+ /**
99
+ * Update strategy configuration
100
+ */
101
+ updateStrategy(newStrategy) {
102
+ this.strategy = { ...this.strategy, ...newStrategy };
103
+ }
104
+ /**
105
+ * Get current strategy configuration
106
+ */
107
+ getStrategy() {
108
+ return { ...this.strategy };
109
+ }
110
+ }
111
+ /**
112
+ * Session archiver
113
+ */
114
+ export class SessionArchiver {
115
+ archiveDir;
116
+ constructor(baseDir) {
117
+ this.archiveDir = `${baseDir}/.salmonloop/chat-archives`;
118
+ }
119
+ /**
120
+ * Create session archive
121
+ */
122
+ async createArchive(session, compressedData) {
123
+ const archiveId = `${session.meta.id}-${Date.now()}`;
124
+ const archivePath = `${this.archiveDir}/${archiveId}.mpack.gz`;
125
+ // Ensure archive directory exists
126
+ await this.ensureArchiveDir();
127
+ // Write compressed data
128
+ await this.writeCompressedData(archivePath, compressedData);
129
+ return archiveId;
130
+ }
131
+ /**
132
+ * Restore session from archive
133
+ */
134
+ async restoreFromArchive(_archiveId) {
135
+ try {
136
+ // Need to implement decompression and deserialization logic
137
+ // Return null for now, implement later
138
+ return null;
139
+ }
140
+ catch {
141
+ return null;
142
+ }
143
+ }
144
+ async ensureArchiveDir() {
145
+ // This method is not implemented as it requires file system adapter
146
+ // The SessionArchiver is currently a placeholder for future implementation
147
+ }
148
+ async writeCompressedData(_archivePath, _compressedData) {
149
+ // This method is not implemented as it requires file system adapter
150
+ // The SessionArchiver is currently a placeholder for future implementation
151
+ }
152
+ }
153
+ //# sourceMappingURL=pruning-strategy.js.map
@@ -0,0 +1,122 @@
1
+ import { TokenBudgetCalculator } from '../context/token/token-budget.js';
2
+ export const DEFAULT_SESSION_CONTEXT_BUDGET_FRACTION = 0.15;
3
+ export const DEFAULT_SESSION_CONTEXT_MIN_TOKENS = 256;
4
+ export const DEFAULT_SESSION_CONTEXT_MAX_TOKENS = 4096;
5
+ function clampInt(value, min, max) {
6
+ const v = Math.floor(value);
7
+ return Math.max(min, Math.min(max, v));
8
+ }
9
+ export function getDefaultSessionContextBudgetTokens(params) {
10
+ const calculator = new TokenBudgetCalculator();
11
+ if (typeof params.modelId === 'string' && params.modelId.trim()) {
12
+ calculator.setModel(params.modelId);
13
+ }
14
+ const recommended = calculator.getDefaultBudget();
15
+ const derived = recommended * DEFAULT_SESSION_CONTEXT_BUDGET_FRACTION;
16
+ return clampInt(derived, DEFAULT_SESSION_CONTEXT_MIN_TOKENS, DEFAULT_SESSION_CONTEXT_MAX_TOKENS);
17
+ }
18
+ function defaultCountTokens(textValue) {
19
+ // Deterministic approximation for English-ish text. This matches our existing conventions.
20
+ return Math.ceil(textValue.length / 4);
21
+ }
22
+ function toSafeHistoryMessage(msg) {
23
+ if (!msg || typeof msg !== 'object')
24
+ return null;
25
+ if (msg.role !== 'user' && msg.role !== 'assistant')
26
+ return null;
27
+ if (typeof msg.content !== 'string')
28
+ return null;
29
+ const content = msg.content.trimEnd();
30
+ if (!content)
31
+ return null;
32
+ return { role: msg.role, content };
33
+ }
34
+ /**
35
+ * Build a deterministic conversation context slice from a persisted session.
36
+ *
37
+ * Notes:
38
+ * - Only includes `user` and `assistant` messages.
39
+ * - Drops a leading `assistant` message to avoid starting mid-turn.
40
+ * - Uses a soft token budget with a deterministic approximation unless overridden.
41
+ */
42
+ export function buildSessionConversationContext(messages, options) {
43
+ const history = Array.isArray(messages) ? messages.map(toSafeHistoryMessage).filter(Boolean) : [];
44
+ if (history.length === 0)
45
+ return [];
46
+ const maxMessages = clampInt(options.maxMessages ?? 32, 1, 256);
47
+ const budgetTokens = Math.max(0, Math.floor(options.budgetTokens));
48
+ if (budgetTokens === 0)
49
+ return [];
50
+ const count = options.countTokens ?? defaultCountTokens;
51
+ let remaining = budgetTokens;
52
+ const selectedReversed = [];
53
+ for (let i = history.length - 1; i >= 0; i--) {
54
+ if (selectedReversed.length >= maxMessages)
55
+ break;
56
+ const msg = history[i];
57
+ const tokens = Math.max(0, Math.floor(count(msg.content)));
58
+ if (tokens <= remaining) {
59
+ selectedReversed.push(msg);
60
+ remaining -= tokens;
61
+ continue;
62
+ }
63
+ if (selectedReversed.length === 0) {
64
+ // If a single message doesn't fit, include a deterministic prefix slice.
65
+ const maxChars = Math.max(0, remaining * 4);
66
+ if (maxChars >= 16) {
67
+ selectedReversed.push({ role: msg.role, content: msg.content.slice(0, maxChars) });
68
+ }
69
+ }
70
+ break;
71
+ }
72
+ const selected = selectedReversed.reverse();
73
+ while (selected.length > 0 && selected[0].role === 'assistant') {
74
+ selected.shift();
75
+ }
76
+ const summaryMessages = buildSummaryMessages(options.summaryState);
77
+ if (summaryMessages.length === 0) {
78
+ return selected;
79
+ }
80
+ const selectedTokens = selected.reduce((sum, msg) => sum + Math.max(0, Math.floor(count(msg.content))), 0);
81
+ let budgetLeftForSummary = Math.max(0, budgetTokens - selectedTokens);
82
+ const prepended = [];
83
+ for (const msg of summaryMessages) {
84
+ if (budgetLeftForSummary <= 0)
85
+ break;
86
+ const fullTokens = Math.max(0, Math.floor(count(msg.content)));
87
+ if (fullTokens <= budgetLeftForSummary) {
88
+ prepended.push(msg);
89
+ budgetLeftForSummary -= fullTokens;
90
+ continue;
91
+ }
92
+ const maxChars = Math.max(0, budgetLeftForSummary * 4);
93
+ if (maxChars >= 16) {
94
+ prepended.push({ role: 'system', content: msg.content.slice(0, maxChars) });
95
+ }
96
+ budgetLeftForSummary = 0;
97
+ }
98
+ return [...prepended, ...selected];
99
+ }
100
+ function buildSummaryMessages(summaryState) {
101
+ if (!summaryState)
102
+ return [];
103
+ const messages = [];
104
+ const structured = summaryState.structuredState;
105
+ if (structured) {
106
+ messages.push({
107
+ role: 'system',
108
+ content: `[Conversation structured state v${summaryState.summaryVersion ?? 2}]` +
109
+ `\ncontextHash=${summaryState.contextHash ?? 'none'}\n` +
110
+ JSON.stringify(structured),
111
+ });
112
+ }
113
+ const summaryText = typeof summaryState.summary === 'string' ? summaryState.summary.trim() : '';
114
+ if (summaryText) {
115
+ messages.push({
116
+ role: 'system',
117
+ content: `[Previous conversation summary]\n${summaryText}`,
118
+ });
119
+ }
120
+ return messages;
121
+ }
122
+ //# sourceMappingURL=session-context-builder.js.map
@@ -0,0 +1,82 @@
1
+ import { ConversationSummarizer } from '../context/summarization/summarizer.js';
2
+ import { DEFAULT_SUMMARIZATION_CONFIG } from '../context/summarization/types.js';
3
+ import { TokenTracker } from './token-tracker.js';
4
+ export async function refreshSessionSummary(params) {
5
+ const { sessionManager, llm, contextHash } = params;
6
+ const strategy = params.strategy ?? 'auto';
7
+ if (!sessionManager)
8
+ return;
9
+ try {
10
+ const summarizer = new ConversationSummarizer({
11
+ chat: async ({ messages, temperature, maxTokens }) => {
12
+ const response = await llm.chat(messages, {
13
+ temperature,
14
+ maxTokens,
15
+ phase: 'CONTEXT',
16
+ });
17
+ return { content: response.content };
18
+ },
19
+ }, {
20
+ count: (text) => TokenTracker.estimateTokens(text),
21
+ }, {
22
+ ...DEFAULT_SUMMARIZATION_CONFIG,
23
+ async: false,
24
+ summaryModel: {
25
+ model: llm.getModelId?.() ?? 'session-summary',
26
+ temperature: 0,
27
+ maxTokens: DEFAULT_SUMMARIZATION_CONFIG.maxSummaryTokens,
28
+ },
29
+ });
30
+ await summarizer.initialize();
31
+ const persistedState = sessionManager.getSummaryState();
32
+ if (persistedState) {
33
+ summarizer.restoreState(persistedState);
34
+ }
35
+ const messages = sessionManager.getMessagesWithIds().map((msg) => ({
36
+ id: msg.id,
37
+ role: msg.role,
38
+ content: msg.content,
39
+ timestamp: msg.timestamp,
40
+ }));
41
+ if (strategy === 'force') {
42
+ await summarizer.forceSummarize(messages, contextHash);
43
+ }
44
+ else {
45
+ await summarizer.triggerSummarization(messages, contextHash);
46
+ }
47
+ sessionManager.updateSummaryState(summarizer.getState());
48
+ }
49
+ catch {
50
+ // Best-effort summary update: never affect execution flow.
51
+ }
52
+ }
53
+ export function buildEffectiveConversationContext(params) {
54
+ const { sessionManager } = params;
55
+ const summaryState = sessionManager.getSummaryState();
56
+ const messages = sessionManager.getMessagesWithIds().map((msg) => ({
57
+ id: msg.id,
58
+ role: msg.role,
59
+ content: msg.content,
60
+ timestamp: msg.timestamp,
61
+ }));
62
+ const summarizer = new ConversationSummarizer({
63
+ chat: async () => ({ content: '' }),
64
+ }, {
65
+ count: (text) => TokenTracker.estimateTokens(text),
66
+ }, {
67
+ ...DEFAULT_SUMMARIZATION_CONFIG,
68
+ async: false,
69
+ summaryModel: {
70
+ model: params.llm.getModelId?.() ?? 'session-summary',
71
+ temperature: 0,
72
+ maxTokens: DEFAULT_SUMMARIZATION_CONFIG.maxSummaryTokens,
73
+ },
74
+ });
75
+ if (summaryState) {
76
+ summarizer.restoreState(summaryState);
77
+ }
78
+ return summarizer
79
+ .getEffectiveContext(messages)
80
+ .map((m) => ({ role: m.role, content: m.content }));
81
+ }
82
+ //# sourceMappingURL=summary-sync.js.map