@pentoshi/clai 4.1.0 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/README.md +14 -0
  2. package/dist/agent/compaction-executor.d.ts +68 -0
  3. package/dist/agent/compaction-executor.js +343 -0
  4. package/dist/agent/compaction-executor.js.map +1 -0
  5. package/dist/agent/context-breakdown.js +2 -0
  6. package/dist/agent/context-breakdown.js.map +1 -1
  7. package/dist/agent/context-manager.d.ts +23 -9
  8. package/dist/agent/context-manager.js +72 -43
  9. package/dist/agent/context-manager.js.map +1 -1
  10. package/dist/agent/events.d.ts +3 -0
  11. package/dist/agent/loop-guard.d.ts +2 -0
  12. package/dist/agent/loop-guard.js +48 -3
  13. package/dist/agent/loop-guard.js.map +1 -1
  14. package/dist/agent/prompt-composer.js +6 -6
  15. package/dist/agent/prompt-composer.js.map +1 -1
  16. package/dist/agent/reliability-policy.d.ts +1 -0
  17. package/dist/agent/reliability-policy.js +6 -3
  18. package/dist/agent/reliability-policy.js.map +1 -1
  19. package/dist/agent/request-accounting.d.ts +97 -0
  20. package/dist/agent/request-accounting.js +207 -0
  21. package/dist/agent/request-accounting.js.map +1 -0
  22. package/dist/agent/request-budget.d.ts +2 -2
  23. package/dist/agent/request-budget.js +2 -4
  24. package/dist/agent/request-budget.js.map +1 -1
  25. package/dist/agent/runner.d.ts +8 -2
  26. package/dist/agent/runner.js +409 -178
  27. package/dist/agent/runner.js.map +1 -1
  28. package/dist/agent/session-title.d.ts +0 -26
  29. package/dist/agent/session-title.js +0 -80
  30. package/dist/agent/session-title.js.map +1 -1
  31. package/dist/agent/tool-history.d.ts +2 -2
  32. package/dist/agent/tool-history.js +19 -6
  33. package/dist/agent/tool-history.js.map +1 -1
  34. package/dist/app/adapters/agent-event-adapter.js +19 -0
  35. package/dist/app/adapters/agent-event-adapter.js.map +1 -1
  36. package/dist/app/adapters/current-agent-adapter.js +4 -0
  37. package/dist/app/adapters/current-agent-adapter.js.map +1 -1
  38. package/dist/app/commands/catalog.js +24 -0
  39. package/dist/app/commands/catalog.js.map +1 -1
  40. package/dist/app/controllers/cancel-coordinator.d.ts +51 -0
  41. package/dist/app/controllers/cancel-coordinator.js +48 -0
  42. package/dist/app/controllers/cancel-coordinator.js.map +1 -0
  43. package/dist/app/controllers/session-compact-helper.d.ts +19 -2
  44. package/dist/app/controllers/session-compact-helper.js +100 -127
  45. package/dist/app/controllers/session-compact-helper.js.map +1 -1
  46. package/dist/app/controllers/session-context-usage.d.ts +32 -15
  47. package/dist/app/controllers/session-context-usage.js +186 -51
  48. package/dist/app/controllers/session-context-usage.js.map +1 -1
  49. package/dist/app/controllers/session-controller.d.ts +20 -11
  50. package/dist/app/controllers/session-controller.js +111 -90
  51. package/dist/app/controllers/session-controller.js.map +1 -1
  52. package/dist/app/controllers/session-naming.d.ts +31 -0
  53. package/dist/app/controllers/session-naming.js +173 -0
  54. package/dist/app/controllers/session-naming.js.map +1 -0
  55. package/dist/app/controllers/session-persistence.d.ts +2 -2
  56. package/dist/app/controllers/session-persistence.js +3 -6
  57. package/dist/app/controllers/session-persistence.js.map +1 -1
  58. package/dist/app/controllers/session-turn-request.d.ts +2 -1
  59. package/dist/app/controllers/session-turn-request.js +3 -0
  60. package/dist/app/controllers/session-turn-request.js.map +1 -1
  61. package/dist/app/controllers/turn-controller.d.ts +2 -1
  62. package/dist/app/controllers/turn-controller.js +1 -0
  63. package/dist/app/controllers/turn-controller.js.map +1 -1
  64. package/dist/app/events/app-event.d.ts +9 -0
  65. package/dist/app/events/app-event.js.map +1 -1
  66. package/dist/app/ports/agent-port.d.ts +8 -1
  67. package/dist/classic/app/ClassicApp.js +2 -1
  68. package/dist/classic/app/ClassicApp.js.map +1 -1
  69. package/dist/classic/app/app-wiring.js +1 -2
  70. package/dist/classic/app/app-wiring.js.map +1 -1
  71. package/dist/classic/app/wiring-interactions.js +2 -7
  72. package/dist/classic/app/wiring-interactions.js.map +1 -1
  73. package/dist/classic/blocks/tool-lines.js +2 -1
  74. package/dist/classic/blocks/tool-lines.js.map +1 -1
  75. package/dist/classic/input/cancel-ladder.d.ts +2 -19
  76. package/dist/classic/input/cancel-ladder.js +13 -20
  77. package/dist/classic/input/cancel-ladder.js.map +1 -1
  78. package/dist/commands/providers.js +2 -0
  79. package/dist/commands/providers.js.map +1 -1
  80. package/dist/llm/adapters/anthropic-tools.d.ts +31 -14
  81. package/dist/llm/adapters/anthropic-tools.js +124 -29
  82. package/dist/llm/adapters/anthropic-tools.js.map +1 -1
  83. package/dist/llm/adapters/gemini-tools.d.ts +16 -4
  84. package/dist/llm/adapters/gemini-tools.js +117 -16
  85. package/dist/llm/adapters/gemini-tools.js.map +1 -1
  86. package/dist/llm/adapters/openai-tools.d.ts +13 -2
  87. package/dist/llm/adapters/openai-tools.js +58 -11
  88. package/dist/llm/adapters/openai-tools.js.map +1 -1
  89. package/dist/llm/agentrouter.js +68 -45
  90. package/dist/llm/agentrouter.js.map +1 -1
  91. package/dist/llm/anthropic.js +69 -36
  92. package/dist/llm/anthropic.js.map +1 -1
  93. package/dist/llm/aws-mantle.js +70 -32
  94. package/dist/llm/aws-mantle.js.map +1 -1
  95. package/dist/llm/bynara.js +26 -69
  96. package/dist/llm/bynara.js.map +1 -1
  97. package/dist/llm/capabilities.d.ts +2 -1
  98. package/dist/llm/capabilities.js +47 -0
  99. package/dist/llm/capabilities.js.map +1 -1
  100. package/dist/llm/context-snapshot.d.ts +100 -0
  101. package/dist/llm/context-snapshot.js +277 -0
  102. package/dist/llm/context-snapshot.js.map +1 -0
  103. package/dist/llm/context-windows.d.ts +10 -0
  104. package/dist/llm/context-windows.js +129 -0
  105. package/dist/llm/context-windows.js.map +1 -0
  106. package/dist/llm/custom-provider-profile.d.ts +75 -0
  107. package/dist/llm/custom-provider-profile.js +558 -0
  108. package/dist/llm/custom-provider-profile.js.map +1 -0
  109. package/dist/llm/custom-providers.d.ts +13 -1
  110. package/dist/llm/custom-providers.js +77 -25
  111. package/dist/llm/custom-providers.js.map +1 -1
  112. package/dist/llm/effort-fallback.d.ts +44 -0
  113. package/dist/llm/effort-fallback.js +101 -0
  114. package/dist/llm/effort-fallback.js.map +1 -0
  115. package/dist/llm/fireworks.js +4 -0
  116. package/dist/llm/fireworks.js.map +1 -1
  117. package/dist/llm/free.js +4 -0
  118. package/dist/llm/free.js.map +1 -1
  119. package/dist/llm/gemini.d.ts +1 -1
  120. package/dist/llm/gemini.js +89 -51
  121. package/dist/llm/gemini.js.map +1 -1
  122. package/dist/llm/groq.js +4 -0
  123. package/dist/llm/groq.js.map +1 -1
  124. package/dist/llm/hetzner.js +4 -0
  125. package/dist/llm/hetzner.js.map +1 -1
  126. package/dist/llm/http.d.ts +49 -10
  127. package/dist/llm/http.js +417 -153
  128. package/dist/llm/http.js.map +1 -1
  129. package/dist/llm/kimchi.js +4 -0
  130. package/dist/llm/kimchi.js.map +1 -1
  131. package/dist/llm/lightning.js +4 -0
  132. package/dist/llm/lightning.js.map +1 -1
  133. package/dist/llm/meta.d.ts +2 -0
  134. package/dist/llm/meta.js +811 -655
  135. package/dist/llm/meta.js.map +1 -1
  136. package/dist/llm/modal.js +4 -0
  137. package/dist/llm/modal.js.map +1 -1
  138. package/dist/llm/model-families.d.ts +9 -0
  139. package/dist/llm/model-families.js +39 -0
  140. package/dist/llm/model-families.js.map +1 -0
  141. package/dist/llm/nvidia.js +4 -0
  142. package/dist/llm/nvidia.js.map +1 -1
  143. package/dist/llm/ollama.js +44 -40
  144. package/dist/llm/ollama.js.map +1 -1
  145. package/dist/llm/openai.js +4 -0
  146. package/dist/llm/openai.js.map +1 -1
  147. package/dist/llm/openrouter.js +4 -0
  148. package/dist/llm/openrouter.js.map +1 -1
  149. package/dist/llm/operation-ledger.d.ts +60 -0
  150. package/dist/llm/operation-ledger.js +136 -0
  151. package/dist/llm/operation-ledger.js.map +1 -0
  152. package/dist/llm/operation-usage.d.ts +32 -0
  153. package/dist/llm/operation-usage.js +172 -0
  154. package/dist/llm/operation-usage.js.map +1 -0
  155. package/dist/llm/orcarouter.d.ts +7 -0
  156. package/dist/llm/orcarouter.js +166 -0
  157. package/dist/llm/orcarouter.js.map +1 -0
  158. package/dist/llm/provider-profile-layers.d.ts +7 -0
  159. package/dist/llm/provider-profile-layers.js +961 -0
  160. package/dist/llm/provider-profile-layers.js.map +1 -0
  161. package/dist/llm/provider-profile.d.ts +181 -0
  162. package/dist/llm/provider-profile.js +329 -0
  163. package/dist/llm/provider-profile.js.map +1 -0
  164. package/dist/llm/provider-profiles.d.ts +13 -0
  165. package/dist/llm/provider-profiles.js +86 -0
  166. package/dist/llm/provider-profiles.js.map +1 -0
  167. package/dist/llm/provider.d.ts +2 -0
  168. package/dist/llm/provider.js +67 -0
  169. package/dist/llm/provider.js.map +1 -1
  170. package/dist/llm/qwen-cloud.js +4 -0
  171. package/dist/llm/qwen-cloud.js.map +1 -1
  172. package/dist/llm/reasoning-artifacts.d.ts +101 -0
  173. package/dist/llm/reasoning-artifacts.js +440 -0
  174. package/dist/llm/reasoning-artifacts.js.map +1 -0
  175. package/dist/llm/request-fingerprint.d.ts +10 -0
  176. package/dist/llm/request-fingerprint.js +313 -0
  177. package/dist/llm/request-fingerprint.js.map +1 -0
  178. package/dist/llm/request-plan.d.ts +119 -0
  179. package/dist/llm/request-plan.js +279 -0
  180. package/dist/llm/request-plan.js.map +1 -0
  181. package/dist/llm/router.d.ts +19 -1
  182. package/dist/llm/router.js +447 -75
  183. package/dist/llm/router.js.map +1 -1
  184. package/dist/llm/stream-events.d.ts +47 -0
  185. package/dist/llm/stream-events.js +55 -0
  186. package/dist/llm/stream-events.js.map +1 -0
  187. package/dist/llm/stream-terminal.d.ts +30 -0
  188. package/dist/llm/stream-terminal.js +51 -0
  189. package/dist/llm/stream-terminal.js.map +1 -0
  190. package/dist/llm/token-estimate-calibration.d.ts +23 -0
  191. package/dist/llm/token-estimate-calibration.js +140 -0
  192. package/dist/llm/token-estimate-calibration.js.map +1 -0
  193. package/dist/llm/token-usage.d.ts +35 -5
  194. package/dist/llm/token-usage.js +212 -162
  195. package/dist/llm/token-usage.js.map +1 -1
  196. package/dist/llm/tokenrouter.js +8 -2
  197. package/dist/llm/tokenrouter.js.map +1 -1
  198. package/dist/modes/ask.js +11 -5
  199. package/dist/modes/ask.js.map +1 -1
  200. package/dist/noninteractive/start-noninteractive.js +31 -2
  201. package/dist/noninteractive/start-noninteractive.js.map +1 -1
  202. package/dist/noninteractive/stream-blocks.js +15 -4
  203. package/dist/noninteractive/stream-blocks.js.map +1 -1
  204. package/dist/prompts/embedded.js +1 -1
  205. package/dist/prompts/embedded.js.map +1 -1
  206. package/dist/prompts/system.agent.md +6 -0
  207. package/dist/store/config.js +5 -1
  208. package/dist/store/config.js.map +1 -1
  209. package/dist/store/history.d.ts +2 -0
  210. package/dist/store/history.js +19 -10
  211. package/dist/store/history.js.map +1 -1
  212. package/dist/store/keys.js +11 -1
  213. package/dist/store/keys.js.map +1 -1
  214. package/dist/store/plan.js +20 -14
  215. package/dist/store/plan.js.map +1 -1
  216. package/dist/tools/elevated-shell.d.ts +1 -1
  217. package/dist/tools/elevated-shell.js +24 -72
  218. package/dist/tools/elevated-shell.js.map +1 -1
  219. package/dist/tools/nmap-runner.js +30 -36
  220. package/dist/tools/nmap-runner.js.map +1 -1
  221. package/dist/tools/sudo-session.d.ts +83 -0
  222. package/dist/tools/sudo-session.js +124 -0
  223. package/dist/tools/sudo-session.js.map +1 -0
  224. package/dist/tui-v2/app/App.js +9 -24
  225. package/dist/tui-v2/app/App.js.map +1 -1
  226. package/dist/tui-v2/components/status/context-limit-chip.js +2 -2
  227. package/dist/tui-v2/components/status/context-limit-chip.js.map +1 -1
  228. package/dist/tui-v2/components/transcript/intro-card.js +2 -1
  229. package/dist/tui-v2/components/transcript/intro-card.js.map +1 -1
  230. package/dist/tui-v2/composer/composer-editor.js +2 -1
  231. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  232. package/dist/types.d.ts +156 -1
  233. package/dist/types.js +1 -0
  234. package/dist/types.js.map +1 -1
  235. package/dist/ui-core/bootstrap/composition-root.d.ts +2 -0
  236. package/dist/ui-core/bootstrap/composition-root.js +26 -3
  237. package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
  238. package/dist/ui-core/commands/picker-commands.js +11 -5
  239. package/dist/ui-core/commands/picker-commands.js.map +1 -1
  240. package/dist/ui-core/commands/session-commands.js +41 -5
  241. package/dist/ui-core/commands/session-commands.js.map +1 -1
  242. package/dist/ui-core/plan/plan-lifecycle.js +3 -2
  243. package/dist/ui-core/plan/plan-lifecycle.js.map +1 -1
  244. package/dist/ui-core/rendering/context-limit.js +4 -1
  245. package/dist/ui-core/rendering/context-limit.js.map +1 -1
  246. package/dist/ui-core/rendering/duration.d.ts +2 -1
  247. package/dist/ui-core/rendering/duration.js +13 -5
  248. package/dist/ui-core/rendering/duration.js.map +1 -1
  249. package/dist/ui-core/rendering/intro-header.js +2 -2
  250. package/dist/ui-core/rendering/intro-header.js.map +1 -1
  251. package/dist/ui-core/rendering/theme.d.ts +1 -0
  252. package/dist/ui-core/rendering/theme.js +2 -0
  253. package/dist/ui-core/rendering/theme.js.map +1 -1
  254. package/dist/ui-core/state/transcript-hydrate.js +3 -3
  255. package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
  256. package/dist/ui-core/state/transcript-reducer.d.ts +5 -0
  257. package/dist/ui-core/state/transcript-reducer.js +76 -3
  258. package/dist/ui-core/state/transcript-reducer.js.map +1 -1
  259. package/dist/ui-core/state/transcript-store.d.ts +10 -1
  260. package/dist/ui-core/state/transcript-store.js +22 -1
  261. package/dist/ui-core/state/transcript-store.js.map +1 -1
  262. package/dist/ui-core/state/transcript-types.d.ts +2 -0
  263. package/dist/ui-core/state/transcript-types.js.map +1 -1
  264. package/dist/version.generated.d.ts +2 -2
  265. package/dist/version.generated.js +2 -2
  266. package/package.json +6 -1
