@leuduan/lagent 0.0.0-stage → 0.1.2

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 (327) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +144 -2
  3. package/dist/chunks/2O7ZGEIT.js +1 -0
  4. package/dist/chunks/2OSESBIL.js +1 -0
  5. package/dist/chunks/34KW6VNQ.js +1 -0
  6. package/dist/chunks/37YOGDGY.js +1 -0
  7. package/dist/chunks/3LQHQRIU.js +6 -0
  8. package/dist/chunks/3QCW4WDJ.js +1 -0
  9. package/dist/chunks/4XVRUSCQ.js +1 -0
  10. package/dist/chunks/6ECI2GGV.js +1 -0
  11. package/dist/chunks/74HKUGRR.js +1 -0
  12. package/dist/chunks/ADHERZLW.js +2 -0
  13. package/dist/chunks/AP6Q4EPT.js +36 -0
  14. package/dist/chunks/BM3S37EZ.js +1 -0
  15. package/dist/chunks/C5LYCXJG.js +1 -0
  16. package/dist/chunks/CDQG7RKA.js +1 -0
  17. package/dist/chunks/D7E6EWIE.js +3 -0
  18. package/dist/chunks/DDANMY45.js +3 -0
  19. package/dist/chunks/DRYAN665.js +1 -0
  20. package/dist/chunks/DXFXAYDN.js +17 -0
  21. package/dist/chunks/EGZI4XQX.js +24 -0
  22. package/dist/chunks/ENWFSU27.js +41 -0
  23. package/dist/chunks/G6RXC3AL.js +1 -0
  24. package/dist/chunks/G74AGRAJ.js +15 -0
  25. package/dist/chunks/GQGNVSKB.js +1 -0
  26. package/dist/chunks/IJ2WNMD5.js +7 -0
  27. package/dist/chunks/J5S4URAW.js +1 -0
  28. package/dist/chunks/JPZFKSWT.js +1 -0
  29. package/dist/chunks/KESCTXGO.js +5 -0
  30. package/dist/chunks/L3N4FIEN.js +1 -0
  31. package/dist/chunks/NAOUTU7A.js +4 -0
  32. package/dist/chunks/NDIM7MEW.js +1 -0
  33. package/dist/chunks/O4PPOM5Z.js +2 -0
  34. package/dist/chunks/OVZFGILJ.js +1 -0
  35. package/dist/chunks/P5ZHHOOM.js +6 -0
  36. package/dist/chunks/PUSUPTAT.js +1 -0
  37. package/dist/chunks/QMMLQJBS.js +1 -0
  38. package/dist/chunks/RK3VP2Q4.js +3 -0
  39. package/dist/chunks/SGGMBSBA.js +1 -0
  40. package/dist/chunks/SL2YLB2F.js +1 -0
  41. package/dist/chunks/TOOIB6J2.js +1 -0
  42. package/dist/chunks/TYTQRLTX.js +1 -0
  43. package/dist/chunks/UC3FVVJ2.js +5 -0
  44. package/dist/chunks/UCTEU62F.js +1 -0
  45. package/dist/chunks/UD3VJER6.js +1 -0
  46. package/dist/chunks/UKXMCHHT.js +1 -0
  47. package/dist/chunks/WUUKTSRT.js +7 -0
  48. package/dist/chunks/X65X4KP5.js +7 -0
  49. package/dist/chunks/YIR5MYGU.js +1 -0
  50. package/dist/chunks/YLNJXQ3Z.js +1 -0
  51. package/dist/context.d.ts +101 -0
  52. package/dist/index.d.ts +47 -0
  53. package/dist/index.js +77 -0
  54. package/dist/journal/catalog.d.ts +112 -0
  55. package/dist/journal/forkChain.d.ts +16 -0
  56. package/dist/journal/index.d.ts +15 -0
  57. package/dist/journal/journal.d.ts +475 -0
  58. package/dist/journal/projection.d.ts +87 -0
  59. package/dist/journal/store.d.ts +181 -0
  60. package/dist/kit/claim.d.ts +13 -0
  61. package/dist/kit/drain.d.ts +10 -0
  62. package/dist/kit/extension.d.ts +180 -0
  63. package/dist/kit/grants.d.ts +9 -0
  64. package/dist/kit/modes.d.ts +65 -0
  65. package/dist/kit/retries.d.ts +25 -0
  66. package/dist/kit/scope.d.ts +32 -0
  67. package/dist/kit/service.d.ts +7 -0
  68. package/dist/kit/strategy.d.ts +10 -0
  69. package/dist/kit/timers.d.ts +43 -0
  70. package/dist/kit/tool.d.ts +72 -0
  71. package/dist/llm/client.d.ts +135 -0
  72. package/dist/llm/content.d.ts +52 -0
  73. package/dist/llm/door.d.ts +21 -0
  74. package/dist/llm/door.js +1 -0
  75. package/dist/llm/failure.d.ts +82 -0
  76. package/dist/llm/index.d.ts +16 -0
  77. package/dist/llm/primitives.d.ts +286 -0
  78. package/dist/llm/prompt.d.ts +21 -0
  79. package/dist/llm/provider.d.ts +63 -0
  80. package/dist/llm/readLedger.d.ts +24 -0
  81. package/dist/llm/request.d.ts +58 -0
  82. package/dist/loop/agent.d.ts +134 -0
  83. package/dist/loop/auxiliary.d.ts +54 -0
  84. package/dist/loop/chain.d.ts +46 -0
  85. package/dist/loop/chunks.d.ts +27 -0
  86. package/dist/loop/continuation.d.ts +166 -0
  87. package/dist/loop/decide.d.ts +64 -0
  88. package/dist/loop/errors.d.ts +162 -0
  89. package/dist/loop/forks.d.ts +61 -0
  90. package/dist/loop/holds.d.ts +104 -0
  91. package/dist/loop/hooks.d.ts +241 -0
  92. package/dist/loop/inbox.d.ts +188 -0
  93. package/dist/loop/index.d.ts +37 -0
  94. package/dist/loop/limits.d.ts +14 -0
  95. package/dist/loop/opening.d.ts +42 -0
  96. package/dist/loop/prepare.d.ts +30 -0
  97. package/dist/loop/projections.d.ts +307 -0
  98. package/dist/loop/replace.d.ts +33 -0
  99. package/dist/loop/requests.d.ts +129 -0
  100. package/dist/loop/route.d.ts +53 -0
  101. package/dist/loop/runtime.d.ts +85 -0
  102. package/dist/loop/state.d.ts +70 -0
  103. package/dist/loop/strategy.d.ts +71 -0
  104. package/dist/loop/summary.d.ts +3 -0
  105. package/dist/loop/surface.d.ts +153 -0
  106. package/dist/loop/threadState.d.ts +72 -0
  107. package/dist/loop/tool.d.ts +101 -0
  108. package/dist/loop/toolCalls.d.ts +42 -0
  109. package/dist/loop/wake.d.ts +32 -0
  110. package/dist/models/config/agent.d.ts +18 -0
  111. package/dist/models/config/prompt.d.ts +18 -0
  112. package/dist/models/door.d.ts +12 -0
  113. package/dist/models/door.js +1 -0
  114. package/dist/models/index.d.ts +7 -0
  115. package/dist/models/jsonSchema.d.ts +7 -0
  116. package/dist/models/wire/journal.d.ts +2772 -0
  117. package/dist/models/wire/primitives.d.ts +65 -0
  118. package/dist/plugin.d.ts +53 -0
  119. package/dist/plugin.js +1 -0
  120. package/dist/plugins/agentsMd.d.ts +76 -0
  121. package/dist/plugins/agentsMd.js +1 -0
  122. package/dist/plugins/ask/askQuestion.d.ts +9 -0
  123. package/dist/plugins/ask/index.d.ts +26 -0
  124. package/dist/plugins/ask/index.js +1 -0
  125. package/dist/plugins/ask/service.d.ts +125 -0
  126. package/dist/plugins/commands/background.d.ts +8 -0
  127. package/dist/plugins/commands/foreground.d.ts +4 -0
  128. package/dist/plugins/commands/index.d.ts +40 -0
  129. package/dist/plugins/commands/index.js +1 -0
  130. package/dist/plugins/commands/output.d.ts +115 -0
  131. package/dist/plugins/commands/record.d.ts +549 -0
  132. package/dist/plugins/commands/service.d.ts +314 -0
  133. package/dist/plugins/commands/shell.d.ts +25 -0
  134. package/dist/plugins/compaction/checkpoint.d.ts +91 -0
  135. package/dist/plugins/compaction/config.d.ts +133 -0
  136. package/dist/plugins/compaction/estimate.d.ts +29 -0
  137. package/dist/plugins/compaction/index.d.ts +2 -0
  138. package/dist/plugins/compaction/index.js +7 -0
  139. package/dist/plugins/compaction/log.d.ts +61 -0
  140. package/dist/plugins/compaction/planner.d.ts +207 -0
  141. package/dist/plugins/compaction/preset.d.ts +86 -0
  142. package/dist/plugins/compaction/prune.d.ts +9 -0
  143. package/dist/plugins/compaction/records.d.ts +227 -0
  144. package/dist/plugins/compaction/segments.d.ts +23 -0
  145. package/dist/plugins/compaction/shared.d.ts +14 -0
  146. package/dist/plugins/compaction/summarize.d.ts +13 -0
  147. package/dist/plugins/dateAndBranch.d.ts +47 -0
  148. package/dist/plugins/dateAndBranch.js +1 -0
  149. package/dist/plugins/delegations/answers.d.ts +39 -0
  150. package/dist/plugins/delegations/assignmentKey.d.ts +22 -0
  151. package/dist/plugins/delegations/cleanup.d.ts +161 -0
  152. package/dist/plugins/delegations/constraint.d.ts +76 -0
  153. package/dist/plugins/delegations/index.d.ts +39 -0
  154. package/dist/plugins/delegations/index.js +1 -0
  155. package/dist/plugins/delegations/notices.d.ts +261 -0
  156. package/dist/plugins/delegations/obligations.d.ts +210 -0
  157. package/dist/plugins/delegations/record.d.ts +632 -0
  158. package/dist/plugins/delegations/request.d.ts +381 -0
  159. package/dist/plugins/delegations/role.d.ts +30 -0
  160. package/dist/plugins/delegations/service.d.ts +562 -0
  161. package/dist/plugins/delegations/standing.d.ts +19 -0
  162. package/dist/plugins/delegations/stopCheck.d.ts +21 -0
  163. package/dist/plugins/delegations/testing.d.ts +16 -0
  164. package/dist/plugins/delegations/tools.d.ts +71 -0
  165. package/dist/plugins/delegations/waitBook.d.ts +116 -0
  166. package/dist/plugins/delegations/waits.d.ts +118 -0
  167. package/dist/plugins/diagnostics/digest.d.ts +14 -0
  168. package/dist/plugins/diagnostics/index.d.ts +68 -0
  169. package/dist/plugins/diagnostics/index.js +1 -0
  170. package/dist/plugins/historyRecall/history.d.ts +9 -0
  171. package/dist/plugins/historyRecall/index.d.ts +31 -0
  172. package/dist/plugins/historyRecall/index.js +1 -0
  173. package/dist/plugins/historyRecall/render.d.ts +34 -0
  174. package/dist/plugins/historyRecall/tools.d.ts +4 -0
  175. package/dist/plugins/mcp/catalog.d.ts +36 -0
  176. package/dist/plugins/mcp/config.d.ts +63 -0
  177. package/dist/plugins/mcp/connection.d.ts +53 -0
  178. package/dist/plugins/mcp/errors.d.ts +32 -0
  179. package/dist/plugins/mcp/index.d.ts +33 -0
  180. package/dist/plugins/mcp/index.js +5 -0
  181. package/dist/plugins/mcp/mount.d.ts +98 -0
  182. package/dist/plugins/mcp/names.d.ts +25 -0
  183. package/dist/plugins/mcp/render.d.ts +29 -0
  184. package/dist/plugins/mcp/slots.d.ts +15 -0
  185. package/dist/plugins/mcp/stdio.d.ts +49 -0
  186. package/dist/plugins/mcp/tool.d.ts +41 -0
  187. package/dist/plugins/providers/anthropic.d.ts +175 -0
  188. package/dist/plugins/providers/anthropicMessages.d.ts +65 -0
  189. package/dist/plugins/providers/codex.d.ts +60 -0
  190. package/dist/plugins/providers/codexAuth.d.ts +116 -0
  191. package/dist/plugins/providers/deepseek.d.ts +55 -0
  192. package/dist/plugins/providers/door.d.ts +61 -0
  193. package/dist/plugins/providers/door.js +1 -0
  194. package/dist/plugins/providers/failure.d.ts +23 -0
  195. package/dist/plugins/providers/gateway.d.ts +23 -0
  196. package/dist/plugins/providers/index.d.ts +6 -0
  197. package/dist/plugins/providers/openaiChat.d.ts +62 -0
  198. package/dist/plugins/providers/openaiResponses.d.ts +100 -0
  199. package/dist/plugins/providers/opencodeCopilot.d.ts +23 -0
  200. package/dist/plugins/providers/opencodeGo.d.ts +98 -0
  201. package/dist/plugins/providers/shared.d.ts +104 -0
  202. package/dist/plugins/providers/stream.d.ts +154 -0
  203. package/dist/plugins/routeContext.d.ts +22 -0
  204. package/dist/plugins/routeContext.js +1 -0
  205. package/dist/plugins/schedules/index.d.ts +21 -0
  206. package/dist/plugins/schedules/index.js +5 -0
  207. package/dist/plugins/schedules/record.d.ts +396 -0
  208. package/dist/plugins/schedules/service.d.ts +120 -0
  209. package/dist/plugins/schedules/time.d.ts +26 -0
  210. package/dist/plugins/schedules/tools.d.ts +6 -0
  211. package/dist/plugins/skills/discovery.d.ts +54 -0
  212. package/dist/plugins/skills/index.d.ts +31 -0
  213. package/dist/plugins/skills/index.js +1 -0
  214. package/dist/plugins/skills/tool.d.ts +11 -0
  215. package/dist/plugins/store/durableObject.d.ts +23 -0
  216. package/dist/plugins/store/durableObject.js +1 -0
  217. package/dist/plugins/store/durableObjectConnection.d.ts +27 -0
  218. package/dist/plugins/store/memory.d.ts +29 -0
  219. package/dist/plugins/store/sql.d.ts +59 -0
  220. package/dist/plugins/store/sqlite.d.ts +31 -0
  221. package/dist/plugins/store/sqlite.js +1 -0
  222. package/dist/plugins/subAgents/availableRoutes.d.ts +53 -0
  223. package/dist/plugins/subAgents/fork.d.ts +32 -0
  224. package/dist/plugins/subAgents/index.d.ts +67 -0
  225. package/dist/plugins/subAgents/index.js +1 -0
  226. package/dist/plugins/subAgents/tool.d.ts +38 -0
  227. package/dist/plugins/toolPolicy/index.d.ts +61 -0
  228. package/dist/plugins/toolPolicy/index.js +1 -0
  229. package/dist/plugins/tools/editFiles.d.ts +128 -0
  230. package/dist/plugins/tools/fsRead.d.ts +17 -0
  231. package/dist/plugins/tools/html.d.ts +23 -0
  232. package/dist/plugins/tools/index.d.ts +59 -0
  233. package/dist/plugins/tools/index.js +1 -0
  234. package/dist/plugins/tools/network.d.ts +23 -0
  235. package/dist/plugins/tools/ripgrep.d.ts +20 -0
  236. package/dist/plugins/tools/textEdit.d.ts +67 -0
  237. package/dist/plugins/tools/web.d.ts +32 -0
  238. package/dist/plugins/truncateToolOutput.d.ts +26 -0
  239. package/dist/plugins/truncateToolOutput.js +1 -0
  240. package/dist/plugins/usage/index.d.ts +24 -0
  241. package/dist/plugins/usage/index.js +1 -0
  242. package/dist/plugins/usage/tracker.d.ts +34 -0
  243. package/dist/plugins/verify/facts.d.ts +356 -0
  244. package/dist/plugins/verify/index.d.ts +75 -0
  245. package/dist/plugins/verify/index.js +1 -0
  246. package/dist/plugins/verify/service.d.ts +90 -0
  247. package/dist/plugins/workflows/assignment.d.ts +16 -0
  248. package/dist/plugins/workflows/bindings.d.ts +95 -0
  249. package/dist/plugins/workflows/cleanup.d.ts +38 -0
  250. package/dist/plugins/workflows/definition.d.ts +184 -0
  251. package/dist/plugins/workflows/fold.d.ts +373 -0
  252. package/dist/plugins/workflows/index.d.ts +28 -0
  253. package/dist/plugins/workflows/index.js +6 -0
  254. package/dist/plugins/workflows/observations.d.ts +81 -0
  255. package/dist/plugins/workflows/participants.d.ts +143 -0
  256. package/dist/plugins/workflows/policy.d.ts +112 -0
  257. package/dist/plugins/workflows/providers.d.ts +146 -0
  258. package/dist/plugins/workflows/record.d.ts +2863 -0
  259. package/dist/plugins/workflows/routing.d.ts +116 -0
  260. package/dist/plugins/workflows/schema.d.ts +26 -0
  261. package/dist/plugins/workflows/service.d.ts +477 -0
  262. package/dist/plugins/workflows/submit.d.ts +8 -0
  263. package/dist/plugins/workflows/view.d.ts +103 -0
  264. package/dist/plugins/workflows/work.d.ts +21 -0
  265. package/dist/plugins/workspaceContext.d.ts +38 -0
  266. package/dist/plugins/workspaceContext.js +1 -0
  267. package/dist/presets/agents.d.ts +7 -0
  268. package/dist/presets/base.d.ts +10 -0
  269. package/dist/presets/codex.d.ts +60 -0
  270. package/dist/presets/index.d.ts +4 -0
  271. package/dist/presets/prompts.d.ts +56 -0
  272. package/dist/sandbox/absent.d.ts +32 -0
  273. package/dist/sandbox/client.d.ts +39 -0
  274. package/dist/sandbox/files.d.ts +28 -0
  275. package/dist/sandbox/index.d.ts +49 -0
  276. package/dist/sandbox/index.js +4 -0
  277. package/dist/sandbox/mode.d.ts +57 -0
  278. package/dist/sandbox/policy.d.ts +86 -0
  279. package/dist/sandbox/protocol.d.ts +107 -0
  280. package/dist/sandbox/service.d.ts +143 -0
  281. package/dist/sandbox/worker.d.ts +12 -0
  282. package/dist/sandbox/worker.js +1 -0
  283. package/dist/services/admission.d.ts +174 -0
  284. package/dist/services/agents.d.ts +37 -0
  285. package/dist/services/birth.d.ts +220 -0
  286. package/dist/services/contributions.d.ts +73 -0
  287. package/dist/services/core.d.ts +34 -0
  288. package/dist/services/journal.d.ts +26 -0
  289. package/dist/services/launches.d.ts +104 -0
  290. package/dist/services/llm.d.ts +80 -0
  291. package/dist/services/owner.d.ts +367 -0
  292. package/dist/services/preset.d.ts +154 -0
  293. package/dist/services/presets.d.ts +139 -0
  294. package/dist/services/prompts.d.ts +67 -0
  295. package/dist/services/runEvents.d.ts +79 -0
  296. package/dist/services/thread.d.ts +267 -0
  297. package/dist/services/threadActivation.d.ts +100 -0
  298. package/dist/services/threadDirs.d.ts +38 -0
  299. package/dist/services/threadView.d.ts +92 -0
  300. package/dist/services/threads.d.ts +449 -0
  301. package/dist/services/tools.d.ts +41 -0
  302. package/dist/sys/environment.d.ts +47 -0
  303. package/dist/sys/git.d.ts +60 -0
  304. package/dist/sys/paths.d.ts +56 -0
  305. package/dist/sys/spawn.d.ts +176 -0
  306. package/dist/testing/clock.d.ts +17 -0
  307. package/dist/testing/fakeLlm.d.ts +74 -0
  308. package/dist/testing/fedLlm.d.ts +32 -0
  309. package/dist/testing/helpers.d.ts +344 -0
  310. package/dist/testing/index.d.ts +13 -0
  311. package/dist/testing/index.js +1 -0
  312. package/dist/testing/processes.d.ts +13 -0
  313. package/dist/testing/sandbox.d.ts +71 -0
  314. package/dist/testing/settlement.d.ts +6 -0
  315. package/dist/testing/tmpDirs.d.ts +17 -0
  316. package/dist/util/async.d.ts +8 -0
  317. package/dist/util/diff.d.ts +25 -0
  318. package/dist/util/dispatch.d.ts +8 -0
  319. package/dist/util/errors.d.ts +28 -0
  320. package/dist/util/foldState.d.ts +17 -0
  321. package/dist/util/freeze.d.ts +2 -0
  322. package/dist/util/ids.d.ts +2 -0
  323. package/dist/util/json.d.ts +37 -0
  324. package/dist/util/log.d.ts +6 -0
  325. package/dist/util/text.d.ts +21 -0
  326. package/dist/util/version.d.ts +2 -0
  327. package/package.json +175 -3
