saeeol 1.1.1 → 1.2.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 (379) hide show
  1. package/package.json +14 -14
  2. package/script/build.ts +1 -1
  3. package/src/addons/addon-analytics.ts +1 -1
  4. package/src/cli/cmd/tui/routes/session/suggest.tsx +1 -1
  5. package/src/cli/logo.ts +1 -1
  6. package/src/cli/ui.ts +1 -1
  7. package/src/config/config-loader.ts +1 -1
  8. package/src/config/config-schema.ts +1 -1
  9. package/src/config/config.ts +1 -1
  10. package/src/config/markdown.ts +1 -1
  11. package/src/index.ts +2 -2
  12. package/src/lsp/lsp.ts +1 -1
  13. package/src/lsp/server-web.ts +1 -1
  14. package/src/mcp/oauth-callback.ts +1 -1
  15. package/src/{saeeol → overlay}/encoding.ts +1 -1
  16. package/src/{saeeol → overlay}/text-stream.ts +1 -1
  17. package/src/{saeeol → overlay}/tool/encoded-io.ts +1 -1
  18. package/src/patch/patch-apply.ts +1 -1
  19. package/src/patch/patch-parse.ts +1 -1
  20. package/src/session/compaction-helpers.ts +1 -169
  21. package/src/session/compaction.ts +1 -712
  22. package/src/session/core/compaction/compaction-helpers.ts +169 -0
  23. package/src/session/core/compaction/compaction.ts +712 -0
  24. package/src/session/core/compaction/overflow.ts +28 -0
  25. package/src/session/core/instruction.ts +234 -0
  26. package/src/session/core/llm.ts +504 -0
  27. package/src/session/core/network.ts +392 -0
  28. package/src/session/core/processor.ts +731 -0
  29. package/src/session/core/projectors.ts +139 -0
  30. package/src/session/core/resolve-tools.ts +241 -0
  31. package/src/session/core/retry.ts +149 -0
  32. package/src/session/core/revert.ts +173 -0
  33. package/src/session/core/run-state.ts +110 -0
  34. package/src/session/core/schema.ts +35 -0
  35. package/src/session/core/session-types.ts +160 -0
  36. package/src/session/core/session.sql.ts +124 -0
  37. package/src/session/core/session.ts +948 -0
  38. package/src/session/core/shell-exec.ts +205 -0
  39. package/src/session/core/status.ts +100 -0
  40. package/src/session/core/subtask.ts +268 -0
  41. package/src/session/core/summary.ts +173 -0
  42. package/src/session/core/system.ts +114 -0
  43. package/src/session/core/todo.ts +86 -0
  44. package/src/session/core/user-part.ts +293 -0
  45. package/src/session/instruction.ts +1 -234
  46. package/src/session/llm.ts +1 -504
  47. package/src/session/message/message-errors.ts +83 -0
  48. package/src/session/message/message-parts.ts +89 -0
  49. package/src/session/message/message-query.ts +107 -0
  50. package/src/session/message/message-transform.ts +156 -0
  51. package/src/session/message/message-types.ts +68 -0
  52. package/src/session/message/message-v2.ts +73 -0
  53. package/src/session/message/message.ts +192 -0
  54. package/src/session/message-errors.ts +1 -83
  55. package/src/session/message-parts.ts +1 -89
  56. package/src/session/message-query.ts +1 -107
  57. package/src/session/message-transform.ts +1 -156
  58. package/src/session/message-types.ts +1 -68
  59. package/src/session/message-v2.ts +1 -73
  60. package/src/session/message.ts +1 -192
  61. package/src/session/network.ts +1 -392
  62. package/src/session/overflow.ts +1 -28
  63. package/src/session/processor.ts +1 -731
  64. package/src/session/projectors.ts +2 -139
  65. package/src/session/prompt/prompt-command.ts +93 -0
  66. package/src/session/prompt/prompt-loop.ts +299 -0
  67. package/src/session/prompt/prompt-model.ts +44 -0
  68. package/src/session/prompt/prompt-reminders.ts +120 -0
  69. package/src/session/prompt/prompt-resolve.ts +42 -0
  70. package/src/session/prompt/prompt-schemas.ts +128 -0
  71. package/src/session/prompt/prompt-title.ts +55 -0
  72. package/src/session/prompt/prompt-types.ts +47 -0
  73. package/src/session/prompt/prompt-user-msg.ts +80 -0
  74. package/src/session/prompt/prompt.ts +211 -0
  75. package/src/session/prompt-command.ts +1 -93
  76. package/src/session/prompt-loop.ts +1 -299
  77. package/src/session/prompt-model.ts +1 -44
  78. package/src/session/prompt-reminders.ts +1 -120
  79. package/src/session/prompt-resolve.ts +1 -42
  80. package/src/session/prompt-schemas.ts +1 -128
  81. package/src/session/prompt-title.ts +1 -55
  82. package/src/session/prompt-types.ts +1 -47
  83. package/src/session/prompt-user-msg.ts +1 -80
  84. package/src/session/prompt.ts +1 -211
  85. package/src/session/resolve-tools.ts +1 -241
  86. package/src/session/retry.ts +1 -149
  87. package/src/session/revert.ts +1 -173
  88. package/src/session/run-state.ts +1 -110
  89. package/src/session/schema.ts +1 -35
  90. package/src/session/session-types.ts +1 -160
  91. package/src/session/session.sql.ts +1 -124
  92. package/src/session/session.ts +1 -948
  93. package/src/session/shell-exec.ts +1 -205
  94. package/src/session/status.ts +1 -100
  95. package/src/session/subtask.ts +1 -268
  96. package/src/session/summary.ts +1 -173
  97. package/src/session/system.ts +1 -114
  98. package/src/session/todo.ts +1 -86
  99. package/src/session/user-part.ts +1 -293
  100. package/src/skill/index.ts +1 -1
  101. package/src/suggestion/index.ts +1 -1
  102. package/src/tool/apply_patch.ts +2 -2
  103. package/src/tool/edit.ts +2 -2
  104. package/src/tool/read.ts +2 -2
  105. package/src/tool/recall.ts +1 -1
  106. package/src/tool/registry.ts +2 -2
  107. package/src/tool/suggest.ts +1 -1
  108. package/src/tool/task.ts +3 -3
  109. package/src/tool/todo.ts +1 -1
  110. package/src/tool/write.ts +2 -2
  111. package/test/lsp/index.test.ts +1 -1
  112. package/test/saeeol/agent-manager-tool.test.ts +1 -1
  113. package/test/saeeol/ask-agent-permissions.test.ts +1 -1
  114. package/test/saeeol/bash-hierarchy.test.ts +1 -1
  115. package/test/saeeol/builtin-skills.test.ts +1 -1
  116. package/test/saeeol/cli/dev-setup.test.ts +1 -1
  117. package/test/saeeol/cli/roll-call.test.ts +1 -1
  118. package/test/saeeol/cli-run-auto-helper.test.ts +1 -1
  119. package/test/saeeol/codex-auth-refresh.test.ts +1 -1
  120. package/test/saeeol/commit-message/generate.test.ts +1 -1
  121. package/test/saeeol/commit-message/git-context.test.ts +1 -1
  122. package/test/saeeol/commit-message-windows.test.ts +1 -1
  123. package/test/saeeol/compaction-payload-recovery.test.ts +1 -1
  124. package/test/saeeol/config/config.test.ts +1 -1
  125. package/test/saeeol/config-injector.test.ts +1 -1
  126. package/test/saeeol/config-validation.test.ts +1 -1
  127. package/test/saeeol/cost-propagation.test.ts +1 -1
  128. package/test/saeeol/custom-provider-delete.test.ts +1 -1
  129. package/test/saeeol/diff-full.test.ts +1 -1
  130. package/test/saeeol/encoding.test.ts +1 -1
  131. package/test/saeeol/enhance-prompt.test.ts +1 -1
  132. package/test/saeeol/ensure-plan-dir.test.ts +1 -1
  133. package/test/saeeol/errors.test.ts +1 -1
  134. package/test/saeeol/help.test.ts +3 -3
  135. package/test/saeeol/ignore-migrator.test.ts +1 -1
  136. package/test/saeeol/indexing-auth.test.ts +1 -1
  137. package/test/saeeol/indexing-feature.test.ts +1 -1
  138. package/test/saeeol/indexing-label.test.ts +1 -1
  139. package/test/saeeol/indexing-startup.test.ts +1 -1
  140. package/test/saeeol/indexing-worktree.test.ts +1 -1
  141. package/test/saeeol/lancedb-runtime.test.ts +9 -9
  142. package/test/saeeol/logo.test.ts +1 -1
  143. package/test/saeeol/lsp-typescript-lightweight.test.ts +2 -2
  144. package/test/saeeol/mcp-migrator.test.ts +1 -1
  145. package/test/saeeol/model-info-panel-utils.test.ts +1 -1
  146. package/test/saeeol/modes-migrator.test.ts +1 -1
  147. package/test/saeeol/paths.test.ts +1 -1
  148. package/test/saeeol/permission/config-paths.test.ts +2 -2
  149. package/test/saeeol/permission/external-directory-allow.test.ts +1 -1
  150. package/test/saeeol/plan-exit-detection.test.ts +1 -1
  151. package/test/saeeol/plan-followup.test.ts +2 -2
  152. package/test/saeeol/project-id.test.ts +1 -1
  153. package/test/saeeol/question-dismiss-all.test.ts +1 -1
  154. package/test/saeeol/rules-migrator.test.ts +1 -1
  155. package/test/saeeol/semantic-search.test.ts +2 -2
  156. package/test/saeeol/session/platform-attribution.test.ts +1 -1
  157. package/test/saeeol/session-compaction-cap.test.ts +2 -2
  158. package/test/saeeol/session-compaction-chunks.test.ts +1 -1
  159. package/test/saeeol/session-compaction-safety.test.ts +1 -1
  160. package/test/saeeol/session-import-service.test.ts +1 -1
  161. package/test/saeeol/session-processor-empty-tool-calls.test.ts +1 -1
  162. package/test/saeeol/session-processor-review-telemetry.test.ts +1 -1
  163. package/test/saeeol/session-prompt-queue.test.ts +1 -1
  164. package/test/saeeol/sessions/remote-sender.test.ts +1 -1
  165. package/test/saeeol/snapshot-track-timeout.test.ts +1 -1
  166. package/test/saeeol/suggestion/auto-dismiss.test.ts +2 -2
  167. package/test/saeeol/suggestion/suggestion.test.ts +1 -1
  168. package/test/saeeol/suggestion/tool.test.ts +2 -2
  169. package/test/saeeol/system-prompt.test.ts +1 -1
  170. package/test/saeeol/todo-view.test.ts +1 -1
  171. package/test/saeeol/tool-registry-indexing.test.ts +3 -3
  172. package/test/saeeol/tui-diff.test.ts +1 -1
  173. package/test/saeeol/tui-sync.test.ts +1 -1
  174. package/test/saeeol/util/url.test.ts +1 -1
  175. package/test/saeeol/workflows-migrator.test.ts +1 -1
  176. package/test/saeeol/worktree-diff-summary.test.ts +1 -1
  177. package/tsconfig.json +1 -1
  178. /package/src/{saeeol → overlay}/agent/agent-remove.ts +0 -0
  179. /package/src/{saeeol → overlay}/agent/index.ts +0 -0
  180. /package/src/{saeeol → overlay}/agent/patch-agents.ts +0 -0
  181. /package/src/{saeeol → overlay}/agent/permissions.ts +0 -0
  182. /package/src/{saeeol → overlay}/agent-manager/event.ts +0 -0
  183. /package/src/{saeeol → overlay}/bash-hierarchy.ts +0 -0
  184. /package/src/{saeeol → overlay}/bell.ts +0 -0
  185. /package/src/{saeeol → overlay}/bootstrap.ts +0 -0
  186. /package/src/{saeeol → overlay}/claw/autocomplete-popup.tsx +0 -0
  187. /package/src/{saeeol → overlay}/claw/autocomplete-ref.ts +0 -0
  188. /package/src/{saeeol → overlay}/claw/autocomplete-types.ts +0 -0
  189. /package/src/{saeeol → overlay}/claw/autocomplete.tsx +0 -0
  190. /package/src/{saeeol → overlay}/claw/chat-client.ts +0 -0
  191. /package/src/{saeeol → overlay}/claw/chat.tsx +0 -0
  192. /package/src/{saeeol → overlay}/claw/client-events.ts +0 -0
  193. /package/src/{saeeol → overlay}/claw/client-helpers.ts +0 -0
  194. /package/src/{saeeol → overlay}/claw/client.ts +0 -0
  195. /package/src/{saeeol → overlay}/claw/dialog-conversation-list.tsx +0 -0
  196. /package/src/{saeeol → overlay}/claw/event-service-client-core.ts +0 -0
  197. /package/src/{saeeol → overlay}/claw/event-service-client-impl.ts +0 -0
  198. /package/src/{saeeol → overlay}/claw/event-service-client.ts +0 -0
  199. /package/src/{saeeol → overlay}/claw/hooks.ts +0 -0
  200. /package/src/{saeeol → overlay}/claw/sidebar.tsx +0 -0
  201. /package/src/{saeeol → overlay}/claw/types.ts +0 -0
  202. /package/src/{saeeol → overlay}/claw/view.tsx +0 -0
  203. /package/src/{saeeol → overlay}/cli/cmd/roll-call-call.ts +0 -0
  204. /package/src/{saeeol → overlay}/cli/cmd/roll-call-format.ts +0 -0
  205. /package/src/{saeeol → overlay}/cli/cmd/roll-call.ts +0 -0
  206. /package/src/{saeeol → overlay}/cli/cmd/tui/app.tsx +0 -0
  207. /package/src/{saeeol → overlay}/cli/cmd/tui/component/dialog-provider.tsx +0 -0
  208. /package/src/{saeeol → overlay}/cli/cmd/tui/feedback.ts +0 -0
  209. /package/src/{saeeol → overlay}/cli/cmd/tui/util/terminal.ts +0 -0
  210. /package/src/{saeeol → overlay}/cli/dev-setup-utils.ts +0 -0
  211. /package/src/{saeeol → overlay}/cli/dev-setup.ts +0 -0
  212. /package/src/{saeeol → overlay}/cli/heap-snapshot.ts +0 -0
  213. /package/src/{saeeol → overlay}/cli/logo.ts +0 -0
  214. /package/src/{saeeol → overlay}/cli/run-auto.ts +0 -0
  215. /package/src/{saeeol → overlay}/cli/saeeol-logo.ts +0 -0
  216. /package/src/{saeeol → overlay}/cloud-session.ts +0 -0
  217. /package/src/{saeeol → overlay}/commands-index.ts +0 -0
  218. /package/src/{saeeol → overlay}/commands.ts +0 -0
  219. /package/src/{saeeol → overlay}/commands.tsx +0 -0
  220. /package/src/{saeeol → overlay}/commit-message/generate.ts +0 -0
  221. /package/src/{saeeol → overlay}/commit-message/git-context.ts +0 -0
  222. /package/src/{saeeol → overlay}/commit-message/index.ts +0 -0
  223. /package/src/{saeeol → overlay}/commit-message/types.ts +0 -0
  224. /package/src/{saeeol → overlay}/components/dialog-auto-method.tsx +0 -0
  225. /package/src/{saeeol → overlay}/components/dialog-claw-setup.tsx +0 -0
  226. /package/src/{saeeol → overlay}/components/dialog-claw-upgrade.tsx +0 -0
  227. /package/src/{saeeol → overlay}/components/dialog-indexing-helpers.ts +0 -0
  228. /package/src/{saeeol → overlay}/components/dialog-indexing.tsx +0 -0
  229. /package/src/{saeeol → overlay}/components/dialog-notifications.tsx +0 -0
  230. /package/src/{saeeol → overlay}/components/dialog-organization.tsx +0 -0
  231. /package/src/{saeeol → overlay}/components/dialog-profile.tsx +0 -0
  232. /package/src/{saeeol → overlay}/components/dialog-provider-settings.tsx +0 -0
  233. /package/src/{saeeol → overlay}/components/dialog-team-select.tsx +0 -0
  234. /package/src/{saeeol → overlay}/components/dialog-tuning.tsx +0 -0
  235. /package/src/{saeeol → overlay}/components/dialog-vector-store.tsx +0 -0
  236. /package/src/{saeeol → overlay}/components/error-display.tsx +0 -0
  237. /package/src/{saeeol → overlay}/components/model-info-panel-utils.ts +0 -0
  238. /package/src/{saeeol → overlay}/components/model-info-panel.tsx +0 -0
  239. /package/src/{saeeol → overlay}/components/news.tsx +0 -0
  240. /package/src/{saeeol → overlay}/components/notification-banner.tsx +0 -0
  241. /package/src/{saeeol → overlay}/components/session-indexing.tsx +0 -0
  242. /package/src/{saeeol → overlay}/components/tips.tsx +0 -0
  243. /package/src/{saeeol → overlay}/config/config-core.ts +0 -0
  244. /package/src/{saeeol → overlay}/config/config-helpers.ts +0 -0
  245. /package/src/{saeeol → overlay}/config/config-legacy.ts +0 -0
  246. /package/src/{saeeol → overlay}/config/config.ts +0 -0
  247. /package/src/{saeeol → overlay}/config/default-plugins.ts +0 -0
  248. /package/src/{saeeol → overlay}/config/markdown.ts +0 -0
  249. /package/src/{saeeol → overlay}/config-injector.ts +0 -0
  250. /package/src/{saeeol → overlay}/config-validation.ts +0 -0
  251. /package/src/{saeeol → overlay}/const.ts +0 -0
  252. /package/src/{saeeol → overlay}/cost-tracker/format.ts +0 -0
  253. /package/src/{saeeol → overlay}/cost-tracker/index.ts +0 -0
  254. /package/src/{saeeol → overlay}/cost-tracker/state.ts +0 -0
  255. /package/src/{saeeol → overlay}/cost-tracker/types.ts +0 -0
  256. /package/src/{saeeol → overlay}/docs/migration.md +0 -0
  257. /package/src/{saeeol → overlay}/docs/rules-migration.md +0 -0
  258. /package/src/{saeeol → overlay}/editor-context.ts +0 -0
  259. /package/src/{saeeol → overlay}/enhance-prompt.ts +0 -0
  260. /package/src/{saeeol → overlay}/errors.ts +0 -0
  261. /package/src/{saeeol → overlay}/generate-cli-docs.ts +0 -0
  262. /package/src/{saeeol → overlay}/help-command.ts +0 -0
  263. /package/src/{saeeol → overlay}/help.ts +0 -0
  264. /package/src/{saeeol → overlay}/i18n/index.ts +0 -0
  265. /package/src/{saeeol → overlay}/ignore-migrator.ts +0 -0
  266. /package/src/{saeeol → overlay}/index.ts +0 -0
  267. /package/src/{saeeol → overlay}/indexing-auth.ts +0 -0
  268. /package/src/{saeeol → overlay}/indexing-feature.ts +0 -0
  269. /package/src/{saeeol → overlay}/indexing-helpers.ts +0 -0
  270. /package/src/{saeeol → overlay}/indexing-label.ts +0 -0
  271. /package/src/{saeeol → overlay}/indexing-state.ts +0 -0
  272. /package/src/{saeeol → overlay}/indexing-types.ts +0 -0
  273. /package/src/{saeeol → overlay}/indexing.ts +0 -0
  274. /package/src/{saeeol → overlay}/lancedb.ts +0 -0
  275. /package/src/{saeeol → overlay}/mcp-migrator.ts +0 -0
  276. /package/src/{saeeol → overlay}/mcp-oauth-callback.ts +0 -0
  277. /package/src/{saeeol → overlay}/memory/age.ts +0 -0
  278. /package/src/{saeeol → overlay}/memory/index.ts +0 -0
  279. /package/src/{saeeol → overlay}/memory/paths.ts +0 -0
  280. /package/src/{saeeol → overlay}/memory/scan.ts +0 -0
  281. /package/src/{saeeol → overlay}/memory/types.ts +0 -0
  282. /package/src/{saeeol → overlay}/model-match.ts +0 -0
  283. /package/src/{saeeol → overlay}/modes-migrator.ts +0 -0
  284. /package/src/{saeeol → overlay}/paths.ts +0 -0
  285. /package/src/{saeeol → overlay}/permission/config-paths.ts +0 -0
  286. /package/src/{saeeol → overlay}/permission/drain.ts +0 -0
  287. /package/src/{saeeol → overlay}/permission/external-directory.ts +0 -0
  288. /package/src/{saeeol → overlay}/permission/read.ts +0 -0
  289. /package/src/{saeeol → overlay}/permission/routes.ts +0 -0
  290. /package/src/{saeeol → overlay}/permission/rule.ts +0 -0
  291. /package/src/{saeeol → overlay}/plan-followup-handover.ts +0 -0
  292. /package/src/{saeeol → overlay}/plan-followup-runtime.ts +0 -0
  293. /package/src/{saeeol → overlay}/plan-followup-session.ts +0 -0
  294. /package/src/{saeeol → overlay}/plan-followup.ts +0 -0
  295. /package/src/{saeeol → overlay}/plugins/home-footer.tsx +0 -0
  296. /package/src/{saeeol → overlay}/plugins/home-news.tsx +0 -0
  297. /package/src/{saeeol → overlay}/plugins/home-onboarding.tsx +0 -0
  298. /package/src/{saeeol → overlay}/plugins/sidebar-footer.tsx +0 -0
  299. /package/src/{saeeol → overlay}/plugins/sidebar-pr.tsx +0 -0
  300. /package/src/{saeeol → overlay}/plugins/sidebar-usage.tsx +0 -0
  301. /package/src/{saeeol → overlay}/project-id.ts +0 -0
  302. /package/src/{saeeol → overlay}/provider/codex-refresh.ts +0 -0
  303. /package/src/{saeeol → overlay}/provider/provider.ts +0 -0
  304. /package/src/{saeeol → overlay}/provider-options.ts +0 -0
  305. /package/src/{saeeol → overlay}/question/index.ts +0 -0
  306. /package/src/{saeeol → overlay}/remote-tui.tsx +0 -0
  307. /package/src/{saeeol → overlay}/review/command.ts +0 -0
  308. /package/src/{saeeol → overlay}/review/diff.ts +0 -0
  309. /package/src/{saeeol → overlay}/review/prompt.ts +0 -0
  310. /package/src/{saeeol → overlay}/review/review.ts +0 -0
  311. /package/src/{saeeol → overlay}/review/types.ts +0 -0
  312. /package/src/{saeeol → overlay}/review/worktree-diff.ts +0 -0
  313. /package/src/{saeeol → overlay}/rules-migrator.ts +0 -0
  314. /package/src/{saeeol → overlay}/server/instance.ts +0 -0
  315. /package/src/{saeeol → overlay}/server/router.ts +0 -0
  316. /package/src/{saeeol → overlay}/server/routes/commit-message.ts +0 -0
  317. /package/src/{saeeol → overlay}/server/routes/indexing.ts +0 -0
  318. /package/src/{saeeol → overlay}/server/server.ts +0 -0
  319. /package/src/{saeeol → overlay}/session/compaction-chunks-core.ts +0 -0
  320. /package/src/{saeeol → overlay}/session/compaction-chunks-utils.ts +0 -0
  321. /package/src/{saeeol → overlay}/session/compaction-chunks.ts +0 -0
  322. /package/src/{saeeol → overlay}/session/compaction-payload-recovery.ts +0 -0
  323. /package/src/{saeeol → overlay}/session/cost-propagation.ts +0 -0
  324. /package/src/{saeeol → overlay}/session/digest-storage.ts +0 -0
  325. /package/src/{saeeol → overlay}/session/fork.ts +0 -0
  326. /package/src/{saeeol → overlay}/session/index.ts +0 -0
  327. /package/src/{saeeol → overlay}/session/instruction.ts +0 -0
  328. /package/src/{saeeol → overlay}/session/kg-compaction.ts +0 -0
  329. /package/src/{saeeol → overlay}/session/llm.ts +0 -0
  330. /package/src/{saeeol → overlay}/session/overflow.ts +0 -0
  331. /package/src/{saeeol → overlay}/session/platform.ts +0 -0
  332. /package/src/{saeeol → overlay}/session/processor.ts +0 -0
  333. /package/src/{saeeol → overlay}/session/prompt-context.ts +0 -0
  334. /package/src/{saeeol → overlay}/session/prompt-plan.ts +0 -0
  335. /package/src/{saeeol → overlay}/session/prompt-queue.ts +0 -0
  336. /package/src/{saeeol → overlay}/session/prompt.ts +0 -0
  337. /package/src/{saeeol → overlay}/session/queries.ts +0 -0
  338. /package/src/{saeeol → overlay}/session/tui-sync.ts +0 -0
  339. /package/src/{saeeol → overlay}/session-import/routes.ts +0 -0
  340. /package/src/{saeeol → overlay}/session-import/service.ts +0 -0
  341. /package/src/{saeeol → overlay}/session-import/types.ts +0 -0
  342. /package/src/{saeeol → overlay}/skills/builtin.ts +0 -0
  343. /package/src/{saeeol → overlay}/skills/config.md +0 -0
  344. /package/src/{saeeol → overlay}/snapshot/diff-full.ts +0 -0
  345. /package/src/{saeeol → overlay}/snapshot/index.ts +0 -0
  346. /package/src/{saeeol → overlay}/snapshot/track-hooks.ts +0 -0
  347. /package/src/{saeeol → overlay}/snapshot/track-types.ts +0 -0
  348. /package/src/{saeeol → overlay}/snapshot/track.ts +0 -0
  349. /package/src/{saeeol → overlay}/soul.txt +0 -0
  350. /package/src/{saeeol → overlay}/suggestion/index.ts +0 -0
  351. /package/src/{saeeol → overlay}/suggestion/routes.ts +0 -0
  352. /package/src/{saeeol → overlay}/suggestion/tool.ts +0 -0
  353. /package/src/{saeeol → overlay}/suggestion/tool.txt +0 -0
  354. /package/src/{saeeol → overlay}/suggestion/tui/bar.tsx +0 -0
  355. /package/src/{saeeol → overlay}/suggestion/tui/prompt.tsx +0 -0
  356. /package/src/{saeeol → overlay}/suggestion/tui/render.tsx +0 -0
  357. /package/src/{saeeol → overlay}/suggestion/tui/sync.ts +0 -0
  358. /package/src/{saeeol → overlay}/system-prompt.ts +0 -0
  359. /package/src/{saeeol → overlay}/todo-view.ts +0 -0
  360. /package/src/{saeeol → overlay}/tool/agent-manager.ts +0 -0
  361. /package/src/{saeeol → overlay}/tool/agent-manager.txt +0 -0
  362. /package/src/{saeeol → overlay}/tool/bash-security-patterns.ts +0 -0
  363. /package/src/{saeeol → overlay}/tool/bash-security.ts +0 -0
  364. /package/src/{saeeol → overlay}/tool/question.ts +0 -0
  365. /package/src/{saeeol → overlay}/tool/registry.ts +0 -0
  366. /package/src/{saeeol → overlay}/tool/semantic-search.ts +0 -0
  367. /package/src/{saeeol → overlay}/tool/semantic-search.txt +0 -0
  368. /package/src/{saeeol → overlay}/tool/task.ts +0 -0
  369. /package/src/{saeeol → overlay}/ts-check.ts +0 -0
  370. /package/src/{saeeol → overlay}/ts-client.ts +0 -0
  371. /package/src/{saeeol → overlay}/tui/diff.ts +0 -0
  372. /package/src/{saeeol → overlay}/util/url.ts +0 -0
  373. /package/src/{saeeol → overlay}/worker/index.ts +0 -0
  374. /package/src/{saeeol → overlay}/worker/pool.ts +0 -0
  375. /package/src/{saeeol → overlay}/worker/store.ts +0 -0
  376. /package/src/{saeeol → overlay}/worker/types.ts +0 -0
  377. /package/src/{saeeol → overlay}/workflows-migrator.ts +0 -0
  378. /package/src/{saeeol → overlay}/worktree-cleanup.ts +0 -0
  379. /package/src/{saeeol → overlay}/worktree-family.ts +0 -0