@@ -1,23 +1,11 @@
1
1
  /**
2
2
  * Summarizer callback used by SessionController.compact (keeps the controller slim).
3
3
  */
4
- import { buildCompactionRetryPrompt, compactionSinglePassInputBudget, COMPACTION_MAX_COMPLETION_TOKENS, COMPACTION_MAP_MAX_COMPLETION_TOKENS, isCompactionCompletionTruncated, looksLikeIncompleteCompactionSummary, looksLikeTranscriptReplay, normalizeCompactionSummary, } from "../../agent/compaction-summary.js";
4
+ import { buildDirectCompactionPrompt, compactionSinglePassInputBudget, COMPACTION_MAX_COMPLETION_TOKENS, COMPACTION_MAP_MAX_COMPLETION_TOKENS, } from "../../agent/compaction-summary.js";
5
+ import { executeCompactionSummary, planCompactionReplay, } from "../../agent/compaction-executor.js";
5
6
  import { compactMessagesWithSummary, estimateMessagesTokens, isCompactionMemoryMessage, } from "../../agent/context-manager.js";
6
- import { completeWithProvider, streamWithProvider } from "../../llm/router.js";
7
- import { streamAlreadyEmitted } from "../../llm/stream-progress.js";
8
7
  import { modelContextWindow } from "../../llm/token-usage.js";
