evolcore 0.0.5 → 0.0.6

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 (322) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +4 -12
  3. package/dist/agents/baseagent.js +39 -0
  4. package/dist/agents/claude-runner.js +10 -2
  5. package/dist/agents/codex-runner.js +37 -8
  6. package/dist/agents/ecagent-runner.js +1159 -0
  7. package/dist/agents/gemini-runner.js +4 -1
  8. package/dist/agents/runner-types.js +20 -4
  9. package/dist/aun/msg/history.js +32 -9
  10. package/dist/aun/outbox.js +4 -9
  11. package/dist/channels/aun.js +32 -6
  12. package/dist/channels/daemon.js +7 -4
  13. package/dist/channels/dingtalk.js +3 -5
  14. package/dist/channels/feishu.js +16 -108
  15. package/dist/channels/wechat.js +4 -4
  16. package/dist/channels/wecom.js +4 -6
  17. package/dist/cli/agent-command.js +1 -1
  18. package/dist/cli/agent.js +42 -11
  19. package/dist/cli/aun-commands.js +50 -3
  20. package/dist/cli/daemon-commands.js +81 -6
  21. package/dist/cli/data-command.js +132 -0
  22. package/dist/cli/index.js +11 -3
  23. package/dist/cli/init.js +76 -17
  24. package/dist/cli/net-check.js +9 -20
  25. package/dist/cli/restart-monitor.js +11 -2
  26. package/dist/cli/trigger-command.js +1 -1
  27. package/dist/cli/watch-msg.js +12 -25
  28. package/dist/config/builtin-roles.js +3 -1
  29. package/dist/config/config-field-policy.js +1 -1
  30. package/dist/config/gateway-config.js +21 -4
  31. package/dist/config/resolved-config-op.js +10 -0
  32. package/dist/core/command/command-handler.js +2 -2
  33. package/dist/core/command/menu-handler.js +11 -9
  34. package/dist/core/command/role-menu.js +11 -0
  35. package/dist/core/command/slash-handler.js +18 -14
  36. package/dist/core/data-migration.js +1434 -0
  37. package/dist/core/handoff/store.js +14 -4
  38. package/dist/core/inference/text-inference.js +42 -1
  39. package/dist/core/message/pending-hints.js +1 -1
  40. package/dist/core/message/response-engine.js +406 -167
  41. package/dist/core/message/retry-scheduler.js +71 -0
  42. package/dist/core/model/model-catalog.js +7 -2
  43. package/dist/core/model/model-fallback.js +81 -0
  44. package/dist/core/protected-paths.js +41 -8
  45. package/dist/core/session/adapters/ecagent-session-file-adapter.js +112 -0
  46. package/dist/core/session/session-fs-store.js +283 -59
  47. package/dist/core/session/session-manager.js +19 -21
  48. package/dist/core/session/session-title.js +1 -0
  49. package/dist/core/session/session-turn-coordinator.js +8 -1
  50. package/dist/core/system-channels.js +1 -0
  51. package/dist/index.js +10 -9
  52. package/dist/paths.js +35 -27
  53. package/dist/trigger/feedback.js +16 -0
  54. package/dist/trigger/legacy-session-history.js +19 -0
  55. package/dist/trigger/manager.js +12 -1
  56. package/dist/trigger/parser.js +4 -2
  57. package/dist/trigger/scheduler.js +185 -15
  58. package/dist/trigger/session-lock.js +62 -0
  59. package/dist/trigger/state.js +64 -0
  60. package/dist/trigger/validation.js +32 -2
  61. package/dist/utils/aid-bind.js +1 -1
  62. package/dist/utils/error-utils.js +9 -0
  63. package/dist/utils/welcome.js +2 -3
  64. package/ecagent/LICENSE +21 -0
  65. package/ecagent/NOTICE +11 -0
  66. package/ecagent/README.md +61 -0
  67. package/ecagent/dist/agent-loop.d.ts +24 -0
  68. package/ecagent/dist/agent-loop.d.ts.map +1 -0
  69. package/ecagent/dist/agent-loop.js +547 -0
  70. package/ecagent/dist/agent-loop.js.map +1 -0
  71. package/ecagent/dist/agent.d.ts +127 -0
  72. package/ecagent/dist/agent.d.ts.map +1 -0
  73. package/ecagent/dist/agent.js +386 -0
  74. package/ecagent/dist/agent.js.map +1 -0
  75. package/ecagent/dist/harness/agent-harness.d.ts +95 -0
  76. package/ecagent/dist/harness/agent-harness.d.ts.map +1 -0
  77. package/ecagent/dist/harness/agent-harness.js +926 -0
  78. package/ecagent/dist/harness/agent-harness.js.map +1 -0
  79. package/ecagent/dist/harness/compaction/branch-summarization.d.ts +51 -0
  80. package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
  81. package/ecagent/dist/harness/compaction/branch-summarization.js +174 -0
  82. package/ecagent/dist/harness/compaction/branch-summarization.js.map +1 -0
  83. package/ecagent/dist/harness/compaction/compaction.d.ts +95 -0
  84. package/ecagent/dist/harness/compaction/compaction.d.ts.map +1 -0
  85. package/ecagent/dist/harness/compaction/compaction.js +528 -0
  86. package/ecagent/dist/harness/compaction/compaction.js.map +1 -0
  87. package/ecagent/dist/harness/compaction/utils.d.ts +25 -0
  88. package/ecagent/dist/harness/compaction/utils.d.ts.map +1 -0
  89. package/ecagent/dist/harness/compaction/utils.js +131 -0
  90. package/ecagent/dist/harness/compaction/utils.js.map +1 -0
  91. package/ecagent/dist/harness/env/nodejs.d.ts +51 -0
  92. package/ecagent/dist/harness/env/nodejs.d.ts.map +1 -0
  93. package/ecagent/dist/harness/env/nodejs.js +513 -0
  94. package/ecagent/dist/harness/env/nodejs.js.map +1 -0
  95. package/ecagent/dist/harness/messages.d.ts +51 -0
  96. package/ecagent/dist/harness/messages.d.ts.map +1 -0
  97. package/ecagent/dist/harness/messages.js +102 -0
  98. package/ecagent/dist/harness/messages.js.map +1 -0
  99. package/ecagent/dist/harness/prompt-templates.d.ts +48 -0
  100. package/ecagent/dist/harness/prompt-templates.d.ts.map +1 -0
  101. package/ecagent/dist/harness/prompt-templates.js +230 -0
  102. package/ecagent/dist/harness/prompt-templates.js.map +1 -0
  103. package/ecagent/dist/harness/session/jsonl-repo.d.ts +26 -0
  104. package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +1 -0
  105. package/ecagent/dist/harness/session/jsonl-repo.js +100 -0
  106. package/ecagent/dist/harness/session/jsonl-repo.js.map +1 -0
  107. package/ecagent/dist/harness/session/jsonl-storage.d.ts +34 -0
  108. package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +1 -0
  109. package/ecagent/dist/harness/session/jsonl-storage.js +234 -0
  110. package/ecagent/dist/harness/session/jsonl-storage.js.map +1 -0
  111. package/ecagent/dist/harness/session/memory-repo.d.ts +18 -0
  112. package/ecagent/dist/harness/session/memory-repo.d.ts.map +1 -0
  113. package/ecagent/dist/harness/session/memory-repo.js +44 -0
  114. package/ecagent/dist/harness/session/memory-repo.js.map +1 -0
  115. package/ecagent/dist/harness/session/memory-storage.d.ts +25 -0
  116. package/ecagent/dist/harness/session/memory-storage.d.ts.map +1 -0
  117. package/ecagent/dist/harness/session/memory-storage.js +111 -0
  118. package/ecagent/dist/harness/session/memory-storage.js.map +1 -0
  119. package/ecagent/dist/harness/session/repo-utils.d.ts +11 -0
  120. package/ecagent/dist/harness/session/repo-utils.d.ts.map +1 -0
  121. package/ecagent/dist/harness/session/repo-utils.js +39 -0
  122. package/ecagent/dist/harness/session/repo-utils.js.map +1 -0
  123. package/ecagent/dist/harness/session/session.d.ts +47 -0
  124. package/ecagent/dist/harness/session/session.d.ts.map +1 -0
  125. package/ecagent/dist/harness/session/session.js +245 -0
  126. package/ecagent/dist/harness/session/session.js.map +1 -0
  127. package/ecagent/dist/harness/session/uuid.d.ts +2 -0
  128. package/ecagent/dist/harness/session/uuid.d.ts.map +1 -0
  129. package/ecagent/dist/harness/session/uuid.js +50 -0
  130. package/ecagent/dist/harness/session/uuid.js.map +1 -0
  131. package/ecagent/dist/harness/skills.d.ts +44 -0
  132. package/ecagent/dist/harness/skills.d.ts.map +1 -0
  133. package/ecagent/dist/harness/skills.js +311 -0
  134. package/ecagent/dist/harness/skills.js.map +1 -0
  135. package/ecagent/dist/harness/system-prompt.d.ts +3 -0
  136. package/ecagent/dist/harness/system-prompt.d.ts.map +1 -0
  137. package/ecagent/dist/harness/system-prompt.js +30 -0
  138. package/ecagent/dist/harness/system-prompt.js.map +1 -0
  139. package/ecagent/dist/harness/types.d.ts +619 -0
  140. package/ecagent/dist/harness/types.d.ts.map +1 -0
  141. package/ecagent/dist/harness/types.js +81 -0
  142. package/ecagent/dist/harness/types.js.map +1 -0
  143. package/ecagent/dist/harness/utils/shell-output.d.ts +14 -0
  144. package/ecagent/dist/harness/utils/shell-output.d.ts.map +1 -0
  145. package/ecagent/dist/harness/utils/shell-output.js +126 -0
  146. package/ecagent/dist/harness/utils/shell-output.js.map +1 -0
  147. package/ecagent/dist/harness/utils/truncate.d.ts +70 -0
  148. package/ecagent/dist/harness/utils/truncate.d.ts.map +1 -0
  149. package/ecagent/dist/harness/utils/truncate.js +290 -0
  150. package/ecagent/dist/harness/utils/truncate.js.map +1 -0
  151. package/ecagent/dist/index.d.ts +22 -0
  152. package/ecagent/dist/index.d.ts.map +1 -0
  153. package/ecagent/dist/index.js +27 -0
  154. package/ecagent/dist/index.js.map +1 -0
  155. package/ecagent/dist/node.d.ts +3 -0
  156. package/ecagent/dist/node.d.ts.map +1 -0
  157. package/ecagent/dist/node.js +3 -0
  158. package/ecagent/dist/node.js.map +1 -0
  159. package/ecagent/dist/proxy.d.ts +69 -0
  160. package/ecagent/dist/proxy.d.ts.map +1 -0
  161. package/ecagent/dist/proxy.js +278 -0
  162. package/ecagent/dist/proxy.js.map +1 -0
  163. package/ecagent/dist/runtime/api/lazy.d.ts +15 -0
  164. package/ecagent/dist/runtime/api/lazy.d.ts.map +1 -0
  165. package/ecagent/dist/runtime/api/lazy.js +59 -0
  166. package/ecagent/dist/runtime/api/lazy.js.map +1 -0
  167. package/ecagent/dist/runtime/api/pi-messages.d.ts +97 -0
  168. package/ecagent/dist/runtime/api/pi-messages.d.ts.map +1 -0
  169. package/ecagent/dist/runtime/api/pi-messages.js +307 -0
  170. package/ecagent/dist/runtime/api/pi-messages.js.map +1 -0
  171. package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts +3 -0
  172. package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +1 -0
  173. package/ecagent/dist/runtime/api/pi-messages.lazy.js +3 -0
  174. package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +1 -0
  175. package/ecagent/dist/runtime/auth/context.d.ts +7 -0
  176. package/ecagent/dist/runtime/auth/context.d.ts.map +1 -0
  177. package/ecagent/dist/runtime/auth/context.js +42 -0
  178. package/ecagent/dist/runtime/auth/context.js.map +1 -0
  179. package/ecagent/dist/runtime/auth/credential-store.d.ts +16 -0
  180. package/ecagent/dist/runtime/auth/credential-store.d.ts.map +1 -0
  181. package/ecagent/dist/runtime/auth/credential-store.js +39 -0
  182. package/ecagent/dist/runtime/auth/credential-store.js.map +1 -0
  183. package/ecagent/dist/runtime/auth/helpers.d.ts +20 -0
  184. package/ecagent/dist/runtime/auth/helpers.d.ts.map +1 -0
  185. package/ecagent/dist/runtime/auth/helpers.js +46 -0
  186. package/ecagent/dist/runtime/auth/helpers.js.map +1 -0
  187. package/ecagent/dist/runtime/auth/resolve.d.ts +26 -0
  188. package/ecagent/dist/runtime/auth/resolve.d.ts.map +1 -0
  189. package/ecagent/dist/runtime/auth/resolve.js +100 -0
  190. package/ecagent/dist/runtime/auth/resolve.js.map +1 -0
  191. package/ecagent/dist/runtime/auth/types.d.ts +180 -0
  192. package/ecagent/dist/runtime/auth/types.d.ts.map +1 -0
  193. package/ecagent/dist/runtime/auth/types.js +2 -0
  194. package/ecagent/dist/runtime/auth/types.js.map +1 -0
  195. package/ecagent/dist/runtime/compat.d.ts +28 -0
  196. package/ecagent/dist/runtime/compat.d.ts.map +1 -0
  197. package/ecagent/dist/runtime/compat.js +86 -0
  198. package/ecagent/dist/runtime/compat.js.map +1 -0
  199. package/ecagent/dist/runtime/index.d.ts +20 -0
  200. package/ecagent/dist/runtime/index.d.ts.map +1 -0
  201. package/ecagent/dist/runtime/index.js +17 -0
  202. package/ecagent/dist/runtime/index.js.map +1 -0
  203. package/ecagent/dist/runtime/models.d.ts +142 -0
  204. package/ecagent/dist/runtime/models.d.ts.map +1 -0
  205. package/ecagent/dist/runtime/models.js +245 -0
  206. package/ecagent/dist/runtime/models.js.map +1 -0
  207. package/ecagent/dist/runtime/oauth.d.ts +2 -0
  208. package/ecagent/dist/runtime/oauth.d.ts.map +1 -0
  209. package/ecagent/dist/runtime/oauth.js +2 -0
  210. package/ecagent/dist/runtime/oauth.js.map +1 -0
  211. package/ecagent/dist/runtime/providers/faux.d.ts +97 -0
  212. package/ecagent/dist/runtime/providers/faux.d.ts.map +1 -0
  213. package/ecagent/dist/runtime/providers/faux.js +395 -0
  214. package/ecagent/dist/runtime/providers/faux.js.map +1 -0
  215. package/ecagent/dist/runtime/types.d.ts +607 -0
  216. package/ecagent/dist/runtime/types.d.ts.map +1 -0
  217. package/ecagent/dist/runtime/types.js +2 -0
  218. package/ecagent/dist/runtime/types.js.map +1 -0
  219. package/ecagent/dist/runtime/utils/diagnostics.d.ts +19 -0
  220. package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +1 -0
  221. package/ecagent/dist/runtime/utils/diagnostics.js +25 -0
  222. package/ecagent/dist/runtime/utils/diagnostics.js.map +1 -0
  223. package/ecagent/dist/runtime/utils/event-stream.d.ts +21 -0
  224. package/ecagent/dist/runtime/utils/event-stream.d.ts.map +1 -0
  225. package/ecagent/dist/runtime/utils/event-stream.js +77 -0
  226. package/ecagent/dist/runtime/utils/event-stream.js.map +1 -0
  227. package/ecagent/dist/runtime/utils/headers.d.ts +4 -0
  228. package/ecagent/dist/runtime/utils/headers.d.ts.map +1 -0
  229. package/ecagent/dist/runtime/utils/headers.js +18 -0
  230. package/ecagent/dist/runtime/utils/headers.js.map +1 -0
  231. package/ecagent/dist/runtime/utils/json-parse.d.ts +16 -0
  232. package/ecagent/dist/runtime/utils/json-parse.d.ts.map +1 -0
  233. package/ecagent/dist/runtime/utils/json-parse.js +113 -0
  234. package/ecagent/dist/runtime/utils/json-parse.js.map +1 -0
  235. package/ecagent/dist/runtime/utils/oauth/types.d.ts +64 -0
  236. package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +1 -0
  237. package/ecagent/dist/runtime/utils/oauth/types.js +2 -0
  238. package/ecagent/dist/runtime/utils/oauth/types.js.map +1 -0
  239. package/ecagent/dist/runtime/utils/overflow.d.ts +58 -0
  240. package/ecagent/dist/runtime/utils/overflow.d.ts.map +1 -0
  241. package/ecagent/dist/runtime/utils/overflow.js +158 -0
  242. package/ecagent/dist/runtime/utils/overflow.js.map +1 -0
  243. package/ecagent/dist/runtime/utils/provider-env.d.ts +7 -0
  244. package/ecagent/dist/runtime/utils/provider-env.d.ts.map +1 -0
  245. package/ecagent/dist/runtime/utils/provider-env.js +44 -0
  246. package/ecagent/dist/runtime/utils/provider-env.js.map +1 -0
  247. package/ecagent/dist/runtime/utils/retry.d.ts +12 -0
  248. package/ecagent/dist/runtime/utils/retry.d.ts.map +1 -0
  249. package/ecagent/dist/runtime/utils/retry.js +90 -0
  250. package/ecagent/dist/runtime/utils/retry.js.map +1 -0
  251. package/ecagent/dist/runtime/utils/typebox-helpers.d.ts +17 -0
  252. package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +1 -0
  253. package/ecagent/dist/runtime/utils/typebox-helpers.js +21 -0
  254. package/ecagent/dist/runtime/utils/typebox-helpers.js.map +1 -0
  255. package/ecagent/dist/runtime/utils/validation.d.ts +18 -0
  256. package/ecagent/dist/runtime/utils/validation.d.ts.map +1 -0
  257. package/ecagent/dist/runtime/utils/validation.js +269 -0
  258. package/ecagent/dist/runtime/utils/validation.js.map +1 -0
  259. package/ecagent/dist/types.d.ts +401 -0
  260. package/ecagent/dist/types.d.ts.map +1 -0
  261. package/ecagent/dist/types.js +2 -0
  262. package/ecagent/dist/types.js.map +1 -0
  263. package/ecagent/package.json +93 -0
  264. package/ecagent/src/agent-loop.ts +792 -0
  265. package/ecagent/src/agent.ts +575 -0
  266. package/ecagent/src/harness/agent-harness.ts +1029 -0
  267. package/ecagent/src/harness/compaction/branch-summarization.ts +261 -0
  268. package/ecagent/src/harness/compaction/compaction.ts +753 -0
  269. package/ecagent/src/harness/compaction/utils.ts +144 -0
  270. package/ecagent/src/harness/env/nodejs.ts +569 -0
  271. package/ecagent/src/harness/messages.ts +164 -0
  272. package/ecagent/src/harness/prompt-templates.ts +267 -0
  273. package/ecagent/src/harness/session/jsonl-repo.ts +179 -0
  274. package/ecagent/src/harness/session/jsonl-storage.ts +314 -0
  275. package/ecagent/src/harness/session/memory-repo.ts +50 -0
  276. package/ecagent/src/harness/session/memory-storage.ts +133 -0
  277. package/ecagent/src/harness/session/repo-utils.ts +51 -0
  278. package/ecagent/src/harness/session/session.ts +338 -0
  279. package/ecagent/src/harness/session/uuid.ts +54 -0
  280. package/ecagent/src/harness/skills.ts +375 -0
  281. package/ecagent/src/harness/system-prompt.ts +34 -0
  282. package/ecagent/src/harness/types.ts +838 -0
  283. package/ecagent/src/harness/utils/shell-output.ts +135 -0
  284. package/ecagent/src/harness/utils/truncate.ts +344 -0
  285. package/ecagent/src/index.ts +46 -0
  286. package/ecagent/src/node.ts +2 -0
  287. package/ecagent/src/proxy.ts +367 -0
  288. package/ecagent/src/runtime/api/lazy.ts +70 -0
  289. package/ecagent/src/runtime/api/pi-messages.lazy.ts +4 -0
  290. package/ecagent/src/runtime/api/pi-messages.ts +436 -0
  291. package/ecagent/src/runtime/auth/context.ts +45 -0
  292. package/ecagent/src/runtime/auth/credential-store.ts +47 -0
  293. package/ecagent/src/runtime/auth/helpers.ts +46 -0
  294. package/ecagent/src/runtime/auth/resolve.ts +141 -0
  295. package/ecagent/src/runtime/auth/types.ts +182 -0
  296. package/ecagent/src/runtime/compat.ts +158 -0
  297. package/ecagent/src/runtime/index.ts +31 -0
  298. package/ecagent/src/runtime/models.ts +452 -0
  299. package/ecagent/src/runtime/oauth.ts +1 -0
  300. package/ecagent/src/runtime/providers/faux.ts +538 -0
  301. package/ecagent/src/runtime/types.ts +718 -0
  302. package/ecagent/src/runtime/utils/diagnostics.ts +45 -0
  303. package/ecagent/src/runtime/utils/event-stream.ts +88 -0
  304. package/ecagent/src/runtime/utils/headers.ts +18 -0
  305. package/ecagent/src/runtime/utils/json-parse.ts +124 -0
  306. package/ecagent/src/runtime/utils/oauth/types.ts +79 -0
  307. package/ecagent/src/runtime/utils/overflow.ts +165 -0
  308. package/ecagent/src/runtime/utils/provider-env.ts +52 -0
  309. package/ecagent/src/runtime/utils/retry.ts +101 -0
  310. package/ecagent/src/runtime/utils/typebox-helpers.ts +24 -0
  311. package/ecagent/src/runtime/utils/validation.ts +310 -0
  312. package/ecagent/src/types.ts +430 -0
  313. package/ecagent/tsconfig.build.json +32 -0
  314. package/kits/schemas/_meta.json +7 -4
  315. package/kits/schemas/agent-config.schema.10.json +370 -0
  316. package/kits/schemas/defaults.schema.4.json +93 -0
  317. package/kits/schemas/relation-config.schema.8.json +69 -0
  318. package/kits/templates/roles/admin.json +1 -1
  319. package/package.json +22 -6
  320. package/skills/eclink/SKILL.md +70 -0
  321. package/skills/eclink/agents/openai.yaml +4 -0
  322. package/assets/.env.template +0 -4