@@ -0,0 +1,7 @@
1
+ import{a as B,b as Me,c as j}from"../../chunks/UC3FVVJ2.js";import{a as G}from"../../chunks/4XVRUSCQ.js";import{a as Se}from"../../chunks/L3N4FIEN.js";import"../../chunks/NAOUTU7A.js";import"../../chunks/UKXMCHHT.js";import{b as K}from"../../chunks/DRYAN665.js";import"../../chunks/2OSESBIL.js";import{j as Te,k as qe,o as A,p as Oe}from"../../chunks/YLNJXQ3Z.js";import{f as se}from"../../chunks/DDANMY45.js";import{h as Ie}from"../../chunks/37YOGDGY.js";import{a as L,b as Re}from"../../chunks/KESCTXGO.js";import"../../chunks/TYTQRLTX.js";import{A as Ce,i as $e,j as ne,k as _e,q as ve,v as H,w as D}from"../../chunks/D7E6EWIE.js";import{z as p}from"zod";var Ee=p.number().gt(0).lt(1),U=p.number().int().nonnegative(),ot=p.strictObject({provider:p.string().min(1).optional(),model:p.string().min(1).optional(),thinkingEffort:_e.default("low")}),at=p.strictObject({kind:p.literal("summarize"),target:Ee.default(.5),tail:p.number().nonnegative().lt(1).default(.15),opening:p.number().nonnegative().lt(1).default(.1),summaryCap:p.number().int().positive().default(8192),summaryFloor:p.number().int().positive().default(1024),reasoningAllowance:U.default(8192),replyReserve:U.default(16384),checkpointRatio:p.number().gt(0).lte(1).default(.5),copiedInputChars:p.number().int().positive().default(4e3),boundaryQuoteChars:p.number().int().positive().default(200),breaker:p.number().int().positive().default(3),withoutWindow:p.strictObject({tailTokens:U.default(2e4),openingTokens:U.default(1e4)}).default({tailTokens:2e4,openingTokens:1e4}),summarizer:ot.default({thinkingEffort:"low"})}).refine(e=>e.summaryFloor<=e.summaryCap,{message:"The summary floor must not exceed the summary cap, or no summary could be allowed"}),it=p.strictObject({kind:p.literal("prune"),keepRecent:p.number().int().nonnegative().default(8),minTokens:p.number().int().positive().default(250)}),ze=p.strictObject({threshold:Ee.default(.8),strategy:p.discriminatedUnion("kind",[at,it]).prefault({kind:"summarize"})}).refine(e=>e.strategy.kind!=="summarize"||e.strategy.target<e.threshold,{message:"The target must lie below the threshold, or a compaction would aim above the point that triggers it",path:["strategy","target"]}),Ae=p.strictObject({focus:p.string().trim().min(1).optional()}).nullable();var ct=4,re=4,je=4,lt=1600,v=e=>Math.ceil(e.length/ct);function ut(e){let t=0;for(let n of e)t+=re+(n.type==="text"?v(n.text):lt);return t}function R(e){let t=je+ut(e.content);e.reasoning_content!==null&&(t+=v(e.reasoning_content));for(let n of e.tool_calls)t+=re+v(n.name)+v(ve(n));return t}function Ne(e){let t=Ce(e.systemPrompt),n=e.tools.length===0?0:re+v(JSON.stringify(e.tools));return(t.length===0?0:je+v(t))+n}import{z as T}from"zod";var W="lagent:compaction",Pe=K({plugin:W,kind:"checkpoint",version:1,schema:T.strictObject({summary_cap:T.number().int().positive(),target_reached:T.boolean().nullable()})}),Fe=K({plugin:W,kind:"prune",version:1,schema:T.strictObject({chars:T.number().int().nonnegative(),attachments:T.number().int().nonnegative()})}),We=K({plugin:W,kind:"unusable-summary",version:1,schema:T.strictObject({reason:T.string()})});import{scopeOf as He}from"@leuduan/cordis";function J(e){let t=new Set;return(n,s)=>{t.has(n)||(t.add(n),e.reportError(new Error(s)))}}function Q(e,t){let n=new Set(e.tools.toolsFor(He(e),t).map(s=>s.name));return Me.every(s=>n.has(s))}function V(e,t,n){return Ne({systemPrompt:e.journal.state(A,t).threadPrompt??[],tools:e.tools.toolsFor(He(e),n).map(s=>s.spec)})}var Y=e=>e.queued.reduce((t,n)=>t+R(H({role:n.role,content:n.content})),0);var Le={name:"lagent:compaction:prune",inject:["journal","llm","tools"],apply(e,t){let n=new ae(e,t);G(e,t.threadId,{name:"compaction (prune)",plan:s=>n.plan(s)})}},ae=class{strategy;threshold;threadId;agentName;reportOnce;ctx;constructor(t,n){this.ctx=t,this.strategy=n.strategy,this.threshold=n.threshold,this.threadId=n.threadId,this.agentName=n.agentName,this.reportOnce=J(t)}plan(t){let{trigger:n,route:s}=t,r=this.ctx.journal.state(A,this.threadId).surface.entries,o=this.survey(r);if(n==="pressure"){let c=this.ctx.llm.capacity(s).contextWindow;if(c===null)return this.reportOnce(`window:${oe(s)}`,`Thread ${this.threadId}: ${oe(s)} declares no context window, so its tool results are never pruned for pressure`),{kind:"skip",reason:"the route declares no context window"};let l=this.estimate(r,t);if(l<=this.threshold*c)return{kind:"skip",reason:`the request is estimated at ${dt(l/c)} of the window, under the threshold`}}if(o.eligible.length===0){let c=`nothing to prune: ${N(o.results,"tool result")}, ${o.kept} kept recent, none of the rest an unpruned result estimated at ${N(this.strategy.minTokens,"token")} or more`;return n!=="request"&&this.reportOnce(`none:${n}:${s===null?"":oe(s)}:${mt(r)}`,`Thread ${this.threadId}: cannot prune (${n}): ${c}`),{kind:"skip",reason:c}}let a=o.eligible.reduce((c,l)=>c+l.chars,0),i=o.eligible.reduce((c,l)=>c+l.attachments,0);return{kind:"replace",replacements:this.rewrites(o.eligible),reason:`pruned ${N(o.eligible.length,"tool result")}, ${De(a,i)}`}}survey(t){let n=t.filter(a=>a.message.role==="tool"),s=Math.min(this.strategy.keepRecent,n.length),r=n.slice(0,n.length-s),o=[];for(let a of r){if(a.type!=="tool/result"||R(a.message)<this.strategy.minTokens)continue;let i=this.ctx.journal.eventAt(a.row.seq);if(i?.type!=="tool/result")throw new Error(`Row ${a.row.seq} is behind a tool result but is no tool result`);o.push({entry:a,name:i.data.result.name,chars:D(a.message).length,attachments:a.message.content.filter(c=>c.type!=="text").length})}return{results:n.length,kept:s,eligible:o}}rewrites(t){let{journal:n}=this.ctx,s=B(n,this.threadId),r=Q(this.ctx,this.agentName);return t.map(({entry:o,name:a,chars:i,attachments:c})=>{let l=s.get(o.row.seq);return{kind:"rewrite",stand_in:{content:[{type:"text",text:[`[tool result pruned: ${a}, ${De(i,c)}; message ${l}]`,...r?[j(l,1)]:[]].join(`
2
+ `)}]},source:Fe.record({chars:i,attachments:c}),source_seqs:[o.row.seq]}})}estimate(t,n){let s=V(this.ctx,this.threadId,this.agentName),r=t.reduce((o,a)=>o+R(a.message),0);return s+r+Y(n)}},mt=e=>e.reduce((t,n)=>n.type==="surface/replaced"?Math.max(t,n.row.seq):t,0),N=(e,t)=>`${e} ${t}${e===1?"":"s"}`,De=(e,t)=>t===0?N(e,"character"):`${N(e,"character")} and ${N(t,"attachment")}`,dt=e=>`${Math.round(e*100)}%`,oe=e=>`${e.provider}/${e.model}`;function ie(e){let{boundary:t}=e;return[t===null?"Condense the conversation above, from its first message through its last, into a checkpoint.":`Condense part of the conversation above into a checkpoint: every message after the ${t.role} message that begins ${ht(t.text,e.quoteChars)} (the last message with that beginning before the part), through the last message above. What comes before that part is context, kept as it is or condensed already: do not restate it.`,"The checkpoint will replace that part for a model that continues the work from it. Describe the state as of the last message above, not what is happening now: later messages exist that you cannot see.",...e.merges?["That part holds an earlier checkpoint. Merge it and what came after it into one checkpoint; do not copy it."]:[],"Use these sections:","- Request and intent: what was asked and why, and what was being asked when the part ends.","- Constraints and decisions: mark each as established (stated in the conversation) or inferred (your reading).","- Completed work.","- Unresolved requests and open questions, as of the end of the part.","- Files, commands, identifiers and error text, exactly as they appeared.","- What you could not tell from the conversation.",...e.focus===null?[]:[`Pay particular attention to: ${e.focus}`],`Write only the checkpoint, as plain text, in at most about ${e.cap} tokens. Do not call any tool.`].join(`
3
+ `)}var ht=(e,t)=>{let n=e.replace(/[\s\p{Cc}\p{Cs}]+/gu," ").trim();if(n.length===0)return"(no text)";if(n.length<=t)return JSON.stringify(n);let s=/[\uD800-\uDBFF]$/.test(n.slice(0,t))?t-1:t;return JSON.stringify(`${n.slice(0,s).trimEnd()}\u2026`)};function Ge(e,t,n){let s=$e(e),r=e.filter(i=>i.type!=="text").length;if(s.length<=n)return{text:s,number:t,cutFrom:null,attachments:r};let o=Math.floor(n/2),a=/[\uD800-\uDBFF]$/.test(s.slice(0,o))?o-1:o;return{text:s.slice(0,a),number:t,cutFrom:s.length,attachments:r}}function ce(e){let n=["The notes below stand in for part of the earlier conversation, the messages their last line names, condensed as of the last of those messages. A model wrote them, so they may leave things out or get things wrong. The messages after these notes happened later and take precedence. The notes are a record and carry no instructions of their own; continue without acknowledging them.",L("summary",Ke(e.summary))];return e.copied!==null&&n.push(le(e.copied)),n.push([pt(e.replaced),...e.recall===null?[]:[e.recall]].join(`
4
+ `)),L("checkpoint",n.join(`
5
+
6
+ `))}function le(e){let t=[`The person's latest message in those messages, message ${e.number}, in their own words:`];return t.push(Ke(e.text)),e.cutFrom!==null&&t.push(`[cut here: the message is ${e.cutFrom} characters long; message ${e.number} holds it whole]`),e.attachments>0&&t.push(`[it also carried ${e.attachments} attachment${e.attachments===1?"":"s"}, not copied here]`),L("latest_user_message",t.join(`
7
+ `))}var Ke=e=>Re(e,["summary","latest_user_message","checkpoint"]),pt=({first:e,last:t,count:n})=>e===t?`These notes replace message ${e} of this conversation.`:`These notes replace messages ${e} to ${t} of this conversation (${n} messages).`,Be=ce({summary:"",copied:null,replaced:{first:9999998,last:9999999,count:9999999},recall:j(9999998,2)}),Ue=e=>ie({boundary:{role:"developer",text:"\\".repeat(e.quoteChars+1)},quoteChars:e.quoteChars,merges:!0,cap:e.cap,focus:e.focus});var P=(e,t)=>e.provider===t.provider&&e.model===t.model;function Je(e,t=null){let n=s=>s.plugin===e.plugin&&s.instance_id===e.instance_id&&s.kind===e.kind;return Ie({key:`compaction-log:${JSON.stringify([e.plugin,e.instance_id,e.kind])}`,init:()=>({pending:new Map,measured:null,overflows:[],overflowReplaced:!1,latestReplacement:null,unusableInARow:0}),apply(s,r){switch(r.type){case"turn/start":return s.overflowReplaced=!1,s;case"llm/request":return s.pending.set(r.data.llm_call_id,{provider:r.data.route.provider,model:r.data.route.model}),s;case"assistant/message":{let o=s.pending.get(r.data.llm_call_id);if(s.pending.delete(r.data.llm_call_id),r.data.interrupted)return s;s.overflowReplaced=!1;let{message:a}=r.data.response,i=r.data.usage??a.usage;if(o===void 0||i===null)return s;let c=ft(i,a);return c>0&&(s.measured={...o,seq:r.seq,tokens:c},s.overflows=s.overflows.filter(l=>!P(l,o))),s}case"assistant/attempt":{let o=s.pending.get(r.data.llm_call_id);return s.pending.delete(r.data.llm_call_id),r.data.failure_kind==="overflow"&&o!==void 0&&s.overflows.push({...o,seq:r.seq,measured:s.measured}),s}case"surface/replaced":return s.latestReplacement=r.seq,n(r.data.source)&&(r.data.trigger==="overflow"&&(s.overflowReplaced=!0),s.unusableInARow=0),s;case"ext":return t!==null&&r.data.plugin===e.plugin&&r.data.instance_id===e.instance_id&&r.data.kind===t.kind&&(s.unusableInARow+=1),s;case"installation/applied":case"installation/removed":return s.unusableInARow=0,s;default:return s}}})}function ft(e,t){let n=t.provider_state!==null||t.reasoning_content!==null;return e.input_tokens+e.output_tokens-(n?0:e.reasoning_output_tokens)}function Qe(e,t=0){let n=[],s=t;for(let r=t;r<=e.length;r+=1)r<e.length&&!e[r].directDeveloperInput||(r>s&&n.push({start:s,end:r,last:r===e.length}),s=r+1);return n}var de=e=>e.measured||e.written;function Ye(e){let{entries:t,balanced:n,budgets:s}=e;if(n.length!==t.length+1)throw new RangeError(`balanced has ${n.length} cuts for ${t.length} entries; it needs one more`);let r=t.length,{window:o}=e.continuation,a=ue(e.continuation,e.head,t),i=ue(e.summarizer,e.head,t),c=me(t.map(u=>u.retold?u.tokens:0)),l=(u,m,h)=>u[h]-u[m],w=o===null?s.withoutWindow.openingTokens:s.opening*o,k=o===null?s.withoutWindow.tailTokens:s.tail*o,{openingEnd:g}=e,f=g!==null&&g<r&&n[g+1]===!0&&l(a.sums,0,g+1)<=w?g+1:0,d=Qe(t,f),y=me(t.map(u=>u.written?0:1)),x=(u,m)=>l(y,u,m)>0,E=d.map(u=>{if(!n[u.start])return[];if(!u.last)return n[u.end]&&x(u.start,u.end)?[u.end]:[];let m=[];for(let h=u.start+1;h<r;h+=1)n[h]&&x(u.start,h)&&m.push(h);return m}),z=(u,m,h,$)=>{let I=l(a.sums,m,h),O=l(c,m,h),S=e.latestInput,C=S!==null&&S.index>=m&&S.index<h,M=C?S.tokens:0,F=a.head+a.sums[r]-I+a.written*(e.framing+M+O)+e.continuation.factor*e.claimed,ge=$===null?1/0:($-F)/a.written,Z=e.summarizer,we=Z.reasons?s.reasoningAllowance:0,ke=i.head+i.sums[h]+i.written*e.instruction,ye=Z.window===null?1/0:Z.window-ke-we,xe=s.checkpointRatio*I/a.written-(e.framing+M+O),ee=Math.floor(Math.min(s.summaryCap,ge,ye,xe)),te=Math.max(ee,0),rt=a.written*(e.framing+M+O+te),be=F+a.written*te;return{segment:u,start:m,end:h,capContinuation:ge,capSummary:ye,capRatio:xe,summaryCap:ee,feasible:ee>=s.summaryFloor,copiesInput:C,spanTokens:I,continuation:be,summaryCall:ke+te+we,reduction:I-rt,targetReached:o===null?null:be+s.replyReserve<=s.target*o}},_=u=>{let m=r,h=0;do m-=1,h+=l(a.sums,m,m+1);while(m>u+1&&h<k);for(;m>u&&!n[m];)m-=1;return m},q=u=>d.map((m,h)=>E[h].map($=>z(h,m.start,$,u)).filter($=>$.feasible)),fe=u=>{let m=u.flatMap(($,I)=>{if($.length===0)return[];let O=$.filter(C=>C.targetReached!==!1);if(O.length===0)return[Ve($)];if(!d[I].last)return[O[0]];let S=_(d[I].start);return[O.reduce((C,M)=>{let F=Math.abs(M.end-S)-Math.abs(C.end-S);return F<0||F===0&&M.end<C.end?M:C})]});if(m.length===0)return null;let h=m.filter($=>$.targetReached!==!1);return Ve(h.length>0?h:m)},X=o===null?null:s.threshold*o-s.replyReserve,b=fe(q(X));if(b===null&&o!==null){let u=q(o-s.replyReserve),m=u.filter(h=>h.length>0).length>=2;(e.acceptance==="window"||m)&&(X=o-s.replyReserve,b=fe(u))}return b===null?gt(s.summaryFloor,d.flatMap((u,m)=>E[m].map(h=>z(m,u.start,h,X)))):{kind:"plan",start:b.start,end:b.end,pinned:f,summaryCap:b.summaryCap,copiesInput:b.copiesInput,spanTokens:b.spanTokens,continuation:b.continuation,summaryCall:b.summaryCall,targetReached:b.targetReached,segment:{index:b.segment,count:d.length}}}var Ve=e=>e.reduce((t,n)=>n.reduction>t.reduction?n:t);function gt(e,t){if(t.length===0)return{kind:"none",cause:"nothing-to-replace",reason:"no span can be replaced: past the pinned opening there is no balanced run that keeps the newest message and holds more than checkpoints and notices"};let n=r=>Math.floor(r)>=e,s=t.filter(r=>n(r.capRatio));return s.length===0?{kind:"none",cause:"no-reduction",reason:`no span leaves room for a summary of at least ${e} tokens under the reduction it must make, its checkpoint and the notices it would make plugins tell again counted`}:s.every(r=>!n(r.capSummary))?{kind:"none",cause:"summary-call-too-large",reason:`no span's summary call leaves room for a summary of at least ${e} tokens in the summarizer's window; a summarizer route with a larger window is the way out`}:s.every(r=>!n(r.capContinuation))?{kind:"none",cause:"continuation-too-large",reason:`no span leaves room for a summary of at least ${e} tokens under the next request's ceiling: what must stay (prompt, tools, opening, developer input, tail) plus the reply reserve is too large`}:{kind:"none",cause:"no-span-fits-both",reason:`no span fits both budgets with room for a summary of at least ${e} tokens: a span short enough for the summary call leaves the next request over its ceiling; a summarizer route with a larger window is the way out`}}function ue(e,t,n){let s=e.scale??e.factor,r=o=>e.scale!==null&&de(o)?e.scale:e.factor;return{head:s*t,sums:me(n.map(o=>r(o)*o.tokens)),written:s}}var me=e=>{let t=[0];for(let n of e)t.push(t.at(-1)+n);return t};function Xe(e){let{head:t,sums:n}=ue(e.route,e.head,e.entries);return t+n.at(-1)+e.route.factor*e.claimed}function Ze(e,t,n){let s=t-(n.measuredTokens??0),r=n.estimated>0?s/n.estimated:1;return Math.max(1,e,r)}var wt=Je({plugin:W,instance_id:"default",kind:"checkpoint"},{kind:"unusable-summary"}),nt={name:"lagent:compaction:summarize",inject:["journal","llm","tools"],apply(e,t){let n=new pe(e,t);G(e,t.threadId,{name:"compaction (summarize)",plan:s=>n.plan(s)})}},pe=class{strategy;threshold;threadId;agentName;reportOnce;estimates=new Map;overflowParts=new Map;counted=new Map;ctx;constructor(t,n){this.ctx=t,this.strategy=n.strategy,this.threshold=n.threshold,this.threadId=n.threadId,this.agentName=n.agentName,this.reportOnce=J(t)}plan(t){let{strategy:n}=this,{trigger:s,route:r}=t,o=null;if(s==="request"){let _=Ae.safeParse(t.options??null);if(!_.success)return{kind:"fail",reason:`invalid compaction options: ${_.error.message}`};o=_.data?.focus??null}let a=this.ctx.journal.state(wt,this.threadId);if(s==="pressure"&&a.unusableInARow>=n.breaker)return{kind:"skip",reason:`the summarizer failed ${a.unusableInARow} times in a row; pressure no longer compacts until a summary is recorded or the thread is configured again`};if(s==="overflow"&&a.overflowReplaced)return{kind:"skip",reason:"this overflow sequence already had its recovery; a new turn or a completed reply allows another"};let i=this.ctx.llm.capacity(r).contextWindow;if(s==="pressure"&&i===null)return this.reportOnce(`window:${he(r)}`,`Thread ${this.threadId}: ${he(r)} declares no context window, so it is never compacted for pressure`),{kind:"skip",reason:"the route declares no context window"};let c=this.snapshot(t),l=this.factorFor(r,c.head,a),w=this.measurementOn(r,c.head,a),k=w?.scale??null,g=tt(c.entries,c.estimates,w?.anchor??null);if(s==="pressure"){let _=Xe({entries:g,head:c.head,claimed:c.claimed,route:{window:i,factor:l,scale:k}});if(a.overflowReplaced&&_<=i-n.replyReserve)return{kind:"skip",reason:"the overflow recovery planned this request; pressure resumes after the next finished reply"};if(_<=this.threshold*i)return{kind:"skip",reason:`the request is estimated at ${st(_/i)} of the window, under the threshold`}}let f,d;try{f=yt(this.ctx.llm.resolveRoute(kt(n.summarizer),r),n),d=this.ctx.llm.capacity(f)}catch(_){let q=`the summarizer route cannot be resolved: ${se(_)}`;return s==="request"?{kind:"fail",reason:q}:(this.reportOnce(`summarizer:${q}`,`Thread ${this.threadId}: cannot compact (${s}): ${q}`),{kind:"skip",reason:q})}let y=f.thinking_effort!=="none",x=this.shape(c,g),E=Ue({quoteChars:n.boundaryQuoteChars,cap:n.summaryCap,focus:o}),z=Ye({entries:x.entries,balanced:x.balanced,openingEnd:x.openingEnd,latestInput:x.latest===null?null:{index:x.latest.index,tokens:v(le(x.latest.copied))},head:c.head,claimed:c.claimed,framing:et(Be),instruction:et(E),continuation:{window:i,factor:l,scale:k},summarizer:P(f,r)?{window:d.contextWindow,factor:l,scale:k,reasons:y}:{window:d.contextWindow,factor:this.factorFor(f,c.head,a),scale:null,reasons:y},budgets:{...n,threshold:this.threshold},acceptance:s==="pressure"?"threshold":"window"});return z.kind==="none"?this.noCut(t,r,z,a):this.summarize(t,{snapshot:c,shape:x,plan:z,summarizer:f,reasons:y,focus:o,window:i},a)}summarize(t,n,s){let{strategy:r}=this,{snapshot:o,shape:a,plan:i,summarizer:c}=n,l=o.entries.slice(i.start,i.end),w=i.start>0?o.entries[i.start-1]:null,k=w===null?null:{role:w.message.role,text:D(w.message)},g=ie({boundary:k,quoteChars:r.boundaryQuoteChars,merges:l.some(f=>f.type==="surface/replaced"&&f.kind==="span"),cap:i.summaryCap,focus:n.focus});return{kind:"ask",call:{through:l.at(-1).row.seq,instructions:[g],route:{provider:c.provider,model:c.model,...c.thinking_effort===null?{}:{thinkingEffort:c.thinking_effort}},toolChoice:this.ctx.llm.capacity(c).providerTools?"none":"auto",maxOutputTokens:i.summaryCap+(n.reasons?r.reasoningAllowance:0)},finish:f=>this.checkpoint(f,n,s)}}checkpoint(t,n,s){let{strategy:r}=this,{snapshot:o,shape:a,plan:i}=n,c=o.entries.slice(i.start,i.end);if("failure"in t)return this.unusable(`the summary call failed: ${se(t.failure)}`,s);let{reply:l}=t,w=i.copiesInput?a.latest.copied:null,k=l.text.trim(),g=xt(a,i.start,i.end),f=ce({summary:k,copied:w,replaced:g,recall:this.recallLine(g.first,g.count)}),d=i.summaryCap+(n.reasons?r.reasoningAllowance:0),y=l.usage!==null?{tokens:Math.max(0,l.usage.output_tokens-l.usage.reasoning_output_tokens),limit:i.summaryCap,what:"its cap"}:n.reasons?{tokens:v(k),limit:d,what:"its generation limit"}:null,x=bt(l,y);return x!==null?this.unusable(x,s):{kind:"replace",replacements:[{kind:"span",stand_in:{role:"user",content:f},source:Pe.record({summary_cap:i.summaryCap,target_reached:i.targetReached}),source_seqs:c.map(E=>E.row.seq),auxiliary_request_seq:l.requestSeq}],reason:$t(i,g,n.window)}}recallLine(t,n){return Q(this.ctx,this.agentName)?j(t,n):null}unusable(t,n){let s=n.unusableInARow+1,r=s>=this.strategy.breaker?`; after ${s} in a row, pressure no longer compacts until a summary is recorded`:"";return{kind:"fail",reason:`unusable summary, nothing replaced: ${t}${r}`,facts:[We.record({reason:t})]}}noCut(t,n,s,r){let o=s.cause==="nothing-to-replace"||s.cause==="no-reduction";return t.trigger==="request"?{kind:o?"skip":"fail",reason:s.reason}:(this.reportOnce(`cut:${t.trigger}:${s.cause}:${he(n)}:${r.latestReplacement??0}`,`Thread ${this.threadId}: cannot compact (${t.trigger}): ${s.reason}`),{kind:"skip",reason:s.reason})}snapshot(t){let{journal:n}=this.ctx,s=[...n.state(A,this.threadId).surface.entries],r=s.map(a=>this.estimateOf(a)),o=V(this.ctx,this.threadId,this.agentName);return{entries:s,estimates:r,head:o,claimed:Y(t)}}factorFor(t,n,s){let r=this.ctx.llm.capacity(t).contextWindow;if(r===null)return 1;let o=1;for(let a of s.overflows){if(!P(a,t))continue;let i=this.overflowParts.get(a.seq);if(i===void 0){let c=a.measured!==null&&P(a.measured,a)?a.measured:null,l=0,w=0,k=this.sentWith(a.seq),g=k.map(f=>this.estimateOf(f));for(let f of tt(k,g,c))c!==null&&de(f)?l+=f.tokens:w+=f.tokens;i={measured:c,counted:l,rest:w},this.overflowParts.set(a.seq,i)}o=Ze(o,r,i.measured===null?{measuredTokens:null,estimated:n+i.rest}:{measuredTokens:this.scaleOf(i.measured,n)*(n+i.counted),estimated:i.rest})}return o}measurementOn(t,n,s){let{measured:r}=s;return r===null||!P(r,t)?null:{anchor:r,scale:this.scaleOf(r,n)}}scaleOf(t,n){let s=this.counted.get(t.seq);s===void 0&&(s=this.sentWith(t.seq).reduce((o,a)=>o+this.estimateOf(a).tokens,0),this.counted.set(t.seq,s));let r=n+s;return r>0?t.tokens/r:1}sentWith(t){let n=this.ctx.journal.eventAt(t)?.thread_id??this.threadId;return this.ctx.journal.stateAt(Oe("surface"),n,t).entries}estimateOf(t){let n=this.estimates.get(t.row.seq);if(n===void 0){let s=this.ctx.journal.eventAt(t.row.seq);n={tokens:R(t.message),retold:s?.type==="input/message"&&s.data.source!==null&&s.data.input_id===null},this.estimates.set(t.row.seq,n)}return n}shape(t,n){let{journal:s}=this.ctx,{entries:r}=t,a=s.lineage(this.threadId).filter(d=>d.type==="input/message"&&d.data.role==="user"&&d.data.source===null),i=a[0]?.seq,c=a.at(-1),l=r.map(d=>d.type==="surface/replaced"?qe(s,d.row):[d.row]),w=B(s,this.threadId),k=r.findIndex((d,y)=>(d.type!=="surface/replaced"||d.kind==="rewrite")&&l[y][0]?.seq===i),g=c===void 0?-1:l.findIndex(d=>d.some(y=>y.seq===c.seq));return{entries:r.map((d,y)=>({...n[y],directDeveloperInput:d.directDeveloperInput,retold:t.estimates[y].retold})),balanced:Array.from({length:r.length+1},(d,y)=>Te(r,y)),openingEnd:i===void 0||k<0?null:k,latest:c===void 0||g<0||c.type!=="input/message"?null:{index:g,copied:Ge(c.data.content,w.get(c.seq),this.strategy.copiedInputChars)},originals:l,numbers:w}}},et=e=>R(H({role:"user",content:e})),kt=({provider:e,model:t})=>({...e===void 0?{}:{provider:e},...t===void 0?{}:{model:t}});function yt(e,t){let n=e.thinking_effort,s=t.summarizer.thinkingEffort;if(n===null)return e;let r=ne.indexOf(s)<ne.indexOf(n)?s:n;return{...e,thinking_effort:r}}function xt(e,t,n){let s=e.originals.slice(t,n).flatMap(r=>r.map(o=>e.numbers.get(o.seq)));return{first:s.reduce((r,o)=>Math.min(r,o)),last:s.reduce((r,o)=>Math.max(r,o)),count:s.length}}function bt(e,t){return e.message.tool_calls.length>0?"it asked for a tool call":e.message.provider_calls.length>0?"the provider ran a tool for it":e.finish!=="completed"?`it did not finish (${e.finish})`:e.text.trim()===""?"it returned no text":t!==null&&t.tokens>t.limit?`it is longer than ${t.what} of ${t.limit} tokens`:null}function $t(e,t,n){let s=t.first===t.last?`message ${t.first}`:`messages ${t.first} to ${t.last}`;if(n===null)return`replaced ${s} with a checkpoint; the route declares no window, so the next request is estimated at ${Math.round(e.continuation)} tokens`;let r=st(e.continuation/n);return e.targetReached?`replaced ${s} with a checkpoint; the next request is estimated at ${r} of the window, within the target`:`replaced ${s} with a checkpoint; the next request is estimated at ${r} of the window, above the target`}var st=e=>`${Math.round(e*100)}%`,he=e=>`${e.provider}/${e.model}`;function tt(e,t,n){return e.map((s,r)=>({tokens:t[r].tokens,measured:n!==null&&s.row.seq<=n.seq,written:s.type==="surface/replaced"||t[r].retold}))}var _t=Se({id:"compaction#2",placement:"thread",schema:ze,setup(e,t,n){vt(e,n.thread.id,n.thread.agentName,t)}});function vt(e,t,n,s){let{strategy:r,threshold:o}=s;return r.kind==="summarize"?e.plugin(nt,{threadId:t,agentName:n,threshold:o,strategy:r}):e.plugin(Le,{threadId:t,agentName:n,threshold:o,strategy:r})}export{_t as compaction};
@@ -0,0 +1,61 @@
1
+ import type { ExtensionRecord, Seq } from '../../models/index.js';
2
+ /** A provider and model: what a usage measurement and a calibration factor belong to, effort aside. */
3
+ export type ModelKey = {
4
+ readonly provider: string;
5
+ readonly model: string;
6
+ };
7
+ /** Whether two routes run on the same provider and model, whatever their efforts. */
8
+ export declare const sameModel: (left: ModelKey, right: ModelKey) => boolean;
9
+ /**
10
+ * The last request the provider measured, as its reply's usage says: the input it counted, cached
11
+ * tokens included, plus the reply, which is on the surface now, less reasoning a route does not
12
+ * send back. It counted the head and every surface row at or before the reply's row; those rows keep
13
+ * its scale until a newer measurement replaces it, whatever is replaced around them. Usable only on
14
+ * the same provider and model.
15
+ */
16
+ export type UsageAnchor = ModelKey & {
17
+ /** The reply's `assistant/message` row: every surface entry at or before it is measured. */
18
+ readonly seq: Seq;
19
+ readonly tokens: number;
20
+ };
21
+ /** A request the provider refused as longer than its window, and what was measured when it was sent. */
22
+ export type OverflowRecord = ModelKey & {
23
+ /** The `assistant/attempt` row whose `failure_kind` is `overflow`. */
24
+ readonly seq: Seq;
25
+ /** The measurement in force when it was sent. */
26
+ readonly measured: UsageAnchor | null;
27
+ };
28
+ /** What the compaction strategy measures from, folded over a thread's lineage. */
29
+ export type CompactionLog = {
30
+ /** The route of each request whose reply has not come back yet, by its `llm_call_id`. */
31
+ pending: Map<string, ModelKey>;
32
+ /**
33
+ * The latest reply that was not cut off and carried usage of some positive count, on a known
34
+ * route; replaced only by a newer one, never by a replacement or a cut-off reply, since the rows it
35
+ * counted stay counted.
36
+ */
37
+ measured: UsageAnchor | null;
38
+ /**
39
+ * Overflows since the latest measurement on their own provider and model, oldest first: what the
40
+ * calibration factor for that model is folded from. A measurement on the model clears its overflows.
41
+ */
42
+ overflows: OverflowRecord[];
43
+ /**
44
+ * Whether this strategy already recorded a replacement on the `overflow` trigger in the current
45
+ * overflow sequence, which a turn's start and a reply that was not cut off begin.
46
+ */
47
+ overflowReplaced: boolean;
48
+ /** The latest `surface/replaced` row, by anyone; `null` when none. */
49
+ latestReplacement: Seq | null;
50
+ /**
51
+ * Unusable summaries since this strategy's latest checkpoint and the thread's latest change of
52
+ * installations: what its breaker counts.
53
+ */
54
+ unusableInARow: number;
55
+ };
56
+ /**
57
+ * The fold the strategy measures pressure from, keyed by `source` so two strategies' logs never
58
+ * share a key. Thread-scoped and inherited by forks: a fork's surface is its source's, and so are
59
+ * the measurements that describe it.
60
+ */
61
+ export declare function compactionLog(source: Pick<ExtensionRecord, 'plugin' | 'instance_id' | 'kind'>, unusable?: Pick<ExtensionRecord, 'kind'> | null): import("../../journal/projection.js").PluginProjection<CompactionLog>;
@@ -0,0 +1,207 @@
1
+ import type { SummarizeStrategyConfig } from './config.js';
2
+ /**
3
+ * The planner and the measurement it plans from: pure functions of their inputs, with no journal,
4
+ * no registry and no model, so every rule here is tested by handing it numbers.
5
+ *
6
+ * Token figures are estimates unless said otherwise, priced per route before they meet a window;
7
+ * the reasoning allowance and the reply reserve are tokens already and never scaled. A route with
8
+ * a usage measurement prices at that measurement's scale the head, every row it counted and every
9
+ * written text (stand-ins, notices, the framing, the instruction, the copied input), see
10
+ * {@link countedAtScale}; every other row, and the claimed input, which is recorded as such a row,
11
+ * at its calibration `factor`. The checkpoint is priced as the next step will price its stand-in,
12
+ * the summary at its cap; the summary call reserves the same cap as generation tokens, which is what
13
+ * bounds the summary. The stand-in is later estimated from its characters, which may differ from
14
+ * the provider's count by the tokenizer's ratio; the reply reserve, the slack between the plan's
15
+ * ceiling and the threshold the next check fires at, absorbs that.
16
+ */
17
+ /** One surface message as the planner sees it. */
18
+ export type PlannerEntry = {
19
+ /** Its estimated tokens, unscaled. */
20
+ readonly tokens: number;
21
+ /** A `developer` `input/message` with no `source`: no span may contain it, so it divides segments. */
22
+ readonly directDeveloperInput: boolean;
23
+ /**
24
+ * A sourced `input/message` a plugin contributed at a step: replacing it may make its plugin tell
25
+ * it again, so its size is reserved in the continuation of any span that holds it. Sourced input a
26
+ * plugin queued, such as an agent's notice, is not: its id is spent once queued.
27
+ */
28
+ readonly retold: boolean;
29
+ /** A usage measurement on the turn's provider and model counted it: its row is at or before the measured reply. */
30
+ readonly measured: boolean;
31
+ /** Written text: a stand-in a strategy wrote, or a plugin's contributed `input/message`. */
32
+ readonly written: boolean;
33
+ };
34
+ /** What pricing reads of an entry: its estimate, and how it was counted. */
35
+ export type PricedEntry = Pick<PlannerEntry, 'tokens' | 'measured' | 'written'>;
36
+ /**
37
+ * Whether an entry is priced at a route's measurement scale when the route has one: a measurement
38
+ * counted it, or it is written text, which the measured scale describes better than an overflow's
39
+ * factor. The one partition request pricing, the planner and calibration all use; everything else
40
+ * is priced at the factor.
41
+ */
42
+ export declare const countedAtScale: (entry: Pick<PricedEntry, "measured" | "written">) => boolean;
43
+ /**
44
+ * A route as the budgets read it: its declared window, `null` when none; its calibration factor;
45
+ * and the scale of its last usage measurement, `null` when it has none usable.
46
+ */
47
+ export type RouteBudget = {
48
+ readonly window: number | null;
49
+ readonly factor: number;
50
+ /**
51
+ * What the provider counted over the estimate of what it counted, the head included: the scale
52
+ * the head and every entry {@link countedAtScale} are priced at, and written text. `null` prices
53
+ * everything at `factor`.
54
+ */
55
+ readonly scale: number | null;
56
+ };
57
+ /** The configured budgets the planner reads; see `SummarizeStrategySchema` and `threshold` for each. */
58
+ export type PlanBudgets = Pick<SummarizeStrategyConfig, 'target' | 'tail' | 'opening' | 'summaryCap' | 'summaryFloor' | 'reasoningAllowance' | 'replyReserve' | 'checkpointRatio' | 'withoutWindow'> & {
59
+ readonly threshold: number;
60
+ };
61
+ /** Everything one plan is made from: the surface as estimates, the routes, and the budgets. */
62
+ export type PlannerInput = {
63
+ readonly entries: readonly PlannerEntry[];
64
+ /** `balanced[i]`: the surface can be cut just before `entries[i]`; one longer than `entries`. */
65
+ readonly balanced: readonly boolean[];
66
+ /**
67
+ * The index of the first unsourced `user` input, which ends the opening the planner pins when it
68
+ * fits its budget; `null` when the surface holds none as itself, which pins nothing.
69
+ */
70
+ readonly openingEnd: number | null;
71
+ /** Where the person's latest input is, and what copying it into a checkpoint costs, unscaled. */
72
+ readonly latestInput: {
73
+ readonly index: number;
74
+ readonly tokens: number;
75
+ } | null;
76
+ /** The prompt, guidance and tool definitions every request sends first, unscaled. */
77
+ readonly head: number;
78
+ /** The input this step will record after the replacement, unscaled. */
79
+ readonly claimed: number;
80
+ /** A checkpoint's code-written text, preamble and footer, with an empty summary, unscaled. */
81
+ readonly framing: number;
82
+ /** The summary instruction, unscaled. */
83
+ readonly instruction: number;
84
+ /** The turn's route: what the request after the compaction is sent on. */
85
+ readonly continuation: RouteBudget;
86
+ /** The summary call's route, and whether it reasons, which adds the reasoning allowance. */
87
+ readonly summarizer: RouteBudget & {
88
+ readonly reasons: boolean;
89
+ };
90
+ readonly budgets: PlanBudgets;
91
+ /**
92
+ * What a plan must fit when nothing fits under the threshold less the reply reserve. `threshold`,
93
+ * for pressure: under the window less the reserve only when another segment remains for the next
94
+ * step to take. `window`, for an overflow or a request, which no later pressure check finishes:
95
+ * under the window less the reserve, whatever remains.
96
+ */
97
+ readonly acceptance: 'threshold' | 'window';
98
+ };
99
+ /** A span to replace with a checkpoint, and what the replacement is estimated to leave. */
100
+ export type CompactionPlan = {
101
+ readonly kind: 'plan';
102
+ /** The span: `entries[start]` up to, not including, `entries[end]`. */
103
+ readonly start: number;
104
+ readonly end: number;
105
+ /** How many leading entries are the pinned opening, which no span touches. */
106
+ readonly pinned: number;
107
+ /**
108
+ * The most the summary may come to, in generation tokens: the `maxOutputTokens` before the
109
+ * allowance, and what the plan priced the summary at in the checkpoint. The recorded stand-in is
110
+ * estimated from its characters and may differ by the tokenizer's ratio, which the reserve absorbs.
111
+ */
112
+ readonly summaryCap: number;
113
+ /** Whether the span holds the person's latest input, which the checkpoint then copies. */
114
+ readonly copiesInput: boolean;
115
+ /** The span's estimate, scaled. */
116
+ readonly spanTokens: number;
117
+ /**
118
+ * The request after the replacement as the next step will price it, the checkpoint's summary at
119
+ * its cap at the written scale, without the reply reserve.
120
+ */
121
+ readonly continuation: number;
122
+ /** The summary call, scaled, with its whole generation reserve. */
123
+ readonly summaryCall: number;
124
+ /** Whether the continuation and its reply reserve fit under the target; `null` on a route with no window. */
125
+ readonly targetReached: boolean | null;
126
+ /** Which segment, counting from the oldest, of how many. */
127
+ readonly segment: {
128
+ readonly index: number;
129
+ readonly count: number;
130
+ };
131
+ };
132
+ /** Why no span is worth replacing; every room is judged against the summary floor. */
133
+ export type NoPlanCause =
134
+ /** No segment has a balanced span that keeps the newest message, or holds more than written text. */
135
+ 'nothing-to-replace'
136
+ /** No span's summary call leaves room for the floor in the summarizer's window. */
137
+ | 'summary-call-too-large'
138
+ /** No span leaves room for the floor under the continuation's ceiling, its reply reserve counted. */
139
+ | 'continuation-too-large'
140
+ /**
141
+ * Some span leaves room for the floor under both budgets, but not under the reduction it must
142
+ * make, its checkpoint and re-told notices counted: nothing is worth doing.
143
+ */
144
+ | 'no-reduction'
145
+ /**
146
+ * Each budget alone admits some span, but no span fits both: the summary call fits only spans
147
+ * too short to leave the continuation room.
148
+ */
149
+ | 'no-span-fits-both';
150
+ /** No plan: why, as a cause a strategy can act on and a reason a person can read. */
151
+ export type NoPlan = {
152
+ readonly kind: 'none';
153
+ readonly cause: NoPlanCause;
154
+ readonly reason: string;
155
+ };
156
+ /** What `planCompaction` answers: a plan, or why there is none. */
157
+ export type PlanOutcome = CompactionPlan | NoPlan;
158
+ /**
159
+ * Plans one compaction: which balanced span to replace with a checkpoint, and how long the summary
160
+ * in it may be, so that both the summary call and the request after it fit; or why none can.
161
+ *
162
+ * - **The opening is pinned**: every message through the first unsourced `user` input, when together
163
+ * they fit the opening budget, is never in a span.
164
+ * - **Direct developer inputs divide segments**, each compacted on its own. An earlier segment is
165
+ * replaced whole; only the last keeps a tail, which keeps the newest message.
166
+ * - **Retention proposes the cut**: walking back from the newest message until the tail reaches the
167
+ * tail budget, then widening it to a balanced cut.
168
+ * - **Two budgets settle it.** The summary call (the head, the surface through the end of the span,
169
+ * the instruction and the generation reserve) must fit the summarizer's window; the continuation
170
+ * (the head, the surface as the replacement leaves it, the checkpoint at its cap, the notices the
171
+ * span makes plugins tell again and the claimed input) must stay under the acceptance ceiling:
172
+ * the threshold less the reply reserve, or, when nothing fits that, the window less it as
173
+ * `acceptance` allows. The summary cap is the configured cap, lowered to what both leave and to
174
+ * what the reduction leaves, the checkpoint and its re-tells within the configured ratio of the
175
+ * span; a candidate whose cap ends below the summary floor is discarded.
176
+ * - **Feasibility first, then the target.** Among feasible candidates, those that bring the
177
+ * continuation and its reply reserve under the target come first, and in the last segment the one
178
+ * nearest the retention cut, the larger tail on a tie; with none, the largest reduction. Across
179
+ * segments, a candidate reaching the target first, then the largest reduction.
180
+ *
181
+ * On a route with no window the opening and tail budgets are the configured absolute ones, nothing
182
+ * has a ceiling, and every feasible candidate counts as aimed: the outcome is a reduction, not a fit.
183
+ */
184
+ export declare function planCompaction(input: PlannerInput): PlanOutcome;
185
+ /**
186
+ * The size of the request about to be sent on `route`, priced as the planner prices a
187
+ * continuation: the head, the surface and the claimed input, each at its scale. One computation, so
188
+ * a pressure check after a replacement prices the rows that survived it as the plan did.
189
+ */
190
+ export declare function estimateRequest(input: {
191
+ readonly entries: readonly PricedEntry[];
192
+ readonly head: number;
193
+ readonly claimed: number;
194
+ readonly route: RouteBudget;
195
+ }): number;
196
+ /**
197
+ * The calibration factor after a request the provider refused as longer than its `window`: that
198
+ * request was at least the window, so the estimated part of it was low by at least the window, less
199
+ * any measured part, over that estimate. Never below one, and never below `previous`, the factor in
200
+ * force, until a usage anchor replaces it: a request sent already estimated above the window proves
201
+ * nothing about the estimator, and a factor below one would make a recovery less careful than the
202
+ * attempt. No count is ever read from the provider's message; this bound is the measurement.
203
+ */
204
+ export declare function calibrate(previous: number, window: number, failed: {
205
+ readonly measuredTokens: number | null;
206
+ readonly estimated: number;
207
+ }): number;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The compaction plugin, a `thread` preset with two placements, which keeps a thread's surface
3
+ * within its route's window by the strategy its configuration names. Mounted on the root for an
4
+ * agent selector, `mountPreset(root, compaction, config, { agents })`, it serves every thread whose
5
+ * agent `agents` selects: each matching activation gets its own strategy, provided in the thread's
6
+ * scope, until the mount is disposed. Installed on one thread through the presets service, it
7
+ * serves that thread, recorded so a reopen and a fork keep it.
8
+ *
9
+ * Both strategies act on three triggers: **pressure**, before every model step whose request is
10
+ * estimated above `threshold` of the window (a route whose provider declares no window is never
11
+ * compacted for pressure, which is reported once per route); **overflow**, when the provider
12
+ * refuses a step's request as too long, after which the step is asked again if anything was
13
+ * replaced; and **request**, `thread.compact()`, whatever the pressure.
14
+ *
15
+ * - **`summarize`**, the default. It replaces one span, after the pinned opening and between direct
16
+ * developer inputs, with one `user` checkpoint: notes a summary call wrote from the surface
17
+ * through the span, the person's latest input copied from its row when the span held it, and a
18
+ * footer naming the messages replaced. It measures from the last usage the provider reported on
19
+ * the same provider and model plus an estimate of what came since, calibrates its estimates by
20
+ * an overflow, and recovers once per overflow sequence: a new turn or a completed reply allows
21
+ * another. Three unusable summaries in a row stop pressure compaction until its next
22
+ * checkpoint or a change of the thread's configuration; the count is recorded, so a reopen and a
23
+ * fork keep it. On request, `options` may say what the summary should `focus` on.
24
+ * - **`prune`**. It rewrites old tool results in place, keeping each one's role and call id, to a
25
+ * one-line stand-in, `[tool result pruned: <tool>, <n> characters and <k> attachments; message
26
+ * <number>]`, the attachments named only when it had some, followed by where to read it back when
27
+ * the agent has both `historyRecall` tools; no model is called. A result is pruned when it is an
28
+ * original, never a stand-in, outside the `keepRecent` most recent tool results, and estimated at
29
+ * `minTokens` or more, images and files included; every such result goes in one atomic group.
30
+ * Pressure is estimated by characters, uncalibrated. Nothing eligible is `skipped`, reported once
31
+ * per activation, trigger, route and latest replacement on pressure and overflow. It takes no
32
+ * request options and ignores any.
33
+ *
34
+ * Plugins whose notices a replacement took away tell them again at the next model step.
35
+ *
36
+ * Disposing a root mount stops new dispatches on the threads it serves, live ones included; a
37
+ * dispatch already in flight finishes, and may still record its replacement. A mount added later
38
+ * reaches activations from then on, not threads already live: they get it at their next activation.
39
+ *
40
+ * A thread runs one strategy, and a second on it, from another mount of this plugin or any other
41
+ * strategy that claims its thread, is refused when the thread activates, naming the one already
42
+ * there. To choose per agent, mount this on the root more than once with disjoint selectors and the
43
+ * strategy each should run; to choose per thread, mount none on the root and install it on each
44
+ * thread instead.
45
+ *
46
+ * ```ts
47
+ * await mountPreset(root, compaction, {}, { agents: ['main'] }) // summarize, with every default
48
+ * await mountPreset(root, compaction, { strategy: { kind: 'prune', keepRecent: 4 } }, { agents: ['worker'] })
49
+ * ```
50
+ */
51
+ export declare const compaction: import("../../services/preset.js").Preset<import("zod").ZodObject<{
52
+ threshold: import("zod").ZodDefault<import("zod").ZodNumber>;
53
+ strategy: import("zod").ZodPrefault<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
54
+ kind: import("zod").ZodLiteral<"summarize">;
55
+ target: import("zod").ZodDefault<import("zod").ZodNumber>;
56
+ tail: import("zod").ZodDefault<import("zod").ZodNumber>;
57
+ opening: import("zod").ZodDefault<import("zod").ZodNumber>;
58
+ summaryCap: import("zod").ZodDefault<import("zod").ZodNumber>;
59
+ summaryFloor: import("zod").ZodDefault<import("zod").ZodNumber>;
60
+ reasoningAllowance: import("zod").ZodDefault<import("zod").ZodNumber>;
61
+ replyReserve: import("zod").ZodDefault<import("zod").ZodNumber>;
62
+ checkpointRatio: import("zod").ZodDefault<import("zod").ZodNumber>;
63
+ copiedInputChars: import("zod").ZodDefault<import("zod").ZodNumber>;
64
+ boundaryQuoteChars: import("zod").ZodDefault<import("zod").ZodNumber>;
65
+ breaker: import("zod").ZodDefault<import("zod").ZodNumber>;
66
+ withoutWindow: import("zod").ZodDefault<import("zod").ZodObject<{
67
+ tailTokens: import("zod").ZodDefault<import("zod").ZodNumber>;
68
+ openingTokens: import("zod").ZodDefault<import("zod").ZodNumber>;
69
+ }, import("zod/v4/core").$strict>>;
70
+ summarizer: import("zod").ZodDefault<import("zod").ZodObject<{
71
+ provider: import("zod").ZodOptional<import("zod").ZodString>;
72
+ model: import("zod").ZodOptional<import("zod").ZodString>;
73
+ thinkingEffort: import("zod").ZodDefault<import("zod").ZodEnum<{
74
+ low: "low";
75
+ high: "high";
76
+ none: "none";
77
+ medium: "medium";
78
+ max: "max";
79
+ }>>;
80
+ }, import("zod/v4/core").$strict>>;
81
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
82
+ kind: import("zod").ZodLiteral<"prune">;
83
+ keepRecent: import("zod").ZodDefault<import("zod").ZodNumber>;
84
+ minTokens: import("zod").ZodDefault<import("zod").ZodNumber>;
85
+ }, import("zod/v4/core").$strict>], "kind">>;
86
+ }, import("zod/v4/core").$strict>>;
@@ -0,0 +1,9 @@
1
+ import type { Plugin } from '@leuduan/cordis';
2
+ import type { PruneStrategyConfig, StrategyOptions } from './config.js';
3
+ /**
4
+ * The `prune` strategy on one thread, provided from the thread's own scope; a second strategy on the
5
+ * thread, this one again or another, is refused, the later of the two. It rewrites old tool results to a one-line stand-in and calls no
6
+ * model, the read-time counterpart of `truncateToolOutput`. Its reports last one activation;
7
+ * everything it decides from is the surface.
8
+ */
9
+ export declare const pruneStrategy: Plugin.Object<StrategyOptions<PruneStrategyConfig>>;