9
- import { createThinkingStreamParser, stripThinking } from "../../ui/thinking.js";
10
- function isCompactionServerError(error) {
11
- if (streamAlreadyEmitted(error))
12
- return false;
13
- const status = error && typeof error === "object" && "status" in error
14
- ? Number(error.status)
15
- : 0;
16
- if (status >= 500 && status <= 504)
17
- return true;
18
- const message = error instanceof Error ? error.message : String(error);
19
- return /internal server error/i.test(message);
20
- }
8
+ import { OperationLedger, } from "../../llm/operation-ledger.js";
21
9
  export async function summarizeForSessionCompact(prompt, opts) {
22
10
  const maxTokens = opts.stage === "map"
23
11
  ? COMPACTION_MAP_MAX_COMPLETION_TOKENS
@@ -25,113 +13,53 @@ export async function summarizeForSessionCompact(prompt, opts) {
25
13
  const systemContent = opts.purpose === "plan-implement"
26
14
  ? "Write concise, non-redundant research memory for an agent executing an approved plan. Do not add framing: the PLAN MODE HANDOFF wrapper and active plan are injected separately. For coding target 600–1000 tokens; preserve only verified state, reusable research/artifacts, decisions, blockers, and risks. Security handoffs may be longer to preserve findings and coverage. Never invent or cut a fact mid-token. You are summarizing, not continuing: never emit tool calls or fabricate tool results, file receipts, or transcript lines."
27
15
  : "You compress conversation history into accurate continuation memory. You are SUMMARIZING the past session, not continuing it: do not answer the user, do not perform the next task, and never emit tool calls or fabricate tool results, file-write receipts (bytes/lines/sha256), exit codes, or 'TOOL:'/'[tools: …]' transcript lines. Describe what already happened in your own words.";
28
- const completeSummary = async (p, onToken) => {
29
- const request = {
30
- provider: opts.provider,
31
- model: opts.model,
32
- messages: opts.sourceMessages
33
- ? [
34
- ...opts.sourceMessages,
35
- { role: "user", content: p },
36
- ]
37
- : [
38
- {
39
- role: "system",
40
- content: systemContent,
41
- },
42
- { role: "user", content: p },
43
- ],
44
- temperature: 0.1,
45
- maxTokens,
46
- thinking: { enabled: false, effort: "none" },
47
- signal: opts.signal,
48
- };
49
- const runProviderAttempt = async (attemptRequest, replace = false) => {
50
- if (!onToken) {
51
- return completeWithProvider(attemptRequest, { maxRetries: 0 });
52
- }
53
- if (replace)
54
- onToken("", true);
55
- const parser = createThinkingStreamParser((text) => onToken(text), undefined, { remember: false });
56
- const result = await streamWithProvider(attemptRequest, (token) => parser.push(token), { onStatus: () => undefined, maxRetries: 0 });
57
- parser.finish();
58
- return result;
59
- };
60
- const runAttempt = async (attemptRequest, replace = false) => {
61
- try {
62
- return await runProviderAttempt(attemptRequest, replace);
63
- }
64
- catch (error) {
65
- if (!isCompactionServerError(error))
66
- throw error;
67
- return await runProviderAttempt(attemptRequest, replace);
68
- }
69
- };
70
- const first = await runAttempt(request);
71
- let visible = normalizeCompactionSummary(stripThinking(first.text).visible);
72
- let retryReason;
73
- if (isCompactionCompletionTruncated(first, maxTokens)) {
74
- retryReason = "truncated";
75
- }
76
- else if (!visible) {
77
- retryReason = "reasoning-only";
78
- }
79
- else if (looksLikeTranscriptReplay(visible)) {
80
- retryReason = "replayed";
81
- }
82
- else if (looksLikeIncompleteCompactionSummary(visible)) {
83
- retryReason = "incomplete";
84
- }
85
- if (retryReason) {
86
- const retry = await runAttempt({
87
- ...request,
88
- messages: opts.sourceMessages
89
- ? [
90
- ...opts.sourceMessages,
91
- {
92
- role: "user",
93
- content: buildCompactionRetryPrompt(p, retryReason),
94
- },
95
- ]
96
- : [
97
- {
98
- role: "system",
99
- content: `${systemContent}\nReturn only a complete continuation-memory summary. Do not include analysis, reasoning, or <think> tags.`,
100
- },
101
- {
102
- role: "user",
103
- content: buildCompactionRetryPrompt(p, retryReason),
104
- },
105
- ],
106
- temperature: 0,
107
- maxTokens,
108
- thinking: { enabled: false, effort: "none" },
109
- }, true);
110
- if (isCompactionCompletionTruncated(retry, maxTokens)) {
111
- throw new Error("compaction failed: model hit the summary output limit twice — original context retained");
112
- }
113
- visible = normalizeCompactionSummary(stripThinking(retry.text).visible);
114
- if (!visible) {
115
- throw new Error("compaction failed: model returned an empty summary");
116
- }
117
- if (looksLikeTranscriptReplay(visible)) {
118
- throw new Error("compaction failed: model replayed the transcript twice — original context retained");
119
- }
120
- if (looksLikeIncompleteCompactionSummary(visible)) {
121
- throw new Error("compaction failed: model returned an incomplete summary twice — original context retained");
122
- }
123
- }
124
- return visible;
125
- };
126
- // `compactMessagesWithSummary` owns chunking/map-reduce. A second splitting
127
- // layer here multiplied one /compact into N map calls plus another reduce.
128
- return completeSummary(prompt, opts.onToken);
16
+ return executeCompactionSummary({
17
+ provider: opts.provider,
18
+ model: opts.model,
19
+ systemContent,
20
+ prompt,
21
+ maxTokens,
22
+ signal: opts.signal,
23
+ ...(opts.sourceMessages ? { sourceMessages: opts.sourceMessages } : {}),
24
+ ...(opts.baseRequest ? { baseRequest: opts.baseRequest } : {}),
25
+ ...(opts.history ? { history: opts.history } : {}),
26
+ ...(opts.contextLimitTokens !== undefined
27
+ ? { contextLimitTokens: opts.contextLimitTokens }
28
+ : {}),
29
+ ...(opts.operation ? { operation: opts.operation } : {}),
30
+ stream: Boolean(opts.onToken),
31
+ retryOnServerError: true,
32
+ qualityRetry: false,
33
+ onToken: opts.onToken,
34
+ });
129
35
  }
130
36
  export async function runSessionCompaction(options) {
131
37
  const emit = (type, payload) => {
132
38
  options.emit(options.sequencer.build(type, payload, undefined));
133
39
  };
134
- const beforeTokens = estimateMessagesTokens(options.history);
40
+ const historyTokensBefore = estimateMessagesTokens(options.history);
41
+ // The request-scoped measurement is the same provider-reported number the
42
+ // composer chip shows. The raw history estimate can exceed it (deliberately
43
+ // conservative chars-per-token ratio); preferring the estimate here made the
44
+ // compaction card disagree with the chip, so the request-scoped figure wins
45
+ // whenever one exists.
46
+ const requestTokensBefore = typeof options.requestTokensBefore === "number" &&
47
+ Number.isFinite(options.requestTokensBefore) &&
48
+ options.requestTokensBefore > 0
49
+ ? Math.floor(options.requestTokensBefore)
50
+ : undefined;
51
+ const scope = requestTokensBefore === undefined ? "message-history" : "assembled-request";
52
+ const beforeTokens = requestTokensBefore ?? historyTokensBefore;
53
+ // Compaction only rewrites messages: the system prefix and tool schemas are
54
+ // untouched, so the request shrinks by exactly what the history shrinks by.
55
+ const reportedFor = (result) => ({
56
+ beforeTokens,
57
+ afterTokens: requestTokensBefore === undefined
58
+ ? result.afterTokens
59
+ : Math.max(0, requestTokensBefore -
60
+ Math.max(0, result.beforeTokens - result.afterTokens)),
61
+ scope,
62
+ });
135
63
  if (options.persist) {
136
64
  emit("compaction-started", {
137
65
  compactionId: options.compactionId,
@@ -139,16 +67,58 @@ export async function runSessionCompaction(options) {
139
67
  });
140
68
  }
141
69
  let settled = false;
70
+ const operation = new OperationLedger({
71
+ kind: "compaction",
72
+ admissionBudget: 64,
73
+ continuationBudget: 0,
74
+ });
142
75
  try {
143
- const result = await compactMessagesWithSummary(options.history, (prompt, stage) => summarizeForSessionCompact(prompt, {
76
+ const successfulRequest = options.successfulRequest;
77
+ if (!successfulRequest) {
78
+ throw new Error("compaction failed: no successful live model request is available for cache-preserving compaction; complete a turn first");
79
+ }
80
+ const contextLimitTokens = options.contextLimitTokens ??
81
+ modelContextWindow(successfulRequest.model, successfulRequest.provider);
82
+ const instruction = buildDirectCompactionPrompt({
83
+ ...(options.purpose ? { purpose: options.purpose } : {}),
84
+ });
85
+ // Cache-preserving replay: the summary request resends the last
86
+ // successful turn request verbatim with the instruction appended, so the
87
+ // whole prior prompt is served from cache. When that assembled request
88
+ // would not fit (e.g. compacting a nearly-full session), fall back to the
89
+ // legacy transcript-rendered requests rather than failing closed.
90
+ const replayPlan = planCompactionReplay({
91
+ baseRequest: successfulRequest,
92
+ history: options.history,
93
+ prompt: instruction,
94
+ maxTokens: COMPACTION_MAX_COMPLETION_TOKENS,
95
+ contextLimitTokens,
96
+ stream: true,
97
+ });
98
+ const replay = replayPlan && !replayPlan.accounting.overLimit
99
+ ? successfulRequest
100
+ : undefined;
101
+ const result = await compactMessagesWithSummary(options.history, (prompt, stage) => summarizeForSessionCompact(replay ? instruction : prompt, {
144
102
  provider: options.provider,
145
103
  model: options.model,
146
104
  signal: options.signal,
147
105
  purpose: options.purpose,
148
106
  stage: stage?.phase,
149
- ...(stage?.sourceMessages
150
- ? { sourceMessages: stage.sourceMessages }
151
- : {}),
107
+ ...(replay
108
+ ? {
109
+ baseRequest: replay,
110
+ history: options.history,
111
+ contextLimitTokens,
112
+ }
113
+ : {
114
+ // Legacy path: the direct strategy carries the full source
115
+ // messages; the transcript strategies embed the material in
116
+ // the prompt itself and need no sourceMessages.
117
+ ...(stage?.sourceMessages
118
+ ? { sourceMessages: stage.sourceMessages }
119
+ : {}),
120
+ }),
121
+ operation,
152
122
  ...(options.persist && stage?.phase !== "map"
153
123
  ? {
154
124
  onToken: (text, replace) => {
@@ -166,12 +136,14 @@ export async function runSessionCompaction(options) {
166
136
  budgetTokens: 0,
167
137
  keepRecent: options.keepRecent,
168
138
  purpose: options.purpose,
169
- singlePassInputBudgetTokens: compactionSinglePassInputBudget(options.contextLimitTokens ??
170
- modelContextWindow(options.model, options.provider)),
171
- }, options.sessionTranscript);
139
+ singleAdmission: true,
140
+ ...(replay ? { forceDirectSinglePass: true } : {}),
141
+ singlePassInputBudgetTokens: compactionSinglePassInputBudget(contextLimitTokens),
142
+ });
172
143
  if (!options.isCurrent())
173
144
  return result;
174
- options.commit(result);
145
+ const reported = reportedFor(result);
146
+ options.commit(result, reported);
175
147
  if (options.persist && result.summarized) {
176
148
  const summary = [...result.messages]
177
149
  .reverse()
@@ -180,8 +152,9 @@ export async function runSessionCompaction(options) {
180
152
  emit("compaction-completed", {
181
153
  compactionId: options.compactionId,
182
154
  summary,
183
- beforeTokens: result.beforeTokens,
184
- afterTokens: result.afterTokens,
155
+ beforeTokens: reported.beforeTokens,
156
+ afterTokens: reported.afterTokens,
157
+ contextScope: reported.scope,
185
158
  });
186
159
  }
187
160
  else if (options.persist) {
@@ -1 +1 @@
1
- {"version":3,"file":"session-compact-helper.js","sourceRoot":"","sources":["../../../src/app/controllers/session-compact-helper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-compact-helper.js","sourceRoot":"","sources":["../../../src/app/controllers/session-compact-helper.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { type ContextUsageSnapshot } from "../../llm/token-usage.js";
1
+ import { type ContextAttemptReference, type ContextSnapshotScope, type ContextSnapshotV1 } from "../../llm/context-snapshot.js";
2
+ import type { ContextUsageSnapshot } from "../../llm/token-usage.js";
2
3
  import type { ChatMessage, ProviderId, TokenUsage } from "../../types.js";
3
4
  export interface ContextUsageTarget {
4
5
  readonly provider?: ProviderId | undefined;
@@ -6,22 +7,38 @@ export interface ContextUsageTarget {
6
7
  /** Explicit provider/model window for this session, if the user set one. */
7
8
  readonly contextLimitTokens?: number | undefined;
8
9
  }
10
+ export type ContextClock = () => number;
9
11
  export declare function contextUsageLimit(target: ContextUsageTarget): number;
10
- export declare function resolveContextUsageSnapshot(target: ContextUsageTarget, history: readonly ChatMessage[], current: ContextUsageSnapshot | undefined): ContextUsageSnapshot | undefined;
11
- export declare function recordUsageSnapshot(target: ContextUsageTarget, current: ContextUsageSnapshot | undefined, usage: TokenUsage): ContextUsageSnapshot;
12
- export declare function compactedUsageSnapshot(target: ContextUsageTarget, current: ContextUsageSnapshot | undefined, history: readonly ChatMessage[], afterTokens?: number): ContextUsageSnapshot;
13
- export declare function estimatedUsageSnapshot(target: ContextUsageTarget, current: ContextUsageSnapshot | undefined, estimatedTokens: number): ContextUsageSnapshot | undefined;
12
+ /**
13
+ * Keep the most recent request-scoped measurement. The message-history estimate
14
+ * omits the system prefix and tool schemas, so substituting it for a live
15
+ * measurement made the displayed number oscillate between two different scopes
16
+ * every step; it is now only a cold-start fallback.
17
+ */
18
+ export declare function resolveContextSnapshot(target: ContextUsageTarget, history: readonly ChatMessage[], current: ContextSnapshotV1 | undefined, now?: ContextClock): ContextSnapshotV1 | undefined;
19
+ /** Fold provider usage into one canonical provider-request observation. */
20
+ export declare function recordContextUsageSnapshot(target: ContextUsageTarget, current: ContextSnapshotV1 | undefined, usage: TokenUsage, attempt: ContextAttemptReference | undefined, now?: ContextClock): ContextSnapshotV1;
21
+ /** After compaction, exact provider fill is stale and the new scope is explicit. */
22
+ export declare function compactedContextSnapshot(target: ContextUsageTarget, current: ContextSnapshotV1 | undefined, history: readonly ChatMessage[], afterTokens: number | undefined, scope: Extract<ContextSnapshotScope, "message-history" | "assembled-request">, now?: ContextClock): ContextSnapshotV1;
23
+ export declare function estimatedContextSnapshot(target: ContextUsageTarget, current: ContextSnapshotV1 | undefined, estimatedTokens: number, now?: ContextClock): ContextSnapshotV1 | undefined;
14
24
  export interface ContextProjection {
15
- contextUsage: ContextUsageSnapshot | undefined;
16
- contextChip: string | undefined;
25
+ readonly contextSnapshot: ContextSnapshotV1 | undefined;
26
+ readonly contextUsage: ContextUsageSnapshot | undefined;
27
+ readonly contextChip: string | undefined;
17
28
  }
18
- export declare function createContextProjector(formatChip: (snapshot: ContextUsageSnapshot) => string): (target: ContextUsageTarget, history: readonly ChatMessage[], current: ContextUsageSnapshot | undefined) => ContextProjection;
29
+ export declare function createContextProjector(formatChip: (snapshot: ContextUsageSnapshot) => string): (target: ContextUsageTarget, history: readonly ChatMessage[], current: ContextSnapshotV1 | undefined, now?: ContextClock) => ContextProjection;
30
+ /** Legacy persisted shape, optionally carrying the additive V1 object. */
19
31
  export interface PartialUsageSnapshot {
20
- contextTokens: number;
21
- contextLimit?: number | undefined;
22
- lastCompletionTokens?: number | undefined;
23
- sessionPromptTokens?: number | undefined;
24
- sessionCompletionTokens?: number | undefined;
25
- exact: boolean;
32
+ readonly contextTokens: number;
33
+ readonly contextLimit?: number | undefined;
34
+ readonly lastCompletionTokens?: number | undefined;
35
+ readonly sessionPromptTokens?: number | undefined;
36
+ readonly sessionCompletionTokens?: number | undefined;
37
+ readonly exact: boolean;
38
+ readonly contextSnapshot?: unknown;
26
39
  }
27
- export declare function restoredUsageSnapshot(target: ContextUsageTarget, usage: PartialUsageSnapshot | ContextUsageSnapshot | undefined): ContextUsageSnapshot | undefined;
40
+ /** Restore V1 when available, otherwise migrate the unversioned legacy shape. */
41
+ export declare function restoredContextSnapshot(target: ContextUsageTarget, usage: PartialUsageSnapshot | ContextUsageSnapshot | ContextSnapshotV1 | undefined, now?: ContextClock): ContextSnapshotV1 | undefined;
42
+ export declare function resolveContextUsageSnapshot(target: ContextUsageTarget, history: readonly ChatMessage[], current: ContextUsageSnapshot | undefined): ContextUsageSnapshot | undefined;
43
+ export declare function compactedUsageSnapshot(target: ContextUsageTarget, current: ContextUsageSnapshot | undefined, history: readonly ChatMessage[], afterTokens?: number): ContextUsageSnapshot;
44
+ export declare function estimatedUsageSnapshot(target: ContextUsageTarget, current: ContextUsageSnapshot | undefined, estimatedTokens: number): ContextUsageSnapshot | undefined;