@@ -0,0 +1,338 @@
1
+ import type { ImageContent, TextContent } from "ecagent/runtime";
2
+ import type { AgentMessage } from "../../types.ts";
3
+ import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from "../messages.ts";
4
+ import type {
5
+ ActiveToolsChangeEntry,
6
+ BranchSummaryEntry,
7
+ CompactionEntry,
8
+ CustomEntry,
9
+ CustomMessageEntry,
10
+ LabelEntry,
11
+ MessageEntry,
12
+ ModelChangeEntry,
13
+ SessionContext,
14
+ SessionInfoEntry,
15
+ SessionMetadata,
16
+ SessionStorage,
17
+ SessionTreeEntry,
18
+ ThinkingLevelChangeEntry,
19
+ } from "../types.ts";
20
+ import { SessionError } from "../types.ts";
21
+
22
+ export type ContextEntryTransform = (entries: readonly SessionTreeEntry[]) => readonly SessionTreeEntry[];
23
+
24
+ export type CustomEntryContextMessageProjector = (
25
+ entry: CustomEntry,
26
+ index: number,
27
+ entries: readonly SessionTreeEntry[],
28
+ ) => readonly AgentMessage[] | undefined;
29
+
30
+ export interface SessionContextBuildOptions {
31
+ /** Additional entry transforms applied after the default compaction transform. */
32
+ entryTransforms?: readonly ContextEntryTransform[];
33
+ /** Optional custom-entry projectors. Custom entries are omitted from model context by default. */
34
+ entryProjectors?: Readonly<Record<string, CustomEntryContextMessageProjector>>;
35
+ }
36
+
37
+ function deriveSessionContextState(pathEntries: readonly SessionTreeEntry[]): Omit<SessionContext, "messages"> {
38
+ let thinkingLevel = "off";
39
+ let model: { provider: string; modelId: string } | null = null;
40
+ let activeToolNames: string[] | null = null;
41
+
42
+ for (const entry of pathEntries) {
43
+ if (entry.type === "thinking_level_change") {
44
+ thinkingLevel = entry.thinkingLevel;
45
+ } else if (entry.type === "model_change") {
46
+ model = { provider: entry.provider, modelId: entry.modelId };
47
+ } else if (entry.type === "message" && entry.message.role === "assistant") {
48
+ model = { provider: entry.message.provider, modelId: entry.message.model };
49
+ } else if (entry.type === "active_tools_change") {
50
+ activeToolNames = [...entry.activeToolNames];
51
+ }
52
+ }
53
+
54
+ return { thinkingLevel, model, activeToolNames };
55
+ }
56
+
57
+ export function defaultContextEntryTransform(pathEntries: readonly SessionTreeEntry[]): SessionTreeEntry[] {
58
+ let compaction: CompactionEntry | null = null;
59
+ for (const entry of pathEntries) {
60
+ if (entry.type === "compaction") {
61
+ compaction = entry;
62
+ }
63
+ }
64
+ if (!compaction) {
65
+ return [...pathEntries];
66
+ }
67
+
68
+ const entries: SessionTreeEntry[] = [compaction];
69
+ const compactionIdx = pathEntries.findIndex((entry) => entry.type === "compaction" && entry.id === compaction.id);
70
+ let foundFirstKept = false;
71
+ for (let i = 0; i < compactionIdx; i++) {
72
+ const entry = pathEntries[i]!;
73
+ if (entry.id === compaction.firstKeptEntryId) foundFirstKept = true;
74
+ if (foundFirstKept) entries.push(entry);
75
+ }
76
+ for (let i = compactionIdx + 1; i < pathEntries.length; i++) {
77
+ entries.push(pathEntries[i]!);
78
+ }
79
+ return entries;
80
+ }
81
+
82
+ export function buildContextEntries(
83
+ pathEntries: readonly SessionTreeEntry[],
84
+ options: SessionContextBuildOptions = {},
85
+ ): SessionTreeEntry[] {
86
+ let entries = defaultContextEntryTransform(pathEntries);
87
+ for (const transform of options.entryTransforms ?? []) {
88
+ entries = [...transform(entries)];
89
+ }
90
+ return entries;
91
+ }
92
+
93
+ export function sessionEntryToContextMessages(
94
+ entry: SessionTreeEntry,
95
+ index: number,
96
+ entries: readonly SessionTreeEntry[],
97
+ options: SessionContextBuildOptions = {},
98
+ ): AgentMessage[] {
99
+ if (entry.type === "message") {
100
+ return [entry.message as AgentMessage];
101
+ }
102
+ if (entry.type === "custom_message") {
103
+ return [
104
+ createCustomMessage(
105
+ entry.customType,
106
+ entry.content as string | (TextContent | ImageContent)[],
107
+ entry.display,
108
+ entry.details,
109
+ entry.timestamp,
110
+ ),
111
+ ];
112
+ }
113
+ if (entry.type === "compaction") {
114
+ return [createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp)];
115
+ }
116
+ if (entry.type === "branch_summary" && entry.summary) {
117
+ return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
118
+ }
119
+ if (entry.type === "custom") {
120
+ return [...(options.entryProjectors?.[entry.customType]?.(entry, index, entries) ?? [])];
121
+ }
122
+ return [];
123
+ }
124
+
125
+ export function buildSessionContext(
126
+ pathEntries: readonly SessionTreeEntry[],
127
+ options: SessionContextBuildOptions = {},
128
+ ): SessionContext {
129
+ const state = deriveSessionContextState(pathEntries);
130
+ const contextEntries = buildContextEntries(pathEntries, options);
131
+ const messages = contextEntries.flatMap((entry, index) =>
132
+ sessionEntryToContextMessages(entry, index, contextEntries, options),
133
+ );
134
+ return { ...state, messages };
135
+ }
136
+
137
+ export class Session<TMetadata extends SessionMetadata = SessionMetadata> {
138
+ private storage: SessionStorage<TMetadata>;
139
+ private contextBuildOptions: SessionContextBuildOptions;
140
+
141
+ constructor(storage: SessionStorage<TMetadata>, contextBuildOptions: SessionContextBuildOptions = {}) {
142
+ this.storage = storage;
143
+ this.contextBuildOptions = contextBuildOptions;
144
+ }
145
+
146
+ getMetadata(): Promise<TMetadata> {
147
+ return this.storage.getMetadata();
148
+ }
149
+
150
+ getStorage(): SessionStorage<TMetadata> {
151
+ return this.storage;
152
+ }
153
+
154
+ getLeafId(): Promise<string | null> {
155
+ return this.storage.getLeafId();
156
+ }
157
+
158
+ getEntry(id: string): Promise<SessionTreeEntry | undefined> {
159
+ return this.storage.getEntry(id);
160
+ }
161
+
162
+ getEntries(): Promise<SessionTreeEntry[]> {
163
+ return this.storage.getEntries();
164
+ }
165
+
166
+ async getBranch(fromId?: string): Promise<SessionTreeEntry[]> {
167
+ const leafId = fromId ?? (await this.storage.getLeafId());
168
+ return this.storage.getPathToRoot(leafId);
169
+ }
170
+
171
+ async buildContextEntries(options: SessionContextBuildOptions = {}): Promise<SessionTreeEntry[]> {
172
+ return buildContextEntries(await this.getBranch(), this.mergeContextBuildOptions(options));
173
+ }
174
+
175
+ async buildContext(options: SessionContextBuildOptions = {}): Promise<SessionContext> {
176
+ return buildSessionContext(await this.getBranch(), this.mergeContextBuildOptions(options));
177
+ }
178
+
179
+ private mergeContextBuildOptions(options: SessionContextBuildOptions): SessionContextBuildOptions {
180
+ return {
181
+ entryTransforms: [...(this.contextBuildOptions.entryTransforms ?? []), ...(options.entryTransforms ?? [])],
182
+ entryProjectors: {
183
+ ...(this.contextBuildOptions.entryProjectors ?? {}),
184
+ ...(options.entryProjectors ?? {}),
185
+ },
186
+ };
187
+ }
188
+
189
+ getLabel(id: string): Promise<string | undefined> {
190
+ return this.storage.getLabel(id);
191
+ }
192
+
193
+ async getSessionName(): Promise<string | undefined> {
194
+ const entries = await this.storage.findEntries("session_info");
195
+ return entries[entries.length - 1]?.name?.trim() || undefined;
196
+ }
197
+
198
+ private async appendTypedEntry<TEntry extends SessionTreeEntry>(entry: TEntry): Promise<string> {
199
+ await this.storage.appendEntry(entry);
200
+ return entry.id;
201
+ }
202
+
203
+ async appendMessage(message: AgentMessage): Promise<string> {
204
+ return this.appendTypedEntry({
205
+ type: "message",
206
+ id: await this.storage.createEntryId(),
207
+ parentId: await this.storage.getLeafId(),
208
+ timestamp: new Date().toISOString(),
209
+ message,
210
+ } satisfies MessageEntry);
211
+ }
212
+
213
+ async appendThinkingLevelChange(thinkingLevel: string): Promise<string> {
214
+ return this.appendTypedEntry({
215
+ type: "thinking_level_change",
216
+ id: await this.storage.createEntryId(),
217
+ parentId: await this.storage.getLeafId(),
218
+ timestamp: new Date().toISOString(),
219
+ thinkingLevel,
220
+ } satisfies ThinkingLevelChangeEntry);
221
+ }
222
+
223
+ async appendModelChange(provider: string, modelId: string): Promise<string> {
224
+ return this.appendTypedEntry({
225
+ type: "model_change",
226
+ id: await this.storage.createEntryId(),
227
+ parentId: await this.storage.getLeafId(),
228
+ timestamp: new Date().toISOString(),
229
+ provider,
230
+ modelId,
231
+ } satisfies ModelChangeEntry);
232
+ }
233
+
234
+ async appendActiveToolsChange(activeToolNames: string[]): Promise<string> {
235
+ return this.appendTypedEntry({
236
+ type: "active_tools_change",
237
+ id: await this.storage.createEntryId(),
238
+ parentId: await this.storage.getLeafId(),
239
+ timestamp: new Date().toISOString(),
240
+ activeToolNames: [...activeToolNames],
241
+ } satisfies ActiveToolsChangeEntry);
242
+ }
243
+
244
+ async appendCompaction<T = unknown>(
245
+ summary: string,
246
+ firstKeptEntryId: string,
247
+ tokensBefore: number,
248
+ details?: T,
249
+ fromHook?: boolean,
250
+ ): Promise<string> {
251
+ return this.appendTypedEntry({
252
+ type: "compaction",
253
+ id: await this.storage.createEntryId(),
254
+ parentId: await this.storage.getLeafId(),
255
+ timestamp: new Date().toISOString(),
256
+ summary,
257
+ firstKeptEntryId,
258
+ tokensBefore,
259
+ details,
260
+ fromHook,
261
+ } satisfies CompactionEntry<T>);
262
+ }
263
+
264
+ async appendCustomEntry(customType: string, data?: unknown): Promise<string> {
265
+ return this.appendTypedEntry({
266
+ type: "custom",
267
+ id: await this.storage.createEntryId(),
268
+ parentId: await this.storage.getLeafId(),
269
+ timestamp: new Date().toISOString(),
270
+ customType,
271
+ data,
272
+ } satisfies CustomEntry);
273
+ }
274
+
275
+ async appendCustomMessageEntry<T = unknown>(
276
+ customType: string,
277
+ content: string | (TextContent | ImageContent)[],
278
+ display: boolean,
279
+ details?: T,
280
+ ): Promise<string> {
281
+ return this.appendTypedEntry({
282
+ type: "custom_message",
283
+ id: await this.storage.createEntryId(),
284
+ parentId: await this.storage.getLeafId(),
285
+ timestamp: new Date().toISOString(),
286
+ customType,
287
+ content,
288
+ display,
289
+ details,
290
+ } satisfies CustomMessageEntry<T>);
291
+ }
292
+
293
+ async appendLabel(targetId: string, label: string | undefined): Promise<string> {
294
+ if (!(await this.storage.getEntry(targetId))) {
295
+ throw new SessionError("not_found", `Entry ${targetId} not found`);
296
+ }
297
+ return this.appendTypedEntry({
298
+ type: "label",
299
+ id: await this.storage.createEntryId(),
300
+ parentId: await this.storage.getLeafId(),
301
+ timestamp: new Date().toISOString(),
302
+ targetId,
303
+ label,
304
+ } satisfies LabelEntry);
305
+ }
306
+
307
+ async appendSessionName(name: string): Promise<string> {
308
+ const sanitizedName = name.replace(/[\r\n]+/g, " ").trim();
309
+ return this.appendTypedEntry({
310
+ type: "session_info",
311
+ id: await this.storage.createEntryId(),
312
+ parentId: await this.storage.getLeafId(),
313
+ timestamp: new Date().toISOString(),
314
+ name: sanitizedName,
315
+ } satisfies SessionInfoEntry);
316
+ }
317
+
318
+ async moveTo(
319
+ entryId: string | null,
320
+ summary?: { summary: string; details?: unknown; fromHook?: boolean },
321
+ ): Promise<string | undefined> {
322
+ if (entryId !== null && !(await this.storage.getEntry(entryId))) {
323
+ throw new SessionError("not_found", `Entry ${entryId} not found`);
324
+ }
325
+ await this.storage.setLeafId(entryId);
326
+ if (!summary) return undefined;
327
+ return this.appendTypedEntry({
328
+ type: "branch_summary",
329
+ id: await this.storage.createEntryId(),
330
+ parentId: entryId,
331
+ timestamp: new Date().toISOString(),
332
+ fromId: entryId ?? "root",
333
+ summary: summary.summary,
334
+ details: summary.details,
335
+ fromHook: summary.fromHook,
336
+ } satisfies BranchSummaryEntry);
337
+ }
338
+ }
@@ -0,0 +1,54 @@
1
+ let lastTimestamp = -Infinity;
2
+ let sequence = 0;
3
+
4
+ function fillRandomBytes(bytes: Uint8Array): void {
5
+ const crypto = globalThis.crypto;
6
+ if (crypto?.getRandomValues) {
7
+ crypto.getRandomValues(bytes);
8
+ return;
9
+ }
10
+ for (let i = 0; i < bytes.length; i++) {
11
+ bytes[i] = Math.floor(Math.random() * 256);
12
+ }
13
+ }
14
+
15
+ export function uuidv7(): string {
16
+ const random = new Uint8Array(16);
17
+ fillRandomBytes(random);
18
+ const timestamp = Date.now();
19
+
20
+ if (timestamp > lastTimestamp) {
21
+ sequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];
22
+ lastTimestamp = timestamp;
23
+ } else {
24
+ sequence = (sequence + 1) >>> 0;
25
+ if (sequence === 0) {
26
+ lastTimestamp++;
27
+ }
28
+ }
29
+
30
+ const bytes = new Uint8Array(16);
31
+ bytes[0] = (lastTimestamp / 0x10000000000) & 0xff;
32
+ bytes[1] = (lastTimestamp / 0x100000000) & 0xff;
33
+ bytes[2] = (lastTimestamp / 0x1000000) & 0xff;
34
+ bytes[3] = (lastTimestamp / 0x10000) & 0xff;
35
+ bytes[4] = (lastTimestamp / 0x100) & 0xff;
36
+ bytes[5] = lastTimestamp & 0xff;
37
+ bytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);
38
+ bytes[7] = (sequence >>> 20) & 0xff;
39
+ bytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);
40
+ bytes[9] = (sequence >>> 6) & 0xff;
41
+ bytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);
42
+ bytes[11] = random[11];
43
+ bytes[12] = random[12];
44
+ bytes[13] = random[13];
45
+ bytes[14] = random[14];
46
+ bytes[15] = random[15];
47
+
48
+ return formatUuid(bytes);
49
+ }
50
+
51
+ function formatUuid(bytes: Uint8Array): string {
52
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
53
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
54
+ }