@openadapter/koda 1.0.0-beta.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 (357) hide show
  1. package/CHANGELOG.md +4448 -0
  2. package/README.md +665 -0
  3. package/dist/bun/cli.d.ts +2 -0
  4. package/dist/bun/cli.js +2 -0
  5. package/dist/bun/register-bedrock.d.ts +1 -0
  6. package/dist/bun/register-bedrock.js +1 -0
  7. package/dist/bun/restore-sandbox-env.d.ts +12 -0
  8. package/dist/bun/restore-sandbox-env.js +1 -0
  9. package/dist/cli/args.d.ts +55 -0
  10. package/dist/cli/args.js +167 -0
  11. package/dist/cli/config-selector.d.ts +13 -0
  12. package/dist/cli/config-selector.js +1 -0
  13. package/dist/cli/file-processor.d.ts +14 -0
  14. package/dist/cli/file-processor.js +7 -0
  15. package/dist/cli/import-sessions.d.ts +34 -0
  16. package/dist/cli/import-sessions.js +6 -0
  17. package/dist/cli/initial-message.d.ts +17 -0
  18. package/dist/cli/initial-message.js +1 -0
  19. package/dist/cli/list-models.d.ts +8 -0
  20. package/dist/cli/list-models.js +2 -0
  21. package/dist/cli/openadapter-setup.d.ts +29 -0
  22. package/dist/cli/openadapter-setup.js +3 -0
  23. package/dist/cli/session-picker.d.ts +8 -0
  24. package/dist/cli/session-picker.js +1 -0
  25. package/dist/cli.d.ts +2 -0
  26. package/dist/cli.js +2 -0
  27. package/dist/config.d.ts +92 -0
  28. package/dist/config.js +1 -0
  29. package/dist/core/agent-session-runtime.d.ts +116 -0
  30. package/dist/core/agent-session-runtime.js +1 -0
  31. package/dist/core/agent-session-services.d.ts +86 -0
  32. package/dist/core/agent-session-services.js +1 -0
  33. package/dist/core/agent-session.d.ts +747 -0
  34. package/dist/core/agent-session.js +32 -0
  35. package/dist/core/auth-guidance.d.ts +4 -0
  36. package/dist/core/auth-guidance.js +8 -0
  37. package/dist/core/auth-storage.d.ts +140 -0
  38. package/dist/core/auth-storage.js +1 -0
  39. package/dist/core/bash-executor.d.ts +31 -0
  40. package/dist/core/bash-executor.js +1 -0
  41. package/dist/core/compaction/branch-summarization.d.ts +89 -0
  42. package/dist/core/compaction/branch-summarization.js +38 -0
  43. package/dist/core/compaction/compaction.d.ts +120 -0
  44. package/dist/core/compaction/compaction.js +104 -0
  45. package/dist/core/compaction/index.d.ts +6 -0
  46. package/dist/core/compaction/index.js +1 -0
  47. package/dist/core/compaction/utils.d.ts +37 -0
  48. package/dist/core/compaction/utils.js +19 -0
  49. package/dist/core/defaults.d.ts +2 -0
  50. package/dist/core/defaults.js +1 -0
  51. package/dist/core/diagnostics.d.ts +14 -0
  52. package/dist/core/diagnostics.js +0 -0
  53. package/dist/core/event-bus.d.ts +8 -0
  54. package/dist/core/event-bus.js +1 -0
  55. package/dist/core/exec.d.ts +28 -0
  56. package/dist/core/exec.js +1 -0
  57. package/dist/core/export-html/ansi-to-html.d.ts +21 -0
  58. package/dist/core/export-html/ansi-to-html.js +1 -0
  59. package/dist/core/export-html/index.d.ts +36 -0
  60. package/dist/core/export-html/index.js +2 -0
  61. package/dist/core/export-html/template.css +1066 -0
  62. package/dist/core/export-html/template.html +55 -0
  63. package/dist/core/export-html/template.js +72 -0
  64. package/dist/core/export-html/tool-renderer.d.ts +33 -0
  65. package/dist/core/export-html/tool-renderer.js +1 -0
  66. package/dist/core/export-html/vendor/highlight.min.js +8 -0
  67. package/dist/core/export-html/vendor/marked.min.js +56 -0
  68. package/dist/core/extensions/index.d.ts +11 -0
  69. package/dist/core/extensions/index.js +1 -0
  70. package/dist/core/extensions/loader.d.ts +23 -0
  71. package/dist/core/extensions/loader.js +1 -0
  72. package/dist/core/extensions/runner.d.ts +160 -0
  73. package/dist/core/extensions/runner.js +1 -0
  74. package/dist/core/extensions/types.d.ts +1180 -0
  75. package/dist/core/extensions/types.js +1 -0
  76. package/dist/core/extensions/wrapper.d.ts +19 -0
  77. package/dist/core/extensions/wrapper.js +1 -0
  78. package/dist/core/footer-data-provider.d.ts +53 -0
  79. package/dist/core/footer-data-provider.js +1 -0
  80. package/dist/core/http-dispatcher.d.ts +20 -0
  81. package/dist/core/http-dispatcher.js +1 -0
  82. package/dist/core/index.d.ts +11 -0
  83. package/dist/core/index.js +1 -0
  84. package/dist/core/keybindings.d.ts +352 -0
  85. package/dist/core/keybindings.js +1 -0
  86. package/dist/core/messages.d.ts +76 -0
  87. package/dist/core/messages.js +17 -0
  88. package/dist/core/model-registry.d.ts +149 -0
  89. package/dist/core/model-registry.js +9 -0
  90. package/dist/core/model-resolver.d.ts +109 -0
  91. package/dist/core/model-resolver.js +1 -0
  92. package/dist/core/output-guard.d.ts +6 -0
  93. package/dist/core/output-guard.js +1 -0
  94. package/dist/core/package-manager.d.ts +203 -0
  95. package/dist/core/package-manager.js +3 -0
  96. package/dist/core/prompt-templates.d.ts +51 -0
  97. package/dist/core/prompt-templates.js +2 -0
  98. package/dist/core/provider-attribution.d.ts +3 -0
  99. package/dist/core/provider-attribution.js +1 -0
  100. package/dist/core/provider-display-names.d.ts +1 -0
  101. package/dist/core/provider-display-names.js +1 -0
  102. package/dist/core/resolve-config-value.d.ts +30 -0
  103. package/dist/core/resolve-config-value.js +1 -0
  104. package/dist/core/resource-loader.d.ts +193 -0
  105. package/dist/core/resource-loader.js +1 -0
  106. package/dist/core/sdk.d.ts +108 -0
  107. package/dist/core/sdk.js +1 -0
  108. package/dist/core/session-cwd.d.ts +18 -0
  109. package/dist/core/session-cwd.js +7 -0
  110. package/dist/core/session-manager.d.ts +331 -0
  111. package/dist/core/session-manager.js +11 -0
  112. package/dist/core/settings-manager.d.ts +265 -0
  113. package/dist/core/settings-manager.js +1 -0
  114. package/dist/core/skills.d.ts +59 -0
  115. package/dist/core/skills.js +4 -0
  116. package/dist/core/slash-commands.d.ts +13 -0
  117. package/dist/core/slash-commands.js +1 -0
  118. package/dist/core/source-info.d.ts +17 -0
  119. package/dist/core/source-info.js +1 -0
  120. package/dist/core/system-prompt.d.ts +27 -0
  121. package/dist/core/system-prompt.js +52 -0
  122. package/dist/core/telemetry.d.ts +2 -0
  123. package/dist/core/telemetry.js +1 -0
  124. package/dist/core/timings.d.ts +7 -0
  125. package/dist/core/timings.js +3 -0
  126. package/dist/core/tools/bash.d.ts +67 -0
  127. package/dist/core/tools/bash.js +18 -0
  128. package/dist/core/tools/edit-diff.d.ts +86 -0
  129. package/dist/core/tools/edit-diff.js +16 -0
  130. package/dist/core/tools/edit.d.ts +50 -0
  131. package/dist/core/tools/edit.js +2 -0
  132. package/dist/core/tools/file-mutation-queue.d.ts +5 -0
  133. package/dist/core/tools/file-mutation-queue.js +1 -0
  134. package/dist/core/tools/find.d.ts +34 -0
  135. package/dist/core/tools/find.js +13 -0
  136. package/dist/core/tools/grep.d.ts +36 -0
  137. package/dist/core/tools/grep.js +13 -0
  138. package/dist/core/tools/index.d.ts +39 -0
  139. package/dist/core/tools/index.js +1 -0
  140. package/dist/core/tools/ls.d.ts +36 -0
  141. package/dist/core/tools/ls.js +9 -0
  142. package/dist/core/tools/output-accumulator.d.ts +51 -0
  143. package/dist/core/tools/output-accumulator.js +4 -0
  144. package/dist/core/tools/path-utils.d.ts +9 -0
  145. package/dist/core/tools/path-utils.js +1 -0
  146. package/dist/core/tools/read.d.ts +34 -0
  147. package/dist/core/tools/read.js +22 -0
  148. package/dist/core/tools/render-utils.d.ts +23 -0
  149. package/dist/core/tools/render-utils.js +4 -0
  150. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
  151. package/dist/core/tools/tool-definition-wrapper.js +1 -0
  152. package/dist/core/tools/truncate.d.ts +69 -0
  153. package/dist/core/tools/truncate.js +5 -0
  154. package/dist/core/tools/write.d.ts +25 -0
  155. package/dist/core/tools/write.js +13 -0
  156. package/dist/index.d.ts +30 -0
  157. package/dist/index.js +1 -0
  158. package/dist/main.d.ts +11 -0
  159. package/dist/main.js +1 -0
  160. package/dist/migrations.d.ts +32 -0
  161. package/dist/migrations.js +8 -0
  162. package/dist/modes/index.d.ts +8 -0
  163. package/dist/modes/index.js +1 -0
  164. package/dist/modes/interactive/assets/clankolas.png +0 -0
  165. package/dist/modes/interactive/components/armin.d.ts +33 -0
  166. package/dist/modes/interactive/components/armin.js +1 -0
  167. package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
  168. package/dist/modes/interactive/components/assistant-message.js +1 -0
  169. package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
  170. package/dist/modes/interactive/components/bash-execution.js +13 -0
  171. package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
  172. package/dist/modes/interactive/components/bordered-loader.js +1 -0
  173. package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
  174. package/dist/modes/interactive/components/branch-summary-message.js +3 -0
  175. package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
  176. package/dist/modes/interactive/components/compaction-summary-message.js +3 -0
  177. package/dist/modes/interactive/components/config-selector.d.ts +70 -0
  178. package/dist/modes/interactive/components/config-selector.js +1 -0
  179. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
  180. package/dist/modes/interactive/components/countdown-timer.js +1 -0
  181. package/dist/modes/interactive/components/custom-editor.d.ts +20 -0
  182. package/dist/modes/interactive/components/custom-editor.js +1 -0
  183. package/dist/modes/interactive/components/custom-message.d.ts +19 -0
  184. package/dist/modes/interactive/components/custom-message.js +2 -0
  185. package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
  186. package/dist/modes/interactive/components/daxnuts.js +1 -0
  187. package/dist/modes/interactive/components/diff.d.ts +11 -0
  188. package/dist/modes/interactive/components/diff.js +3 -0
  189. package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
  190. package/dist/modes/interactive/components/dynamic-border.js +1 -0
  191. package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
  192. package/dist/modes/interactive/components/earendil-announcement.js +1 -0
  193. package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
  194. package/dist/modes/interactive/components/extension-editor.js +3 -0
  195. package/dist/modes/interactive/components/extension-input.d.ts +22 -0
  196. package/dist/modes/interactive/components/extension-input.js +2 -0
  197. package/dist/modes/interactive/components/extension-selector.d.ts +25 -0
  198. package/dist/modes/interactive/components/extension-selector.js +2 -0
  199. package/dist/modes/interactive/components/footer.d.ts +27 -0
  200. package/dist/modes/interactive/components/footer.js +1 -0
  201. package/dist/modes/interactive/components/index.d.ts +31 -0
  202. package/dist/modes/interactive/components/index.js +1 -0
  203. package/dist/modes/interactive/components/keybinding-hints.d.ts +12 -0
  204. package/dist/modes/interactive/components/keybinding-hints.js +1 -0
  205. package/dist/modes/interactive/components/login-dialog.d.ts +51 -0
  206. package/dist/modes/interactive/components/login-dialog.js +1 -0
  207. package/dist/modes/interactive/components/model-selector.d.ts +46 -0
  208. package/dist/modes/interactive/components/model-selector.js +2 -0
  209. package/dist/modes/interactive/components/oauth-selector.d.ts +30 -0
  210. package/dist/modes/interactive/components/oauth-selector.js +1 -0
  211. package/dist/modes/interactive/components/scoped-models-selector.d.ts +41 -0
  212. package/dist/modes/interactive/components/scoped-models-selector.js +1 -0
  213. package/dist/modes/interactive/components/session-selector-search.d.ts +22 -0
  214. package/dist/modes/interactive/components/session-selector-search.js +1 -0
  215. package/dist/modes/interactive/components/session-selector.d.ts +95 -0
  216. package/dist/modes/interactive/components/session-selector.js +2 -0
  217. package/dist/modes/interactive/components/settings-selector.d.ts +68 -0
  218. package/dist/modes/interactive/components/settings-selector.js +1 -0
  219. package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
  220. package/dist/modes/interactive/components/show-images-selector.js +1 -0
  221. package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
  222. package/dist/modes/interactive/components/skill-invocation-message.js +3 -0
  223. package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
  224. package/dist/modes/interactive/components/theme-selector.js +1 -0
  225. package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
  226. package/dist/modes/interactive/components/thinking-selector.js +1 -0
  227. package/dist/modes/interactive/components/tool-execution.d.ts +62 -0
  228. package/dist/modes/interactive/components/tool-execution.js +4 -0
  229. package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
  230. package/dist/modes/interactive/components/tree-selector.js +1 -0
  231. package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
  232. package/dist/modes/interactive/components/user-message-selector.js +1 -0
  233. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  234. package/dist/modes/interactive/components/user-message.js +1 -0
  235. package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
  236. package/dist/modes/interactive/components/visual-truncate.js +1 -0
  237. package/dist/modes/interactive/interactive-mode.d.ts +417 -0
  238. package/dist/modes/interactive/interactive-mode.js +116 -0
  239. package/dist/modes/interactive/theme/dark.json +86 -0
  240. package/dist/modes/interactive/theme/light.json +85 -0
  241. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  242. package/dist/modes/interactive/theme/theme.d.ts +101 -0
  243. package/dist/modes/interactive/theme/theme.js +18 -0
  244. package/dist/modes/print-mode.d.ts +27 -0
  245. package/dist/modes/print-mode.js +4 -0
  246. package/dist/modes/rpc/jsonl.d.ts +16 -0
  247. package/dist/modes/rpc/jsonl.js +3 -0
  248. package/dist/modes/rpc/rpc-client.d.ts +226 -0
  249. package/dist/modes/rpc/rpc-client.js +1 -0
  250. package/dist/modes/rpc/rpc-mode.d.ts +19 -0
  251. package/dist/modes/rpc/rpc-mode.js +1 -0
  252. package/dist/modes/rpc/rpc-types.d.ts +419 -0
  253. package/dist/modes/rpc/rpc-types.js +0 -0
  254. package/dist/package-manager-cli.d.ts +3 -0
  255. package/dist/package-manager-cli.js +49 -0
  256. package/dist/utils/ansi.d.ts +1 -0
  257. package/dist/utils/ansi.js +1 -0
  258. package/dist/utils/auto-update.d.ts +13 -0
  259. package/dist/utils/auto-update.js +1 -0
  260. package/dist/utils/changelog.d.ts +20 -0
  261. package/dist/utils/changelog.js +4 -0
  262. package/dist/utils/child-process.d.ts +14 -0
  263. package/dist/utils/child-process.js +1 -0
  264. package/dist/utils/clipboard-image.d.ts +10 -0
  265. package/dist/utils/clipboard-image.js +1 -0
  266. package/dist/utils/clipboard-native.d.ts +9 -0
  267. package/dist/utils/clipboard-native.js +1 -0
  268. package/dist/utils/clipboard.d.ts +1 -0
  269. package/dist/utils/clipboard.js +1 -0
  270. package/dist/utils/deprecation.d.ts +3 -0
  271. package/dist/utils/deprecation.js +1 -0
  272. package/dist/utils/exif-orientation.d.ts +4 -0
  273. package/dist/utils/exif-orientation.js +1 -0
  274. package/dist/utils/frontmatter.d.ts +7 -0
  275. package/dist/utils/frontmatter.js +4 -0
  276. package/dist/utils/fs-watch.d.ts +4 -0
  277. package/dist/utils/fs-watch.js +1 -0
  278. package/dist/utils/git.d.ts +25 -0
  279. package/dist/utils/git.js +1 -0
  280. package/dist/utils/html.d.ts +6 -0
  281. package/dist/utils/html.js +1 -0
  282. package/dist/utils/image-convert.d.ts +8 -0
  283. package/dist/utils/image-convert.js +1 -0
  284. package/dist/utils/image-resize-core.d.ts +29 -0
  285. package/dist/utils/image-resize-core.js +1 -0
  286. package/dist/utils/image-resize-worker.d.ts +1 -0
  287. package/dist/utils/image-resize-worker.js +1 -0
  288. package/dist/utils/image-resize.d.ts +15 -0
  289. package/dist/utils/image-resize.js +1 -0
  290. package/dist/utils/json.d.ts +2 -0
  291. package/dist/utils/json.js +1 -0
  292. package/dist/utils/koda-user-agent.d.ts +1 -0
  293. package/dist/utils/koda-user-agent.js +1 -0
  294. package/dist/utils/mime.d.ts +2 -0
  295. package/dist/utils/mime.js +1 -0
  296. package/dist/utils/paths.d.ts +30 -0
  297. package/dist/utils/paths.js +1 -0
  298. package/dist/utils/photon.d.ts +20 -0
  299. package/dist/utils/photon.js +1 -0
  300. package/dist/utils/shell.d.ts +29 -0
  301. package/dist/utils/shell.js +8 -0
  302. package/dist/utils/sleep.d.ts +4 -0
  303. package/dist/utils/sleep.js +1 -0
  304. package/dist/utils/syntax-highlight.d.ts +11 -0
  305. package/dist/utils/syntax-highlight.js +2 -0
  306. package/dist/utils/tools-manager.d.ts +2 -0
  307. package/dist/utils/tools-manager.js +1 -0
  308. package/dist/utils/version-check.d.ts +14 -0
  309. package/dist/utils/version-check.js +1 -0
  310. package/dist/utils/windows-self-update.d.ts +2 -0
  311. package/dist/utils/windows-self-update.js +1 -0
  312. package/docs/compaction.md +394 -0
  313. package/docs/custom-provider.md +736 -0
  314. package/docs/development.md +71 -0
  315. package/docs/docs.json +148 -0
  316. package/docs/extensions.md +2626 -0
  317. package/docs/images/doom-extension.png +0 -0
  318. package/docs/images/exy.png +0 -0
  319. package/docs/images/interactive-mode.png +0 -0
  320. package/docs/images/tree-view.png +0 -0
  321. package/docs/index.md +80 -0
  322. package/docs/json.md +82 -0
  323. package/docs/keybindings.md +197 -0
  324. package/docs/models.md +493 -0
  325. package/docs/packages.md +226 -0
  326. package/docs/prompt-templates.md +88 -0
  327. package/docs/providers.md +253 -0
  328. package/docs/quickstart.md +165 -0
  329. package/docs/rpc.md +1408 -0
  330. package/docs/sdk.md +1137 -0
  331. package/docs/session-format.md +412 -0
  332. package/docs/sessions.md +145 -0
  333. package/docs/settings.md +281 -0
  334. package/docs/shell-aliases.md +13 -0
  335. package/docs/skills.md +231 -0
  336. package/docs/terminal-setup.md +114 -0
  337. package/docs/termux.md +127 -0
  338. package/docs/themes.md +295 -0
  339. package/docs/tmux.md +61 -0
  340. package/docs/tui.md +927 -0
  341. package/docs/usage.md +288 -0
  342. package/docs/windows.md +17 -0
  343. package/npm-shrinkwrap.json +1792 -0
  344. package/openadapter/extensions/koda-ask.js +12 -0
  345. package/openadapter/extensions/koda-bg.js +14 -0
  346. package/openadapter/extensions/koda-commands.mjs +15 -0
  347. package/openadapter/extensions/koda-help.js +8 -0
  348. package/openadapter/extensions/koda-memory.js +16 -0
  349. package/openadapter/extensions/koda-status.js +1 -0
  350. package/openadapter/extensions/koda-todo.js +4 -0
  351. package/openadapter/extensions/koda-vision.js +4 -0
  352. package/openadapter/extensions/koda-web.js +7 -0
  353. package/openadapter/setup.mjs +173 -0
  354. package/openadapter/skills/code-review/SKILL.md +22 -0
  355. package/openadapter/skills/debugging/SKILL.md +28 -0
  356. package/openadapter/skills/frontend/SKILL.md +38 -0
  357. package/package.json +108 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Context compaction for long sessions.