@@ -1,712 +1 @@
1
- import { clamp } from "@saeeol/boxes/clamp"
2
- import { BusEvent } from "@/bus/bus-event"
3
- import { Bus } from "@/bus"
4
- import * as Session from "./session"
5
- import { SessionID, MessageID, PartID } from "./schema"
6
- import { Provider } from "@/provider/provider"
7
- import { MessageV2 } from "./message-v2"
8
- import z from "zod"
9
- import { Token } from "@/util/token"
10
- import * as Log from "@saeeol/core/util/log"
11
- import { SessionProcessor } from "./processor"
12
- import { Agent } from "@/agent/agent"
13
- import { Plugin } from "@/plugin"
14
- import { Config } from "@/config/config"
15
- import { NotFoundError } from "@/storage/storage"
16
- import { ModelID, ProviderID } from "@/provider/schema"
17
- import { Effect, Layer, Context, Schema } from "effect"
18
- import { InstanceState } from "@/effect/instance-state"
19
- import { isOverflow as overflow, usable } from "./overflow"
20
- import { makeRuntime } from "@/effect/run-service"
21
- import { fn } from "@/util/fn"
22
- import { SaeeolSessionPromptQueue } from "@/saeeol/session/prompt-queue"
23
- import { SaeeolCompactionPayloadRecovery } from "@/saeeol/session/compaction-payload-recovery"
24
- import { SaeeolCompactionChunks } from "@/saeeol/session/compaction-chunks"
25
-
26
- const log = Log.create({ service: "session.compaction" })
27
-
28
- export const Event = {
29
- Compacted: BusEvent.define(
30
- "session.compacted",
31
- Schema.Struct({
32
- sessionID: SessionID,
33
- }),
34
- ),
35
- }
36
-
37
- export const PRUNE_MINIMUM = 20_000
38
- export const PRUNE_PROTECT = 40_000
39
- const TOOL_OUTPUT_MAX_CHARS = 2_000
40
- const PRUNE_PROTECTED_TOOLS = ["skill"]
41
- const DEFAULT_TAIL_TURNS = 2
42
- const MIN_PRESERVE_RECENT_TOKENS = 4_000
43
- const MAX_PRESERVE_RECENT_TOKENS = 32_000
44
- const TAIL_PRESERVE_RATIO = 0.20
45
- const CONTEXT_HEALTH_WARNING = 0.75
46
- const CONTEXT_HEALTH_CRITICAL = 0.90
47
- const SUMMARY_TEMPLATE = `Output exactly the Markdown structure shown inside <template> and keep the section order unchanged. Do not include the <template> tags in your response.
48
- <template>
49
- ## Goal
50
- - [single-sentence task summary]
51
-
52
- ## Constraints & Preferences
53
- - [user constraints, preferences, specs, or "(none)"]
54
-
55
- ## Progress
56
- ### Done
57
- - [completed work or "(none)"]
58
-
59
- ### In Progress
60
- - [current work or "(none)"]
61
-
62
- ### Blocked
63
- - [blockers or "(none)"]
64
-
65
- ## Key Decisions
66
- - [decision and why, or "(none)"]
67
-
68
- ## Next Steps
69
- - [ordered next actions or "(none)"]
70
-
71
- ## Critical Context
72
- - [important technical facts, errors, open questions, or "(none)"]
73
-
74
- ## Relevant Files
75
- - [file or directory path: why it matters, or "(none)"]
76
-
77
- ## Code Artifacts
78
- - [key code snippets, function signatures, type definitions that were created or modified]
79
- </template>
80
-
81
- Rules:
82
- - Keep every section, even when empty.
83
- - Use terse bullets, not prose paragraphs.
84
- - Preserve exact file paths, commands, error strings, and identifiers when known.
85
- - Preserve critical code: function signatures, type definitions, config values, and error messages.
86
- - Do not mention the summary process or that context was compacted.`
87
- type Turn = {
88
- start: number
89
- end: number
90
- id: MessageID
91
- }
92
-
93
- type Tail = {
94
- start: number
95
- id: MessageID
96
- }
97
-
98
- type CompletedCompaction = {
99
- userIndex: number
100
- assistantIndex: number
101
- summary: string | undefined
102
- }
103
- export type PruneReason = "normal" | "post-compaction" | "payload-limit"
104
-
105
- function summaryText(message: MessageV2.WithParts) {
106
- const text = message.parts
107
- .filter((part): part is MessageV2.TextPart => part.type === "text")
108
- .map((part) => part.text.trim())
109
- .filter(Boolean)
110
- .join("\n\n")
111
- .trim()
112
- return text || undefined
113
- }
114
-
115
- function completedCompactions(messages: MessageV2.WithParts[]) {
116
- const users = new Map<MessageID, number>()
117
- for (let i = 0; i < messages.length; i++) {
118
- const msg = messages[i]
119
- if (msg.info.role !== "user") continue
120
- if (!msg.parts.some((part) => part.type === "compaction")) continue
121
- users.set(msg.info.id, i)
122
- }
123
-
124
- return messages.flatMap((msg, assistantIndex): CompletedCompaction[] => {
125
- if (msg.info.role !== "assistant") return []
126
- if (!msg.info.summary || !msg.info.finish || msg.info.error) return []
127
- const userIndex = users.get(msg.info.parentID)
128
- if (userIndex === undefined) return []
129
- return [{ userIndex, assistantIndex, summary: summaryText(msg) }]
130
- })
131
- }
132
-
133
- function buildPrompt(input: { previousSummary?: string; context: string[] }) {
134
- const anchor = input.previousSummary
135
- ? [
136
- "Update the anchored summary below using the conversation history above.",
137
- "Preserve still-true details, remove stale details, and merge in the new facts.",
138
- "<previous-summary>",
139
- input.previousSummary,
140
- "</previous-summary>",
141
- ].join("\n")
142
- : "Create a new anchored summary from the conversation history above."
143
- return [anchor, SUMMARY_TEMPLATE, ...input.context].join("\n\n")
144
- }
145
-
146
- function preserveRecentBudget(input: { cfg: Config.Info; model: Provider.Model }) {
147
- const ctx = input.model.limit.context || 128_000
148
- const autoBudget = Math.floor(ctx * TAIL_PRESERVE_RATIO)
149
- return (
150
- input.cfg.compaction?.preserve_recent_tokens ??
151
- clamp(autoBudget, MIN_PRESERVE_RECENT_TOKENS, MAX_PRESERVE_RECENT_TOKENS)
152
- )
153
- }
154
-
155
- function turns(messages: MessageV2.WithParts[]) {
156
- const result: Turn[] = []
157
- for (let i = 0; i < messages.length; i++) {
158
- const msg = messages[i]
159
- if (msg.info.role !== "user") continue
160
- if (msg.parts.some((part) => part.type === "compaction")) continue
161
- result.push({
162
- start: i,
163
- end: messages.length,
164
- id: msg.info.id,
165
- })
166
- }
167
- for (let i = 0; i < result.length - 1; i++) {
168
- result[i].end = result[i + 1].start
169
- }
170
- return result
171
- }
172
-
173
- function splitTurn(input: {
174
- messages: MessageV2.WithParts[]
175
- turn: Turn
176
- model: Provider.Model
177
- budget: number
178
- estimate: (input: { messages: MessageV2.WithParts[]; model: Provider.Model }) => Effect.Effect<number>
179
- }) {
180
- return Effect.gen(function* () {
181
- if (input.budget <= 0) return undefined
182
- if (input.turn.end - input.turn.start <= 1) return undefined
183
- for (let start = input.turn.start + 1; start < input.turn.end; start++) {
184
- const size = yield* input.estimate({
185
- messages: input.messages.slice(start, input.turn.end),
186
- model: input.model,
187
- })
188
- if (size > input.budget) continue
189
- return {
190
- start,
191
- id: input.messages[start]!.info.id,
192
- } satisfies Tail
193
- }
194
- return undefined
195
- })
196
- }
197
-
198
- export interface Interface {
199
- readonly isOverflow: (input: {
200
- tokens: MessageV2.Assistant["tokens"]
201
- model: Provider.Model
202
- }) => Effect.Effect<boolean>
203
- readonly prune: (input: { sessionID: SessionID; reason?: PruneReason }) => Effect.Effect<void>
204
- readonly process: (input: {
205
- parentID: MessageID
206
- messages: MessageV2.WithParts[]
207
- sessionID: SessionID
208
- auto: boolean
209
- overflow?: boolean
210
- }) => Effect.Effect<"continue" | "stop">
211
- readonly create: (input: {
212
- sessionID: SessionID
213
- agent: string
214
- model: { providerID: ProviderID; modelID: ModelID }
215
- auto: boolean
216
- overflow?: boolean
217
- }) => Effect.Effect<void>
218
- }
219
-
220
- export class Service extends Context.Service<Service, Interface>()("@saeeol/SessionCompaction") {}
221
-
222
- export const layer: Layer.Layer<
223
- Service,
224
- never,
225
- | Bus.Service
226
- | Config.Service
227
- | Session.Service
228
- | Agent.Service
229
- | Plugin.Service
230
- | SessionProcessor.Service
231
- | Provider.Service
232
- > = Layer.effect(
233
- Service,
234
- Effect.gen(function* () {
235
- const bus = yield* Bus.Service
236
- const config = yield* Config.Service
237
- const session = yield* Session.Service
238
- const agents = yield* Agent.Service
239
- const plugin = yield* Plugin.Service
240
- const processors = yield* SessionProcessor.Service
241
- const provider = yield* Provider.Service
242
-
243
- const isOverflow = Effect.fn("SessionCompaction.isOverflow")(function* (input: {
244
- tokens: MessageV2.Assistant["tokens"]
245
- model: Provider.Model
246
- }) {
247
- return overflow({ cfg: yield* config.get(), tokens: input.tokens, model: input.model })
248
- })
249
-
250
- const estimate = Effect.fn("SessionCompaction.estimate")(function* (input: {
251
- messages: MessageV2.WithParts[]
252
- model: Provider.Model
253
- }) {
254
- const msgs = yield* MessageV2.toModelMessagesEffect(input.messages, input.model)
255
- return Token.estimate(JSON.stringify(msgs))
256
- })
257
-
258
- const select = Effect.fn("SessionCompaction.select")(function* (input: {
259
- messages: MessageV2.WithParts[]
260
- cfg: Config.Info
261
- model: Provider.Model
262
- }) {
263
- const limit = input.cfg.compaction?.tail_turns ?? DEFAULT_TAIL_TURNS
264
- if (limit <= 0) return { head: input.messages, tail_start_id: undefined }
265
- const budget = preserveRecentBudget({ cfg: input.cfg, model: input.model })
266
- const all = turns(input.messages)
267
- if (!all.length) return { head: input.messages, tail_start_id: undefined }
268
- const recent = all.slice(-limit)
269
- const sizes = yield* Effect.forEach(
270
- recent,
271
- (turn) =>
272
- estimate({
273
- messages: input.messages.slice(turn.start, turn.end),
274
- model: input.model,
275
- }),
276
- { concurrency: 1 },
277
- )
278
-
279
- const totalRecent = sizes.reduce((s, n) => s + n, 0)
280
- const expandedLimit = totalRecent > budget
281
- ? Math.min(limit + Math.ceil(totalRecent / budget), all.length)
282
- : limit
283
- const expanded = expandedLimit > limit ? all.slice(-expandedLimit) : recent
284
- const expandedSizes = expandedLimit > limit
285
- ? yield* Effect.forEach(
286
- expanded,
287
- (turn) => estimate({ messages: input.messages.slice(turn.start, turn.end), model: input.model }),
288
- { concurrency: 1 },
289
- )
290
- : sizes
291
-
292
- let total = 0
293
- let keep: Tail | undefined
294
- const iterLimit = expandedLimit > limit ? expanded : recent
295
- const iterSizes = expandedLimit > limit ? expandedSizes : sizes
296
- for (let i = iterLimit.length - 1; i >= 0; i--) {
297
- const turn = iterLimit[i]!
298
- const size = iterSizes[i]
299
- if (total + size <= budget) {
300
- total += size
301
- keep = { start: turn.start, id: turn.id }
302
- continue
303
- }
304
- const remaining = budget - total
305
- const split = yield* splitTurn({
306
- messages: input.messages,
307
- turn,
308
- model: input.model,
309
- budget: remaining,
310
- estimate,
311
- })
312
- if (split) keep = split
313
- else if (!keep) log.info("tail fallback", { budget, size, total })
314
- break
315
- }
316
-
317
- if (!keep || keep.start === 0) return { head: input.messages, tail_start_id: undefined }
318
- return {
319
- head: input.messages.slice(0, keep.start),
320
- tail_start_id: keep.id,
321
- }
322
- })
323
-
324
- // goes backwards through parts until there are PRUNE_PROTECT tokens worth of tool
325
- // calls, then erases output of older tool calls to free context space
326
- const prune = Effect.fn("SessionCompaction.prune")(function* (input: {
327
- sessionID: SessionID
328
- reason?: PruneReason
329
- }) {
330
- const cfg = yield* config.get()
331
- const reason = input.reason ?? "normal"
332
- if (cfg.compaction?.prune === false) return
333
- if (reason === "normal" && cfg.compaction?.prune !== true) return
334
- log.info("pruning", { reason })
335
-
336
- const msgs = yield* session
337
- .messages({ sessionID: input.sessionID })
338
- .pipe(Effect.catchIf(NotFoundError.isInstance, () => Effect.succeed(undefined)))
339
- if (!msgs) return
340
-
341
- let total = 0
342
- let pruned = 0
343
- const toPrune: MessageV2.ToolPart[] = []
344
- let turns = 0
345
-
346
- loop: for (let msgIndex = msgs.length - 1; msgIndex >= 0; msgIndex--) {
347
- const msg = msgs[msgIndex]
348
- if (msg.info.role === "user") turns++
349
- if (turns < 2) continue
350
- if (msg.info.role === "assistant" && msg.info.summary) break loop
351
- for (let partIndex = msg.parts.length - 1; partIndex >= 0; partIndex--) {
352
- const part = msg.parts[partIndex]
353
- if (part.type !== "tool") continue
354
- if (part.state.status !== "completed") continue
355
- if (PRUNE_PROTECTED_TOOLS.includes(part.tool)) continue
356
- if (part.state.time.compacted) break loop
357
- const estimate = Token.estimate(part.state.output)
358
- total += estimate
359
- if (total <= PRUNE_PROTECT) continue
360
- pruned += estimate
361
- toPrune.push(part)
362
- }
363
- }
364
-
365
- log.info("found", { pruned, total })
366
- if (pruned > PRUNE_MINIMUM) {
367
- for (const part of toPrune) {
368
- if (part.state.status === "completed") {
369
- part.state.time.compacted = Date.now()
370
- yield* session.updatePart(part)
371
- }
372
- }
373
- log.info("pruned", { reason, count: toPrune.length })
374
- }
375
- })
376
-
377
- const processCompaction = Effect.fn("SessionCompaction.process")(function* (input: {
378
- parentID: MessageID
379
- messages: MessageV2.WithParts[]
380
- sessionID: SessionID
381
- auto: boolean
382
- overflow?: boolean
383
- }) {
384
- const parent = input.messages.findLast((m) => m.info.id === input.parentID)
385
- if (!parent || parent.info.role !== "user") {
386
- throw new Error(`Compaction parent must be a user message: ${input.parentID}`)
387
- }
388
- const userMessage = parent.info
389
- const compactionPart = parent.parts.find((part): part is MessageV2.CompactionPart => part.type === "compaction")
390
-
391
- let messages = input.messages
392
- let replay:
393
- | {
394
- info: MessageV2.User
395
- parts: MessageV2.Part[]
396
- }
397
- | undefined
398
- if (input.overflow) {
399
- const idx = input.messages.findIndex((m) => m.info.id === input.parentID)
400
- for (let i = idx - 1; i >= 0; i--) {
401
- const msg = input.messages[i]
402
- if (msg.info.role === "user" && !msg.parts.some((p) => p.type === "compaction")) {
403
- replay = { info: msg.info, parts: msg.parts }
404
- messages = input.messages.slice(0, i)
405
- break
406
- }
407
- }
408
- const hasContent =
409
- replay && messages.some((m) => m.info.role === "user" && !m.parts.some((p) => p.type === "compaction"))
410
- if (!hasContent) {
411
- replay = undefined
412
- messages = input.messages
413
- }
414
- }
415
-
416
- const agent = yield* agents.get("compaction")
417
- const model = agent.model
418
- ? yield* provider.getModel(agent.model.providerID, agent.model.modelID)
419
- : yield* provider.getModel(userMessage.model.providerID, userMessage.model.modelID)
420
- const cfg = yield* config.get()
421
- const history = compactionPart && messages.at(-1)?.info.id === input.parentID ? messages.slice(0, -1) : messages
422
- const prior = completedCompactions(history)
423
- const hidden = new Set(prior.flatMap((item) => [item.userIndex, item.assistantIndex]))
424
- const previousSummary = prior.at(-1)?.summary
425
- const selected = yield* select({
426
- messages: history.filter((_, index) => !hidden.has(index)),
427
- cfg,
428
- model,
429
- })
430
- if (!replay) {
431
- const compactable = selected.head.filter(
432
- (m) => m.info.role === "user" && !m.parts.some((p) => p.type === "compaction"),
433
- )
434
- if (compactable.length < 2) return "continue" as const
435
- }
436
- // Allow plugins to inject context or replace compaction prompt.
437
- const compacting = yield* plugin.trigger(
438
- "experimental.session.compacting",
439
- { sessionID: input.sessionID },
440
- { context: [], prompt: undefined },
441
- )
442
- const nextPrompt = compacting.prompt ?? buildPrompt({ previousSummary, context: compacting.context })
443
- const msgs = structuredClone(selected.head)
444
- yield* plugin.trigger("experimental.chat.messages.transform", {}, { messages: msgs })
445
- const modelMessages = yield* MessageV2.toModelMessagesEffect(msgs, model, {
446
- stripMedia: true,
447
- toolOutputMaxChars: TOOL_OUTPUT_MAX_CHARS,
448
- })
449
- const tokens = Token.estimate(JSON.stringify(modelMessages))
450
- const ctx = yield* InstanceState.context
451
- const msg: MessageV2.Assistant = {
452
- id: MessageID.ascending(),
453
- role: "assistant",
454
- parentID: input.parentID,
455
- sessionID: input.sessionID,
456
- mode: "compaction",
457
- agent: "compaction",
458
- variant: userMessage.model.variant,
459
- summary: true,
460
- path: {
461
- cwd: ctx.directory,
462
- root: ctx.worktree,
463
- },
464
- cost: 0,
465
- tokens: {
466
- output: 0,
467
- input: 0,
468
- reasoning: 0,
469
- cache: { read: 0, write: 0 },
470
- },
471
- modelID: model.id,
472
- providerID: model.providerID,
473
- time: {
474
- created: Date.now(),
475
- },
476
- }
477
- yield* session.updateMessage(msg)
478
- const processor = yield* processors.create({
479
- assistantMessage: msg,
480
- sessionID: input.sessionID,
481
- model,
482
- })
483
- const result = SaeeolCompactionChunks.needed({ cfg, model, tokens })
484
- ? "compact"
485
- : yield* SaeeolCompactionPayloadRecovery.process({
486
- processor,
487
- user: userMessage,
488
- agent,
489
- sessionID: input.sessionID,
490
- model,
491
- messages: modelMessages,
492
- prompt: nextPrompt,
493
- recovery: selected.head,
494
- updateMessage: session.updateMessage,
495
- updatePart: session.updatePart,
496
- })
497
- const chunkOut: { tail_start_id?: MessageID } = {}
498
- const fallback = SaeeolCompactionChunks.eligible({
499
- result,
500
- error: processor.message.error ?? processor.compactError?.(),
501
- })
502
- ? yield* SaeeolCompactionChunks.process({
503
- processors,
504
- session,
505
- user: userMessage,
506
- agent,
507
- sessionID: input.sessionID,
508
- model,
509
- cfg,
510
- messages: selected.head,
511
- prompt: nextPrompt,
512
- target: processor.message,
513
- updateMessage: session.updateMessage,
514
- updatePart: session.updatePart,
515
- auto: input.auto,
516
- out: chunkOut,
517
- })
518
- : result
519
- const effectiveTail = chunkOut.tail_start_id ?? selected.tail_start_id
520
- if (fallback === "compact") {
521
- processor.message.error = new MessageV2.ContextOverflowError({
522
- message: replay
523
- ? "Conversation history too large to compact - exceeds model context limit"
524
- : "Session too large to compact - context exceeds model limit even after stripping media",
525
- }).toObject()
526
- processor.message.finish = "error"
527
- yield* session.updateMessage(processor.message)
528
- return "stop"
529
- }
530
-
531
- if (compactionPart && effectiveTail && compactionPart.tail_start_id !== effectiveTail) {
532
- yield* session.updatePart({
533
- ...compactionPart,
534
- tail_start_id: effectiveTail,
535
- })
536
- }
537
-
538
- if (fallback === "continue" && input.auto) {
539
- if (replay) {
540
- replay = yield* SaeeolCompactionChunks.replay({
541
- processors,
542
- session,
543
- user: userMessage,
544
- agent,
545
- sessionID: input.sessionID,
546
- model,
547
- cfg,
548
- messages: selected.head,
549
- prompt: nextPrompt,
550
- target: processor.message,
551
- updateMessage: session.updateMessage,
552
- updatePart: session.updatePart,
553
- replay,
554
- })
555
- const original = replay.info
556
- const replayMsg = yield* session.updateMessage({
557
- id: MessageID.ascending(),
558
- role: "user",
559
- sessionID: input.sessionID,
560
- time: { created: Date.now() },
561
- agent: original.agent,
562
- model: original.model,
563
- format: original.format,
564
- tools: original.tools,
565
- system: original.system,
566
- })
567
- SaeeolSessionPromptQueue.retarget(input.sessionID, replayMsg.id)
568
- for (const part of replay.parts) {
569
- if (part.type === "compaction") continue
570
- const replayPart =
571
- part.type === "file" && MessageV2.isMedia(part.mime)
572
- ? { type: "text" as const, text: `[Attached ${part.mime}: ${part.filename ?? "file"}]` }
573
- : part
574
- yield* session.updatePart({
575
- ...replayPart,
576
- id: PartID.ascending(),
577
- messageID: replayMsg.id,
578
- sessionID: input.sessionID,
579
- })
580
- }
581
- }
582
-
583
- if (!replay) {
584
- const info = yield* provider.getProvider(userMessage.model.providerID)
585
- if (
586
- (yield* plugin.trigger(
587
- "experimental.compaction.autocontinue",
588
- {
589
- sessionID: input.sessionID,
590
- agent: userMessage.agent,
591
- model: yield* provider.getModel(userMessage.model.providerID, userMessage.model.modelID),
592
- provider: {
593
- source: info.source,
594
- info,
595
- options: info.options,
596
- },
597
- message: userMessage,
598
- overflow: input.overflow === true,
599
- },
600
- { enabled: true },
601
- )).enabled
602
- ) {
603
- const continueMsg = yield* session.updateMessage({
604
- id: MessageID.ascending(),
605
- role: "user",
606
- sessionID: input.sessionID,
607
- time: { created: Date.now() },
608
- agent: userMessage.agent,
609
- model: userMessage.model,
610
- })
611
- SaeeolSessionPromptQueue.retarget(input.sessionID, continueMsg.id)
612
- const text =
613
- (input.overflow
614
- ? "The previous request exceeded the provider's size limit due to large media attachments. The conversation was compacted and media files were removed from context. If the user was asking about attached images or files, explain that the attachments were too large to process and suggest they try again with smaller or fewer files.\n\n"
615
- : "") +
616
- "Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed."
617
- yield* session.updatePart({
618
- id: PartID.ascending(),
619
- messageID: continueMsg.id,
620
- sessionID: input.sessionID,
621
- type: "text",
622
- // Internal marker for auto-compaction followups so provider plugins
623
- // can distinguish them from manual post-compaction user prompts.
624
- // This is not a stable plugin contract and may change or disappear.
625
- metadata: { compaction_continue: true },
626
- synthetic: true,
627
- text,
628
- time: {
629
- start: Date.now(),
630
- end: Date.now(),
631
- },
632
- })
633
- }
634
- }
635
- }
636
- if (processor.message.error) return "stop"
637
- if (fallback === "continue") {
638
- yield* prune({ sessionID: input.sessionID, reason: "post-compaction" })
639
- yield* bus.publish(Event.Compacted, { sessionID: input.sessionID })
640
- }
641
- return fallback
642
- })
643
-
644
- const create = Effect.fn("SessionCompaction.create")(function* (input: {
645
- sessionID: SessionID
646
- agent: string
647
- model: { providerID: ProviderID; modelID: ModelID }
648
- auto: boolean
649
- overflow?: boolean
650
- }) {
651
- const msg = yield* session.updateMessage({
652
- id: MessageID.ascending(),
653
- role: "user",
654
- model: input.model,
655
- sessionID: input.sessionID,
656
- agent: input.agent,
657
- time: { created: Date.now() },
658
- })
659
- yield* session.updatePart({
660
- id: PartID.ascending(),
661
- messageID: msg.id,
662
- sessionID: msg.sessionID,
663
- type: "compaction",
664
- auto: input.auto,
665
- overflow: input.overflow,
666
- })
667
- SaeeolSessionPromptQueue.retarget(input.sessionID, msg.id)
668
- })
669
-
670
- return Service.of({
671
- isOverflow,
672
- prune,
673
- process: processCompaction,
674
- create,
675
- })
676
- }),
677
- )
678
-
679
- export const defaultLayer = Layer.suspend(() =>
680
- layer.pipe(
681
- Layer.provide(Provider.defaultLayer),
682
- Layer.provide(Session.defaultLayer),
683
- Layer.provide(SessionProcessor.defaultLayer),
684
- Layer.provide(Agent.defaultLayer),
685
- Layer.provide(Plugin.defaultLayer),
686
- Layer.provide(Bus.layer),
687
- Layer.provide(Config.defaultLayer),
688
- ),
689
- )
690
-
691
- const { runPromise } = makeRuntime(Service, defaultLayer)
692
-
693
- export async function isOverflow(input: { tokens: MessageV2.Assistant["tokens"]; model: Provider.Model }) {
694
- return runPromise((svc) => svc.isOverflow(input))
695
- }
696
-
697
- export async function prune(input: { sessionID: SessionID; reason?: PruneReason }) {
698
- return runPromise((svc) => svc.prune(input))
699
- }
700
-
701
- export const create = fn(
702
- z.object({
703
- sessionID: SessionID.zod,
704
- agent: z.string(),
705
- model: z.object({ providerID: ProviderID.zod, modelID: ModelID.zod }),
706
- auto: z.boolean(),
707
- overflow: z.boolean().optional(),
708
- }),
709
- (input) => runPromise((svc) => svc.create(input)),
710
- )
711
-
712
- export * as SessionCompaction from "./compaction"
1
+ export * from "./core/compaction/compaction"