3
+ *
4
+ * Pure functions for compaction logic. The session manager handles I/O,
5
+ * and after compaction the session is reloaded.
6
+ */
7
+ import type { AgentMessage, StreamFn, ThinkingLevel } from "@openadapter/koda-agent-core";
8
+ import type { Model, Usage } from "@openadapter/koda-ai";
9
+ import { type SessionEntry } from "../session-manager.ts";
10
+ import { type FileOperations } from "./utils.ts";
11
+ /** Details stored in CompactionEntry.details for file tracking */
12
+ export interface CompactionDetails {
13
+ readFiles: string[];
14
+ modifiedFiles: string[];
15
+ }
16
+ /** Result from compact() - SessionManager adds uuid/parentUuid when saving */
17
+ export interface CompactionResult<T = unknown> {
18
+ summary: string;
19
+ firstKeptEntryId: string;
20
+ tokensBefore: number;
21
+ /** Extension-specific data (e.g., ArtifactIndex, version markers for structured compaction) */
22
+ details?: T;
23
+ }
24
+ export interface CompactionSettings {
25
+ enabled: boolean;
26
+ reserveTokens: number;
27
+ keepRecentTokens: number;
28
+ }
29
+ export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
30
+ /**
31
+ * Calculate total context tokens from usage.
32
+ * Uses the native totalTokens field when available, falls back to computing from components.
33
+ */
34
+ export declare function calculateContextTokens(usage: Usage): number;
35
+ /**
36
+ * Find the last non-aborted assistant message usage from session entries.
37
+ */
38
+ export declare function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined;
39
+ export interface ContextUsageEstimate {
40
+ tokens: number;
41
+ usageTokens: number;
42
+ trailingTokens: number;
43
+ lastUsageIndex: number | null;
44
+ }
45
+ /**
46
+ * Estimate context tokens from messages, using the last assistant usage when available.
47
+ * If there are messages after the last usage, estimate their tokens with estimateTokens.
48
+ */
49
+ export declare function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate;
50
+ /**
51
+ * Check if compaction should trigger based on context usage.
52
+ */
53
+ export declare function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean;
54
+ /**
55
+ * Estimate token count for a message using chars/4 heuristic.
56
+ * This is conservative (overestimates tokens).
57
+ */
58
+ export declare function estimateTokens(message: AgentMessage): number;
59
+ /**
60
+ * Find the user message (or bashExecution) that starts the turn containing the given entry index.
61
+ * Returns -1 if no turn start found before the index.
62
+ * BashExecutionMessage is treated like a user message for turn boundaries.
63
+ */
64
+ export declare function findTurnStartIndex(entries: SessionEntry[], entryIndex: number, startIndex: number): number;
65
+ export interface CutPointResult {
66
+ /** Index of first entry to keep */
67
+ firstKeptEntryIndex: number;
68
+ /** Index of user message that starts the turn being split, or -1 if not splitting */
69
+ turnStartIndex: number;
70
+ /** Whether this cut splits a turn (cut point is not a user message) */
71
+ isSplitTurn: boolean;
72
+ }
73
+ /**
74
+ * Find the cut point in session entries that keeps approximately `keepRecentTokens`.
75
+ *
76
+ * Algorithm: Walk backwards from newest, accumulating estimated message sizes.
77
+ * Stop when we've accumulated >= keepRecentTokens. Cut at that point.
78
+ *
79
+ * Can cut at user OR assistant messages (never tool results). When cutting at an
80
+ * assistant message with tool calls, its tool results come after and will be kept.
81
+ *
82
+ * Returns CutPointResult with:
83
+ * - firstKeptEntryIndex: the entry index to start keeping from
84
+ * - turnStartIndex: if cutting mid-turn, the user message that started that turn
85
+ * - isSplitTurn: whether we're cutting in the middle of a turn
86
+ *
87
+ * Only considers entries between `startIndex` and `endIndex` (exclusive).
88
+ */
89
+ export declare function findCutPoint(entries: SessionEntry[], startIndex: number, endIndex: number, keepRecentTokens: number): CutPointResult;
90
+ /**
91
+ * Generate a summary of the conversation using the LLM.
92
+ * If previousSummary is provided, uses the update prompt to merge.
93
+ */
94
+ export declare function generateSummary(currentMessages: AgentMessage[], model: Model<any>, reserveTokens: number, apiKey: string | undefined, headers?: Record<string, string>, signal?: AbortSignal, customInstructions?: string, previousSummary?: string, thinkingLevel?: ThinkingLevel, streamFn?: StreamFn): Promise<string>;
95
+ export interface CompactionPreparation {
96
+ /** UUID of first entry to keep */
97
+ firstKeptEntryId: string;
98
+ /** Messages that will be summarized and discarded */
99
+ messagesToSummarize: AgentMessage[];
100
+ /** Messages that will be turned into turn prefix summary (if splitting) */
101
+ turnPrefixMessages: AgentMessage[];
102
+ /** Whether this is a split turn (cut point in middle of turn) */
103
+ isSplitTurn: boolean;
104
+ tokensBefore: number;
105
+ /** Summary from previous compaction, for iterative update */
106
+ previousSummary?: string;
107
+ /** File operations extracted from messagesToSummarize */
108
+ fileOps: FileOperations;
109
+ /** Compaction settions from settings.jsonl */
110
+ settings: CompactionSettings;
111
+ }
112
+ export declare function prepareCompaction(pathEntries: SessionEntry[], settings: CompactionSettings): CompactionPreparation | undefined;
113
+ /**
114
+ * Generate summaries for compaction using prepared data.
115
+ * Returns CompactionResult - SessionManager adds uuid/parentUuid when saving.
116
+ *
117
+ * @param preparation - Pre-calculated preparation from prepareCompaction()
118
+ * @param customInstructions - Optional custom focus for the summary
119
+ */
120
+ export declare function compact(preparation: CompactionPreparation, model: Model<any>, apiKey: string | undefined, headers?: Record<string, string>, customInstructions?: string, signal?: AbortSignal, thinkingLevel?: ThinkingLevel, streamFn?: StreamFn): Promise<CompactionResult>;
@@ -0,0 +1,104 @@
1
+ var _=Object.defineProperty;var u=(e,t)=>_(e,"name",{value:t,configurable:!0});import{completeSimple as U}from"@openadapter/koda-ai";import{convertToLlm as I,createBranchSummaryMessage as F,createCompactionSummaryMessage as N,createCustomMessage as D}from"../messages.js";import{buildSessionContext as K}from"../session-manager.js";import{computeFileLists as z,createFileOps as $,extractFileOpsFromMessage as P,formatFileOperations as B,SUMMARIZATION_SYSTEM_PROMPT as v,serializeConversation as w}from"./utils.js";function V(e,t,n){const s=$();if(n>=0){const o=t[n];if(!o.fromHook&&o.details){const r=o.details;if(Array.isArray(r.readFiles))for(const a of r.readFiles)s.read.add(a);if(Array.isArray(r.modifiedFiles))for(const a of r.modifiedFiles)s.edited.add(a)}}for(const o of e)P(o,s);return s}u(V,"extractFileOperations");function X(e){if(e.type==="message")return e.message;if(e.type==="custom_message")return D(e.customType,e.content,e.display,e.details,e.timestamp);if(e.type==="branch_summary")return F(e.summary,e.fromId,e.timestamp);if(e.type==="compaction")return N(e.summary,e.tokensBefore,e.timestamp)}u(X,"getMessageFromEntry");function M(e){if(e.type!=="compaction")return X(e)}u(M,"getMessageFromEntryForCompaction");const ie={enabled:!0,reserveTokens:16384,keepRecentTokens:2e4};function G(e){return e.totalTokens||e.input+e.output+e.cacheRead+e.cacheWrite}u(G,"calculateContextTokens");function b(e){if(e.role==="assistant"&&"usage"in e){const t=e;if(t.stopReason!=="aborted"&&t.stopReason!=="error"&&t.usage)return t.usage}}u(b,"getAssistantUsage");function ae(e){for(let t=e.length-1;t>=0;t--){const n=e[t];if(n.type==="message"){const s=b(n.message);if(s)return s}}}u(ae,"getLastAssistantUsage");function L(e){for(let t=e.length-1;t>=0;t--){const n=b(e[t]);if(n)return{usage:n,index:t}}}u(L,"getLastAssistantUsageInfo");function W(e){const t=L(e);if(!t){let o=0;for(const r of e)o+=S(r);return{tokens:o,usageTokens:0,trailingTokens:o,lastUsageIndex:null}}const n=G(t.usage);let s=0;for(let o=t.index+1;o<e.length;o++)s+=S(e[o]);return{tokens:n+s,usageTokens:n,trailingTokens:s,lastUsageIndex:t.index}}u(W,"estimateContextTokens");function ce(e,t,n){return n.enabled?e>t-n.reserveTokens:!1}u(ce,"shouldCompact");const Z=4800;function C(e){if(typeof e=="string")return e.length;let t=0;for(const n of e)n.type==="text"&&n.text?t+=n.text.length:n.type==="image"&&(t+=Z);return t}u(C,"estimateTextAndImageContentChars");function S(e){let t=0;switch(e.role){case"user":return t=C(e.content),Math.ceil(t/4);case"assistant":{const n=e;for(const s of n.content)s.type==="text"?t+=s.text.length:s.type==="thinking"?t+=s.thinking.length:s.type==="toolCall"&&(t+=s.name.length+JSON.stringify(s.arguments).length);return Math.ceil(t/4)}case"custom":case"toolResult":return t=C(e.content),Math.ceil(t/4);case"bashExecution":return t=e.command.length+e.output.length,Math.ceil(t/4);case"branchSummary":case"compactionSummary":return t=e.summary.length,Math.ceil(t/4)}return 0}u(S,"estimateTokens");function Y(e,t,n){const s=[];for(let o=t;o<n;o++){const r=e[o];switch(r.type){case"message":{switch(r.message.role){case"bashExecution":case"custom":case"branchSummary":case"compactionSummary":case"user":case"assistant":s.push(o);break;case"toolResult":break}break}case"thinking_level_change":case"model_change":case"compaction":case"branch_summary":case"custom":case"custom_message":case"label":case"session_info":break}(r.type==="branch_summary"||r.type==="custom_message")&&s.push(o)}return s}u(Y,"findValidCutPoints");function j(e,t,n){for(let s=t;s>=n;s--){const o=e[s];if(o.type==="branch_summary"||o.type==="custom_message")return s;if(o.type==="message"){const r=o.message.role;if(r==="user"||r==="bashExecution")return s}}return-1}u(j,"findTurnStartIndex");function q(e,t,n,s){const o=Y(e,t,n);if(o.length===0)return{firstKeptEntryIndex:t,turnStartIndex:-1,isSplitTurn:!1};let r=0,a=o[0];for(let m=n-1;m>=t;m--){const p=e[m];if(p.type!=="message")continue;const x=S(p.message);if(r+=x,r>=s){for(let f=0;f<o.length;f++)if(o[f]>=m){a=o[f];break}break}}for(;a>t;){const m=e[a-1];if(m.type==="compaction"||m.type==="message")break;a--}const c=e[a],d=c.type==="message"&&c.message.role==="user",g=d?-1:j(e,a,t);return{firstKeptEntryIndex:a,turnStartIndex:g,isSplitTurn:!d&&g!==-1}}u(q,"findCutPoint");const H=`The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.
2
+
3
+ Use this EXACT format:
4
+
5
+ ## Goal
6
+ [What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]
7
+
8
+ ## Constraints & Preferences
9
+ - [Any constraints, preferences, or requirements mentioned by user]
10
+ - [Or "(none)" if none were mentioned]
11
+
12
+ ## Progress
13
+ ### Done
14
+ - [x] [Completed tasks/changes]
15
+
16
+ ### In Progress
17
+ - [ ] [Current work]
18
+
19
+ ### Blocked
20
+ - [Issues preventing progress, if any]
21
+
22
+ ## Key Decisions
23
+ - **[Decision]**: [Brief rationale]
24
+
25
+ ## Next Steps
26
+ 1. [Ordered list of what should happen next]
27
+
28
+ ## Critical Context
29
+ - [Any data, examples, or references needed to continue]
30
+ - [Or "(none)" if not applicable]
31
+
32
+ Keep each section concise. Preserve exact file paths, function names, and error messages.`,J=`The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.
33
+
34
+ Update the existing structured summary with new information. RULES:
35
+ - PRESERVE all existing information from the previous summary
36
+ - ADD new progress, decisions, and context from the new messages
37
+ - UPDATE the Progress section: move items from "In Progress" to "Done" when completed
38
+ - UPDATE "Next Steps" based on what was accomplished
39
+ - PRESERVE exact file paths, function names, and error messages
40
+ - If something is no longer relevant, you may remove it
41
+
42
+ Use this EXACT format:
43
+
44
+ ## Goal
45
+ [Preserve existing goals, add new ones if the task expanded]
46
+
47
+ ## Constraints & Preferences
48
+ - [Preserve existing, add new ones discovered]
49
+
50
+ ## Progress
51
+ ### Done
52
+ - [x] [Include previously done items AND newly completed items]
53
+
54
+ ### In Progress
55
+ - [ ] [Current work - update based on progress]
56
+
57
+ ### Blocked
58
+ - [Current blockers - remove if resolved]
59
+
60
+ ## Key Decisions
61
+ - **[Decision]**: [Brief rationale] (preserve all previous, add new)
62
+
63
+ ## Next Steps
64
+ 1. [Update based on current state]
65
+
66
+ ## Critical Context
67
+ - [Preserve important context, add new if needed]
68
+
69
+ Keep each section concise. Preserve exact file paths, function names, and error messages.`;function E(e,t,n,s,o,r){const a={maxTokens:t,signal:o,apiKey:n,headers:s};return e.reasoning&&r&&r!=="off"&&(a.reasoning=r),a}u(E,"createSummarizationOptions");async function A(e,t,n,s){return s?(await s(e,t,n)).result():U(e,t,n)}u(A,"completeSummarization");async function R(e,t,n,s,o,r,a,c,d,g){const m=Math.min(Math.floor(.8*n),t.maxTokens>0?t.maxTokens:Number.POSITIVE_INFINITY);let p=c?J:H;a&&(p=`${p}
70
+
71
+ Additional focus: ${a}`);const x=I(e);let i=`<conversation>
72
+ ${w(x)}
73
+ </conversation>
74
+
75
+ `;c&&(i+=`<previous-summary>
76
+ ${c}
77
+ </previous-summary>
78
+
79
+ `),i+=p;const l=[{role:"user",content:[{type:"text",text:i}],timestamp:Date.now()}],h=E(t,m,s,o,r,d),y=await A(t,{systemPrompt:v,messages:l},h,g);if(y.stopReason==="error")throw new Error(`Summarization failed: ${y.errorMessage||"Unknown error"}`);return y.content.filter(T=>T.type==="text").map(T=>T.text).join(`
80
+ `)}u(R,"generateSummary");function ue(e,t){if(e.length>0&&e[e.length-1].type==="compaction")return;let n=-1;for(let i=e.length-1;i>=0;i--)if(e[i].type==="compaction"){n=i;break}let s,o=0;if(n>=0){const i=e[n];s=i.summary;const l=e.findIndex(h=>h.id===i.firstKeptEntryId);o=l>=0?l:n+1}const r=e.length,a=W(K(e).messages).tokens,c=q(e,o,r,t.keepRecentTokens),d=e[c.firstKeptEntryIndex];if(!d?.id)return;const g=d.id,m=c.isSplitTurn?c.turnStartIndex:c.firstKeptEntryIndex,p=[];for(let i=o;i<m;i++){const l=M(e[i]);l&&p.push(l)}const x=[];if(c.isSplitTurn)for(let i=c.turnStartIndex;i<c.firstKeptEntryIndex;i++){const l=M(e[i]);l&&x.push(l)}const f=V(p,e,n);if(c.isSplitTurn)for(const i of x)P(i,f);return{firstKeptEntryId:g,messagesToSummarize:p,turnPrefixMessages:x,isSplitTurn:c.isSplitTurn,tokensBefore:a,previousSummary:s,fileOps:f,settings:t}}u(ue,"prepareCompaction");const Q=`This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.
81
+
82
+ Summarize the prefix to provide context for the retained suffix:
83
+
84
+ ## Original Request
85
+ [What did the user ask for in this turn?]
86
+
87
+ ## Early Progress
88
+ - [Key decisions and work done in the prefix]
89
+
90
+ ## Context for Suffix
91
+ - [Information needed to understand the retained recent work]
92
+
93
+ Be concise. Focus on what's needed to understand the kept suffix.`;async function me(e,t,n,s,o,r,a,c){const{firstKeptEntryId:d,messagesToSummarize:g,turnPrefixMessages:m,isSplitTurn:p,tokensBefore:x,previousSummary:f,fileOps:i,settings:l}=e;let h;if(p&&m.length>0){const[T,O]=await Promise.all([g.length>0?R(g,t,l.reserveTokens,n,s,r,o,f,a,c):Promise.resolve("No prior history."),ee(m,t,l.reserveTokens,n,s,r,a,c)]);h=`${T}
94
+
95
+ ---
96
+
97
+ **Turn Context (split turn):**
98
+
99
+ ${O}`}else h=await R(g,t,l.reserveTokens,n,s,r,o,f,a,c);const{readFiles:y,modifiedFiles:k}=z(i);if(h+=B(y,k),!d)throw new Error("First kept entry has no UUID - session may need migration");return{summary:h,firstKeptEntryId:d,tokensBefore:x,details:{readFiles:y,modifiedFiles:k}}}u(me,"compact");async function ee(e,t,n,s,o,r,a,c){const d=Math.min(Math.floor(.5*n),t.maxTokens>0?t.maxTokens:Number.POSITIVE_INFINITY),g=I(e),x=[{role:"user",content:[{type:"text",text:`<conversation>
100
+ ${w(g)}
101
+ </conversation>
102
+
103
+ ${Q}`}],timestamp:Date.now()}],f=await A(t,{systemPrompt:v,messages:x},E(t,d,s,o,r,a),c);if(f.stopReason==="error")throw new Error(`Turn prefix summarization failed: ${f.errorMessage||"Unknown error"}`);return f.content.filter(i=>i.type==="text").map(i=>i.text).join(`
104
+ `)}u(ee,"generateTurnPrefixSummary");export{ie as DEFAULT_COMPACTION_SETTINGS,G as calculateContextTokens,me as compact,W as estimateContextTokens,S as estimateTokens,q as findCutPoint,j as findTurnStartIndex,R as generateSummary,ae as getLastAssistantUsage,ue as prepareCompaction,ce as shouldCompact};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Compaction and summarization utilities.
3
+ */
4
+ export * from "./branch-summarization.ts";
5
+ export * from "./compaction.ts";
6
+ export * from "./utils.ts";
@@ -0,0 +1 @@
1
+ export*from"./branch-summarization.js";export*from"./compaction.js";export*from"./utils.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared utilities for compaction and branch summarization.
3
+ */
4
+ import type { AgentMessage } from "@openadapter/koda-agent-core";
5
+ import type { Message } from "@openadapter/koda-ai";
6
+ export interface FileOperations {
7
+ read: Set<string>;
8
+ written: Set<string>;
9
+ edited: Set<string>;
10
+ }
11
+ export declare function createFileOps(): FileOperations;
12
+ /**
13
+ * Extract file operations from tool calls in an assistant message.
14
+ */
15
+ export declare function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void;
16
+ /**
17
+ * Compute final file lists from file operations.
18
+ * Returns readFiles (files only read, not modified) and modifiedFiles.
19
+ */
20
+ export declare function computeFileLists(fileOps: FileOperations): {
21
+ readFiles: string[];
22
+ modifiedFiles: string[];
23
+ };
24
+ /**
25
+ * Format file operations as XML tags for summary.
26
+ */
27
+ export declare function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string;
28
+ /**
29
+ * Serialize LLM messages to text for summarization.
30
+ * This prevents the model from treating it as a conversation to continue.
31
+ * Call convertToLlm() first to handle custom message types.
32
+ *
33
+ * Tool results are truncated to keep the summarization request within
34
+ * reasonable token budgets. Full content is not needed for summarization.
35
+ */
36
+ export declare function serializeConversation(messages: Message[]): string;
37
+ export declare const SUMMARIZATION_SYSTEM_PROMPT = "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.";
@@ -0,0 +1,19 @@
1
+ var d=Object.defineProperty;var r=(e,n)=>d(e,"name",{value:n,configurable:!0});function m(){return{read:new Set,written:new Set,edited:new Set}}r(m,"createFileOps");function y(e,n){if(e.role==="assistant"&&!(!("content"in e)||!Array.isArray(e.content)))for(const t of e.content){if(typeof t!="object"||t===null||!("type"in t)||t.type!=="toolCall"||!("arguments"in t)||!("name"in t))continue;const i=t.arguments;if(!i)continue;const o=typeof i.path=="string"?i.path:void 0;if(o)switch(t.name){case"read":n.read.add(o);break;case"write":n.written.add(o);break;case"edit":n.edited.add(o);break}}}r(y,"extractFileOpsFromMessage");function $(e){const n=new Set([...e.edited,...e.written]),t=[...e.read].filter(o=>!n.has(o)).sort(),i=[...n].sort();return{readFiles:t,modifiedFiles:i}}r($,"computeFileLists");function j(e,n){const t=[];return e.length>0&&t.push(`<read-files>
2
+ ${e.join(`
3
+ `)}
4
+ </read-files>`),n.length>0&&t.push(`<modified-files>
5
+ ${n.join(`
6
+ `)}
7
+ </modified-files>`),t.length===0?"":`
8
+
9
+ ${t.join(`
10
+
11
+ `)}`}r(j,"formatFileOperations");const p=2e3;function h(e,n){if(e.length<=n)return e;const t=e.length-n;return`${e.slice(0,n)}
12
+
13
+ [... ${t} more characters truncated]`}r(h,"truncateForSummary");function S(e){const n=[];for(const t of e)if(t.role==="user"){const i=typeof t.content=="string"?t.content:t.content.filter(o=>o.type==="text").map(o=>o.text).join("");i&&n.push(`[User]: ${i}`)}else if(t.role==="assistant"){const i=[],o=[],a=[];for(const s of t.content)if(s.type==="text")i.push(s.text);else if(s.type==="thinking")o.push(s.thinking);else if(s.type==="toolCall"){const c=s.arguments,u=Object.entries(c).map(([f,l])=>`${f}=${JSON.stringify(l)}`).join(", ");a.push(`${s.name}(${u})`)}o.length>0&&n.push(`[Assistant thinking]: ${o.join(`
14
+ `)}`),i.length>0&&n.push(`[Assistant]: ${i.join(`
15
+ `)}`),a.length>0&&n.push(`[Assistant tool calls]: ${a.join("; ")}`)}else if(t.role==="toolResult"){const i=t.content.filter(o=>o.type==="text").map(o=>o.text).join("");i&&n.push(`[Tool result]: ${h(i,p)}`)}return n.join(`
16
+
17
+ `)}r(S,"serializeConversation");const w=`You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.
18
+
19
+ Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;export{w as SUMMARIZATION_SYSTEM_PROMPT,$ as computeFileLists,m as createFileOps,y as extractFileOpsFromMessage,j as formatFileOperations,S as serializeConversation};
@@ -0,0 +1,2 @@
1
+ import type { ThinkingLevel } from "@openadapter/koda-agent-core";
2
+ export declare const DEFAULT_THINKING_LEVEL: ThinkingLevel;
@@ -0,0 +1 @@
1
+ const E="medium";export{E as DEFAULT_THINKING_LEVEL};
@@ -0,0 +1,14 @@
1
+ export interface ResourceCollision {
2
+ resourceType: "extension" | "skill" | "prompt" | "theme";
3
+ name: string;
4
+ winnerPath: string;
5
+ loserPath: string;
6
+ winnerSource?: string;
7
+ loserSource?: string;
8
+ }
9
+ export interface ResourceDiagnostic {
10
+ type: "warning" | "error" | "collision";
11
+ message: string;
12
+ path?: string;
13
+ collision?: ResourceCollision;
14
+ }
File without changes
@@ -0,0 +1,8 @@
1
+ export interface EventBus {
2
+ emit(channel: string, data: unknown): void;
3
+ on(channel: string, handler: (data: unknown) => void): () => void;
4
+ }
5
+ export interface EventBusController extends EventBus {
6
+ clear(): void;
7
+ }
8
+ export declare function createEventBus(): EventBusController;
@@ -0,0 +1 @@
1
+ var a=Object.defineProperty;var t=(r,e)=>a(r,"name",{value:e,configurable:!0});import{EventEmitter as c}from"node:events";function l(){const r=new c;return{emit:t((e,o)=>{r.emit(e,o)},"emit"),on:t((e,o)=>{const n=t(async i=>{try{await o(i)}catch(s){console.error(`Event handler error (${e}):`,s)}},"safeHandler");return r.on(e,n),()=>r.off(e,n)},"on"),clear:t(()=>{r.removeAllListeners()},"clear")}}t(l,"createEventBus");export{l as createEventBus};
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Shared command execution utilities for extensions and custom tools.
3
+ */
4
+ /**
5
+ * Options for executing shell commands.
6
+ */
7
+ export interface ExecOptions {
8
+ /** AbortSignal to cancel the command */
9
+ signal?: AbortSignal;
10
+ /** Timeout in milliseconds */
11
+ timeout?: number;
12
+ /** Working directory */
13
+ cwd?: string;
14
+ }
15
+ /**
16
+ * Result of executing a shell command.
17
+ */
18
+ export interface ExecResult {
19
+ stdout: string;
20
+ stderr: string;
21
+ code: number;
22
+ killed: boolean;
23
+ }
24
+ /**
25
+ * Execute a shell command and return stdout/stderr/code.
26
+ * Supports timeout and abort signal.
27
+ */
28
+ export declare function execCommand(command: string, args: string[], cwd: string, options?: ExecOptions): Promise<ExecResult>;
@@ -0,0 +1 @@
1
+ var u=Object.defineProperty;var m=(n,o)=>u(n,"name",{value:o,configurable:!0});import{spawn as g}from"node:child_process";import{waitForChildProcess as k}from"../utils/child-process.js";async function h(n,o,f,e){return new Promise(c=>{const t=g(n,o,{cwd:f,shell:!1,stdio:["ignore","pipe","pipe"]});let s="",d="",a=!1,r;const l=m(()=>{a||(a=!0,t.kill("SIGTERM"),setTimeout(()=>{t.killed||t.kill("SIGKILL")},5e3))},"killProcess");e?.signal&&(e.signal.aborted?l():e.signal.addEventListener("abort",l,{once:!0})),e?.timeout&&e.timeout>0&&(r=setTimeout(()=>{l()},e.timeout)),t.stdout?.on("data",i=>{s+=i.toString()}),t.stderr?.on("data",i=>{d+=i.toString()}),k(t).then(i=>{r&&clearTimeout(r),e?.signal&&e.signal.removeEventListener("abort",l),c({stdout:s,stderr:d,code:i??0,killed:a})}).catch(i=>{r&&clearTimeout(r),e?.signal&&e.signal.removeEventListener("abort",l),c({stdout:s,stderr:d,code:1,killed:a})})})}m(h,"execCommand");export{h as execCommand};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ANSI escape code to HTML converter.
3
+ *
4
+ * Converts terminal ANSI color/style codes to HTML with inline styles.
5
+ * Supports:
6
+ * - Standard foreground colors (30-37) and bright variants (90-97)
7
+ * - Standard background colors (40-47) and bright variants (100-107)
8
+ * - 256-color palette (38;5;N and 48;5;N)
9
+ * - RGB true color (38;2;R;G;B and 48;2;R;G;B)
10
+ * - Text styles: bold (1), dim (2), italic (3), underline (4)
11
+ * - Reset (0)
12
+ */
13
+ /**
14
+ * Convert ANSI-escaped text to HTML with inline styles.
15
+ */
16
+ export declare function ansiToHtml(text: string): string;
17
+ /**
18
+ * Convert array of ANSI-escaped lines to HTML.
19
+ * Each line is wrapped in a div element.
20
+ */
21
+ export declare function ansiLinesToHtml(lines: string[]): string;
@@ -0,0 +1 @@
1
+ var p=Object.defineProperty;var o=(n,e)=>p(n,"name",{value:e,configurable:!0});const g=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"];function a(n){if(n<16)return g[n];if(n<232){const i=n-16,t=Math.floor(i/36),l=Math.floor(i%36/6),c=i%6,s=o(u=>u===0?0:55+u*40,"toComponent"),r=o(u=>s(u).toString(16).padStart(2,"0"),"toHex");return`#${r(t)}${r(l)}${r(c)}`}const f=(8+(n-232)*10).toString(16).padStart(2,"0");return`#${f}${f}${f}`}o(a,"color256ToHex");function b(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}o(b,"escapeHtml");function $(){return{fg:null,bg:null,bold:!1,dim:!1,italic:!1,underline:!1}}o($,"createEmptyStyle");function S(n){const e=[];return n.fg&&e.push(`color:${n.fg}`),n.bg&&e.push(`background-color:${n.bg}`),n.bold&&e.push("font-weight:bold"),n.dim&&e.push("opacity:0.6"),n.italic&&e.push("font-style:italic"),n.underline&&e.push("text-decoration:underline"),e.join(";")}o(S,"styleToInlineCSS");function x(n){return n.fg!==null||n.bg!==null||n.bold||n.dim||n.italic||n.underline}o(x,"hasStyle");function I(n,e){let f=0;for(;f<n.length;){const i=n[f];if(i===0)e.fg=null,e.bg=null,e.bold=!1,e.dim=!1,e.italic=!1,e.underline=!1;else if(i===1)e.bold=!0;else if(i===2)e.dim=!0;else if(i===3)e.italic=!0;else if(i===4)e.underline=!0;else if(i===22)e.bold=!1,e.dim=!1;else if(i===23)e.italic=!1;else if(i===24)e.underline=!1;else if(i>=30&&i<=37)e.fg=g[i-30];else if(i===38){if(n[f+1]===5&&n.length>f+2)e.fg=a(n[f+2]),f+=2;else if(n[f+1]===2&&n.length>f+4){const t=n[f+2],l=n[f+3],c=n[f+4];e.fg=`rgb(${t},${l},${c})`,f+=4}}else if(i===39)e.fg=null;else if(i>=40&&i<=47)e.bg=g[i-40];else if(i===48){if(n[f+1]===5&&n.length>f+2)e.bg=a(n[f+2]),f+=2;else if(n[f+1]===2&&n.length>f+4){const t=n[f+2],l=n[f+3],c=n[f+4];e.bg=`rgb(${t},${l},${c})`,f+=4}}else i===49?e.bg=null:i>=90&&i<=97?e.fg=g[i-90+8]:i>=100&&i<=107&&(e.bg=g[i-100+8]);f++}}o(I,"applySgrCode");const d=/\x1b\[([\d;]*)m/g;function H(n){const e=$();let f="",i=0,t=!1;d.lastIndex=0;let l=d.exec(n);for(;l!==null;){const s=n.slice(i,l.index);s&&(f+=b(s));const r=l[1],u=r?r.split(";").map(h=>parseInt(h,10)||0):[0];t&&(f+="</span>",t=!1),I(u,e),x(e)&&(f+=`<span style="${S(e)}">`,t=!0),i=l.index+l[0].length,l=d.exec(n)}const c=n.slice(i);return c&&(f+=b(c)),t&&(f+="</span>"),f}o(H,"ansiToHtml");function C(n){return n.map(e=>`<div class="ansi-line">${H(e)||"&nbsp;"}</div>`).join("")}o(C,"ansiLinesToHtml");export{C as ansiLinesToHtml,H as ansiToHtml};
@@ -0,0 +1,36 @@
1
+ import type { AgentState } from "@openadapter/koda-agent-core";
2
+ import { SessionManager } from "../session-manager.ts";
3
+ /**
4
+ * Interface for rendering custom tools to HTML.
5
+ * Used by agent-session to pre-render extension tool output.
6
+ */
7
+ export interface ToolHtmlRenderer {
8
+ /** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */
9
+ renderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;
10
+ /** Render a tool result to HTML. Returns collapsed/expanded or undefined if tool has no custom renderer. */
11
+ renderResult(toolCallId: string, toolName: string, result: Array<{
12
+ type: string;
13
+ text?: string;
14
+ data?: string;
15
+ mimeType?: string;
16
+ }>, details: unknown, isError: boolean): {
17
+ collapsed?: string;
18
+ expanded?: string;
19
+ } | undefined;
20
+ }
21
+ export interface ExportOptions {
22
+ outputPath?: string;
23
+ themeName?: string;
24
+ /** Optional tool renderer for custom tools */
25
+ toolRenderer?: ToolHtmlRenderer;
26
+ }
27
+ /**
28
+ * Export session to HTML using SessionManager and AgentState.
29
+ * Used by TUI's /export command.
30
+ */
31
+ export declare function exportSessionToHtml(sm: SessionManager, state?: AgentState, options?: ExportOptions | string): Promise<string>;
32
+ /**
33
+ * Export session file to HTML (standalone, without AgentState).
34
+ * Used by CLI for exporting arbitrary session files.
35
+ */
36
+ export declare function exportFromFile(inputPath: string, options?: ExportOptions | string): Promise<string>;
@@ -0,0 +1,2 @@
1
+ var H=Object.defineProperty;var c=(n,e)=>H(n,"name",{value:e,configurable:!0});import{existsSync as h,readFileSync as u,writeFileSync as B}from"fs";import{basename as E,join as m}from"path";import{APP_NAME as b,getExportTemplateDir as F}from"../../config.js";import{getResolvedThemeColors as x,getThemeExportColors as y}from"../../modes/interactive/theme/theme.js";import{normalizePath as I,resolvePath as v}from"../../utils/paths.js";import{SessionManager as D}from"../session-manager.js";function $(n){const e=n.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(e)return{r:Number.parseInt(e[1],16),g:Number.parseInt(e[2],16),b:Number.parseInt(e[3],16)};const t=n.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);if(t)return{r:Number.parseInt(t[1],10),g:Number.parseInt(t[2],10),b:Number.parseInt(t[3],10)}}c($,"parseColor");function L(n,e,t){const r=c(o=>{const s=o/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4},"toLinear");return .2126*r(n)+.7152*r(e)+.0722*r(t)}c(L,"getLuminance");function d(n,e){const t=$(n);if(!t)return n;const r=c(o=>Math.min(255,Math.max(0,Math.round(o*e))),"adjust");return`rgb(${r(t.r)}, ${r(t.g)}, ${r(t.b)})`}c(d,"adjustBrightness");function M(n){const e=$(n);return e?L(e.r,e.g,e.b)>.5?{pageBg:d(n,.96),cardBg:n,infoBg:`rgb(${Math.min(255,e.r+10)}, ${Math.min(255,e.g+5)}, ${Math.max(0,e.b-20)})`}:{pageBg:d(n,.7),cardBg:d(n,.85),infoBg:`rgb(${Math.min(255,e.r+20)}, ${Math.min(255,e.g+15)}, ${e.b})`}:{pageBg:"rgb(24, 24, 30)",cardBg:"rgb(30, 30, 36)",infoBg:"rgb(60, 55, 40)"}}c(M,"deriveExportColors");function R(n){const e=x(n),t=[];for(const[a,i]of Object.entries(e))t.push(`--${a}: ${i};`);const r=y(n),o=e.userMessageBg||"#343541",s=M(o);return t.push(`--exportPageBg: ${r.pageBg??s.pageBg};`),t.push(`--exportCardBg: ${r.cardBg??s.cardBg};`),t.push(`--exportInfoBg: ${r.infoBg??s.infoBg};`),t.join(`
2
+ `)}c(R,"generateThemeVars");function S(n,e){const t=F(),r=u(m(t,"template.html"),"utf-8"),o=u(m(t,"template.css"),"utf-8"),s=u(m(t,"template.js"),"utf-8"),a=u(m(t,"vendor","marked.min.js"),"utf-8"),i=u(m(t,"vendor","highlight.min.js"),"utf-8"),p=R(e),g=x(e),l=y(e),f=M(g.userMessageBg||"#343541"),T=l.pageBg??f.pageBg,C=l.cardBg??f.cardBg,N=l.infoBg??f.infoBg,A=Buffer.from(JSON.stringify(n)).toString("base64"),j=o.replace("{{THEME_VARS}}",p).replace("{{BODY_BG}}",T).replace("{{CONTAINER_BG}}",C).replace("{{INFO_BG}}",N);return r.replace("{{CSS}}",j).replace("{{JS}}",s).replace("{{SESSION_DATA}}",A).replace("{{MARKED_JS}}",a).replace("{{HIGHLIGHT_JS}}",i)}c(S,"generateHtml");const P=new Set(["bash","read","write","edit","ls"]);function _(n,e){const t={};for(const r of n){if(r.type!=="message")continue;const o=r.message;if(o.role==="assistant"&&Array.isArray(o.content)){for(const s of o.content)if(s.type==="toolCall"&&!P.has(s.name)){const a=e.renderCall(s.id,s.name,s.arguments);a&&(t[s.id]={callHtml:a})}}if(o.role==="toolResult"&&o.toolCallId){const s=o.toolName||"",a=t[o.toolCallId];if(a||!P.has(s)){const i=e.renderResult(o.toolCallId,s,o.content,o.details,o.isError||!1);i&&(t[o.toolCallId]={...a,resultHtmlCollapsed:i.collapsed,resultHtmlExpanded:i.expanded})}}}return t}c(_,"preRenderCustomTools");async function K(n,e,t){const r=typeof t=="string"?{outputPath:t}:t||{},o=n.getSessionFile();if(!o)throw new Error("Cannot export in-memory session to HTML");if(!h(o))throw new Error("Nothing to export yet - start a conversation first");const s=n.getEntries();let a;r.toolRenderer&&(a=_(s,r.toolRenderer),Object.keys(a).length===0&&(a=void 0));const i={header:n.getHeader(),entries:s,leafId:n.getLeafId(),systemPrompt:e?.systemPrompt,tools:e?.tools?.map(l=>({name:l.name,description:l.description,parameters:l.parameters})),renderedTools:a},p=S(i,r.themeName);let g=r.outputPath?I(r.outputPath):void 0;if(!g){const l=E(o,".jsonl");g=`${b}-session-${l}.html`}return B(g,p,"utf8"),g}c(K,"exportSessionToHtml");async function Y(n,e){const t=typeof e=="string"?{outputPath:e}:e||{},r=v(n);if(!h(r))throw new Error(`File not found: ${r}`);const o=D.open(r),s={header:o.getHeader(),entries:o.getEntries(),leafId:o.getLeafId(),systemPrompt:void 0,tools:void 0},a=S(s,t.themeName);let i=t.outputPath?I(t.outputPath):void 0;if(!i){const p=E(r,".jsonl");i=`${b}-session-${p}.html`}return B(i,a,"utf8"),i}c(Y,"exportFromFile");export{Y as exportFromFile,K as exportSessionToHtml};