@pentoshi/clai 4.1.0 → 4.2.0

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 (264) 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/plan.js +20 -14
  213. package/dist/store/plan.js.map +1 -1
  214. package/dist/tools/elevated-shell.d.ts +1 -1
  215. package/dist/tools/elevated-shell.js +24 -72
  216. package/dist/tools/elevated-shell.js.map +1 -1
  217. package/dist/tools/nmap-runner.js +30 -36
  218. package/dist/tools/nmap-runner.js.map +1 -1
  219. package/dist/tools/sudo-session.d.ts +83 -0
  220. package/dist/tools/sudo-session.js +124 -0
  221. package/dist/tools/sudo-session.js.map +1 -0
  222. package/dist/tui-v2/app/App.js +9 -24
  223. package/dist/tui-v2/app/App.js.map +1 -1
  224. package/dist/tui-v2/components/status/context-limit-chip.js +2 -2
  225. package/dist/tui-v2/components/status/context-limit-chip.js.map +1 -1
  226. package/dist/tui-v2/components/transcript/intro-card.js +2 -1
  227. package/dist/tui-v2/components/transcript/intro-card.js.map +1 -1
  228. package/dist/tui-v2/composer/composer-editor.js +2 -1
  229. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  230. package/dist/types.d.ts +156 -1
  231. package/dist/types.js +1 -0
  232. package/dist/types.js.map +1 -1
  233. package/dist/ui-core/bootstrap/composition-root.d.ts +2 -0
  234. package/dist/ui-core/bootstrap/composition-root.js +26 -3
  235. package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
  236. package/dist/ui-core/commands/picker-commands.js +11 -5
  237. package/dist/ui-core/commands/picker-commands.js.map +1 -1
  238. package/dist/ui-core/commands/session-commands.js +41 -5
  239. package/dist/ui-core/commands/session-commands.js.map +1 -1
  240. package/dist/ui-core/plan/plan-lifecycle.js +3 -2
  241. package/dist/ui-core/plan/plan-lifecycle.js.map +1 -1
  242. package/dist/ui-core/rendering/context-limit.js +4 -1
  243. package/dist/ui-core/rendering/context-limit.js.map +1 -1
  244. package/dist/ui-core/rendering/duration.d.ts +2 -1
  245. package/dist/ui-core/rendering/duration.js +13 -5
  246. package/dist/ui-core/rendering/duration.js.map +1 -1
  247. package/dist/ui-core/rendering/intro-header.js +2 -2
  248. package/dist/ui-core/rendering/intro-header.js.map +1 -1
  249. package/dist/ui-core/rendering/theme.d.ts +1 -0
  250. package/dist/ui-core/rendering/theme.js +2 -0
  251. package/dist/ui-core/rendering/theme.js.map +1 -1
  252. package/dist/ui-core/state/transcript-hydrate.js +3 -3
  253. package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
  254. package/dist/ui-core/state/transcript-reducer.d.ts +5 -0
  255. package/dist/ui-core/state/transcript-reducer.js +76 -3
  256. package/dist/ui-core/state/transcript-reducer.js.map +1 -1
  257. package/dist/ui-core/state/transcript-store.d.ts +10 -1
  258. package/dist/ui-core/state/transcript-store.js +22 -1
  259. package/dist/ui-core/state/transcript-store.js.map +1 -1
  260. package/dist/ui-core/state/transcript-types.d.ts +2 -0
  261. package/dist/ui-core/state/transcript-types.js.map +1 -1
  262. package/dist/version.generated.d.ts +2 -2
  263. package/dist/version.generated.js +2 -2
  264. package/package.json +6 -1
@@ -1,10 +1,10 @@
1
- // Context-usage projection for the session footer.
1
+ // Context snapshot projection for the session footer.
2
2
  //
3
- // A denominator is displayed only when the user explicitly sets a session
4
- // model-window override. The default footer remains a concise current-context
5
- // count; compaction policy is resolved independently by the agent runner.
3
+ // ContextSnapshotV1 is the runtime source of truth. ContextUsageSnapshot is a
4
+ // deliberately narrow legacy projection for existing renderers and history.
6
5
  import { estimateMessagesTokens } from "../../agent/context-manager.js";
7
- import { applyUsageToSnapshot, snapshotFromEstimate, } from "../../llm/token-usage.js";
6
+ import { contextLimitFromSessionOverride, contextSnapshotFromLegacy, createContextSnapshot, isContextSnapshotV1, toLegacyContextUsage, withContextSnapshotLimit, } from "../../llm/context-snapshot.js";
7
+ const systemNow = () => Date.now();
8
8
  // The footer denominator is the explicit model window, never a guessed window
9
9
  // or compaction trigger. Zero means no session override was set.
10
10
  export function contextUsageLimit(target) {
@@ -13,54 +13,143 @@ export function contextUsageLimit(target) {
13
13
  ? Math.floor(limit)
14
14
  : 0;
15
15
  }
16
- // Prefer the last API `prompt_tokens` as context fill (exact); otherwise
17
- // estimate from current history so the footer always has a number.
18
- export function resolveContextUsageSnapshot(target, history, current) {
19
- const contextLimit = contextUsageLimit(target);
20
- if (current?.exact && current.contextTokens > 0) {
21
- return { ...current, contextLimit };
16
+ function limitFor(target) {
17
+ return contextLimitFromSessionOverride(contextUsageLimit(target));
18
+ }
19
+ function sameLimit(left, right) {
20
+ return left.source === right.source && left.tokens === right.tokens;
21
+ }
22
+ function hasPromptMeasurement(usage) {
23
+ return usage.promptTokensKnown !== false;
24
+ }
25
+ function reportedCache(usage) {
26
+ const readTokens = usage.cachedPromptTokens;
27
+ const creationTokens = usage.cacheCreationTokens;
28
+ const uncachedTokens = usage.uncachedPromptTokens;
29
+ if (readTokens === undefined &&
30
+ creationTokens === undefined &&
31
+ uncachedTokens === undefined) {
32
+ return undefined;
22
33
  }
23
- const estimated = snapshotFromEstimate(history, target.model, target.provider, current);
24
- return { ...estimated, contextLimit };
34
+ return {
35
+ kind: "reported",
36
+ ...(readTokens !== undefined ? { readTokens } : {}),
37
+ ...(creationTokens !== undefined ? { creationTokens } : {}),
38
+ ...(uncachedTokens !== undefined ? { uncachedTokens } : {}),
39
+ };
25
40
  }
26
- // Fold provider-reported usage into the snapshot against the request budget.
27
- export function recordUsageSnapshot(target, current, usage) {
28
- return applyUsageToSnapshot(current, usage, contextUsageLimit(target));
41
+ function reportedReasoning(usage) {
42
+ if (usage.reasoningTokens === undefined)
43
+ return undefined;
44
+ return { kind: "reported", outputTokens: usage.reasoningTokens };
29
45
  }
30
- // After /compact or auto-compact the exact prompt_tokens are stale: report the
31
- // post-compaction size until the next API usage report.
32
- export function compactedUsageSnapshot(target, current, history, afterTokens) {
33
- const estimated = typeof afterTokens === "number" && afterTokens > 0
34
- ? afterTokens
46
+ function historyEstimateSnapshot(target, current, history, now) {
47
+ return createContextSnapshot({
48
+ contextTokens: estimateMessagesTokens(history),
49
+ lastCompletionTokens: current?.lastCompletionTokens,
50
+ sessionPromptTokens: current?.sessionPromptTokens,
51
+ sessionCompletionTokens: current?.sessionCompletionTokens,
52
+ scope: "message-history",
53
+ precision: "estimate",
54
+ limit: limitFor(target),
55
+ observedAt: now(),
56
+ });
57
+ }
58
+ /**
59
+ * Scopes that describe the occupancy of a real model request. Both the
60
+ * pre-dispatch assembled estimate and the provider's post-dispatch count
61
+ * measure the same thing, so either may be presented as the current fill.
62
+ */
63
+ const REQUEST_SCOPES = new Set([
64
+ "provider-request",
65
+ "assembled-request",
66
+ ]);
67
+ /**
68
+ * Keep the most recent request-scoped measurement. The message-history estimate
69
+ * omits the system prefix and tool schemas, so substituting it for a live
70
+ * measurement made the displayed number oscillate between two different scopes
71
+ * every step; it is now only a cold-start fallback.
72
+ */
73
+ export function resolveContextSnapshot(target, history, current, now = systemNow) {
74
+ const limit = limitFor(target);
75
+ if (current && current.contextTokens > 0 && REQUEST_SCOPES.has(current.scope)) {
76
+ return sameLimit(current.limit, limit)
77
+ ? current
78
+ : withContextSnapshotLimit(current, limit);
79
+ }
80
+ return historyEstimateSnapshot(target, current, history, now);
81
+ }
82
+ /** Fold provider usage into one canonical provider-request observation. */
83
+ export function recordContextUsageSnapshot(target, current, usage, attempt, now = systemNow) {
84
+ const promptMeasured = hasPromptMeasurement(usage);
85
+ const sessionPromptTokens = (current?.sessionPromptTokens ?? 0) +
86
+ (usage.exact && promptMeasured ? usage.promptTokens : 0);
87
+ const sessionCompletionTokens = (current?.sessionCompletionTokens ?? 0) +
88
+ (usage.exact ? usage.completionTokens : 0);
89
+ const cache = reportedCache(usage);
90
+ const reasoning = reportedReasoning(usage);
91
+ return createContextSnapshot({
92
+ // A completion-only report cannot refresh current context occupancy. Keep
93
+ // the prior number only as an explicitly unknown observation so the next
94
+ // estimate replaces it instead of presenting stale provider exactness.
95
+ contextTokens: promptMeasured
96
+ ? usage.promptTokens
97
+ : (current?.contextTokens ?? 0),
98
+ lastCompletionTokens: usage.completionTokens,
99
+ sessionPromptTokens,
100
+ sessionCompletionTokens,
101
+ scope: promptMeasured ? "provider-request" : "unknown",
102
+ precision: usage.exact && promptMeasured
103
+ ? "provider-exact"
104
+ : promptMeasured
105
+ ? "estimate"
106
+ : "unknown",
107
+ limit: limitFor(target),
108
+ ...(cache ? { cache } : {}),
109
+ ...(reasoning ? { reasoning } : {}),
110
+ ...(attempt ? { attempt } : {}),
111
+ observedAt: now(),
112
+ });
113
+ }
114
+ /** After compaction, exact provider fill is stale and the new scope is explicit. */
115
+ export function compactedContextSnapshot(target, current, history, afterTokens, scope, now = systemNow) {
116
+ const contextTokens = typeof afterTokens === "number" && Number.isFinite(afterTokens) && afterTokens > 0
117
+ ? Math.floor(afterTokens)
35
118
  : estimateMessagesTokens(history);
36
- return {
37
- contextTokens: estimated,
38
- contextLimit: contextUsageLimit(target),
119
+ return createContextSnapshot({
120
+ contextTokens,
39
121
  lastCompletionTokens: 0,
40
- sessionPromptTokens: current?.sessionPromptTokens ?? 0,
41
- sessionCompletionTokens: current?.sessionCompletionTokens ?? 0,
42
- exact: false,
43
- };
122
+ sessionPromptTokens: current?.sessionPromptTokens,
123
+ sessionCompletionTokens: current?.sessionCompletionTokens,
124
+ scope,
125
+ precision: "estimate",
126
+ limit: limitFor(target),
127
+ observedAt: now(),
128
+ });
44
129
  }
45
- export function estimatedUsageSnapshot(target, current, estimatedTokens) {
130
+ export function estimatedContextSnapshot(target, current, estimatedTokens, now = systemNow) {
46
131
  if (!Number.isFinite(estimatedTokens) || estimatedTokens <= 0)
47
132
  return current;
48
- if (current?.exact)
133
+ if (current?.scope === "provider-request" &&
134
+ current.precision === "provider-exact") {
49
135
  return current;
50
- return {
136
+ }
137
+ return createContextSnapshot({
51
138
  contextTokens: Math.floor(estimatedTokens),
52
- contextLimit: current?.contextLimit ?? contextUsageLimit(target),
53
- lastCompletionTokens: current?.lastCompletionTokens ?? 0,
54
- sessionPromptTokens: current?.sessionPromptTokens ?? 0,
55
- sessionCompletionTokens: current?.sessionCompletionTokens ?? 0,
56
- exact: false,
57
- };
139
+ lastCompletionTokens: current?.lastCompletionTokens,
140
+ sessionPromptTokens: current?.sessionPromptTokens,
141
+ sessionCompletionTokens: current?.sessionCompletionTokens,
142
+ scope: "assembled-request",
143
+ precision: "estimate",
144
+ limit: limitFor(target),
145
+ observedAt: now(),
146
+ });
58
147
  }
59
148
  // The estimate walks the whole transcript, so the projection is memoized
60
149
  // against the inputs that can change it instead of recomputed per render.
61
150
  export function createContextProjector(formatChip) {
62
151
  let cache;
63
- return (target, history, current) => {
152
+ return (target, history, current, now = systemNow) => {
64
153
  const first = history[0];
65
154
  const last = history[history.length - 1];
66
155
  const key = [
@@ -70,15 +159,37 @@ export function createContextProjector(formatChip) {
70
159
  history.length,
71
160
  first?.content.length ?? 0,
72
161
  last?.content.length ?? 0,
162
+ current?.version ?? 0,
73
163
  current?.contextTokens ?? -1,
74
- current?.contextLimit ?? -1,
75
- current?.lastCompletionTokens ?? -1,
76
- current?.exact ? 1 : 0,
164
+ current?.scope ?? "",
165
+ current?.precision ?? "",
166
+ current?.limit.source ?? "",
167
+ current?.limit.tokens ?? -1,
168
+ current?.cache.kind ?? "",
169
+ current?.cache.kind === "reported" ? current.cache.readTokens ?? -1 : -1,
170
+ current?.cache.kind === "reported"
171
+ ? current.cache.creationTokens ?? -1
172
+ : -1,
173
+ current?.cache.kind === "reported"
174
+ ? current.cache.uncachedTokens ?? -1
175
+ : -1,
176
+ current?.reasoning.kind ?? "",
177
+ current?.reasoning.kind === "reported"
178
+ ? current.reasoning.outputTokens ?? -1
179
+ : -1,
180
+ current?.reasoning.kind === "reported"
181
+ ? current.reasoning.inputArtifactTokens ?? -1
182
+ : -1,
183
+ current?.observedAt ?? -1,
77
184
  ].join("|");
78
185
  if (cache?.key === key)
79
186
  return cache.value;
80
- const contextUsage = resolveContextUsageSnapshot(target, history, current);
187
+ const contextSnapshot = resolveContextSnapshot(target, history, current, now);
188
+ const contextUsage = contextSnapshot
189
+ ? toLegacyContextUsage(contextSnapshot)
190
+ : undefined;
81
191
  const value = {
192
+ contextSnapshot,
82
193
  contextUsage,
83
194
  contextChip: contextUsage ? formatChip(contextUsage) : undefined,
84
195
  };
@@ -86,20 +197,44 @@ export function createContextProjector(formatChip) {
86
197
  return value;
87
198
  };
88
199
  }
89
- // Prefer the exact snapshot saved during the live turn; older sessions without
90
- // a usage payload fall back to an estimate at the call site.
91
- export function restoredUsageSnapshot(target, usage) {
92
- if (!usage || usage.contextTokens <= 0)
200
+ /** Restore V1 when available, otherwise migrate the unversioned legacy shape. */
201
+ export function restoredContextSnapshot(target, usage, now = systemNow) {
202
+ if (!usage)
93
203
  return undefined;
94
- return {
204
+ if (isContextSnapshotV1(usage)) {
205
+ return usage.contextTokens > 0
206
+ ? withContextSnapshotLimit(usage, limitFor(target))
207
+ : undefined;
208
+ }
209
+ const persisted = usage.contextSnapshot;
210
+ if (isContextSnapshotV1(persisted) && persisted.contextTokens > 0) {
211
+ // A saved denominator might have been an old auto-compact trigger. The
212
+ // live session override remains the only display limit after restore.
213
+ return withContextSnapshotLimit(persisted, limitFor(target));
214
+ }
215
+ if (usage.contextTokens <= 0)
216
+ return undefined;
217
+ return contextSnapshotFromLegacy({
95
218
  contextTokens: usage.contextTokens,
96
- // Persisted snapshots from older builds stored an auto-compact trigger
97
- // here. Only a live explicit session override may become a denominator.
98
- contextLimit: contextUsageLimit(target),
219
+ contextLimit: usage.contextLimit ?? 0,
99
220
  lastCompletionTokens: usage.lastCompletionTokens ?? 0,
100
221
  sessionPromptTokens: usage.sessionPromptTokens ?? 0,
101
222
  sessionCompletionTokens: usage.sessionCompletionTokens ?? 0,
102
223
  exact: usage.exact === true,
103
- };
224
+ }, limitFor(target), now());
225
+ }
226
+ // Compatibility exports retained for old callers and legacy-focused tests.
227
+ export function resolveContextUsageSnapshot(target, history, current) {
228
+ const canonical = resolveContextSnapshot(target, history, current
229
+ ? contextSnapshotFromLegacy(current, limitFor(target))
230
+ : undefined);
231
+ return canonical ? toLegacyContextUsage(canonical) : undefined;
232
+ }
233
+ export function compactedUsageSnapshot(target, current, history, afterTokens) {
234
+ return toLegacyContextUsage(compactedContextSnapshot(target, current ? contextSnapshotFromLegacy(current, limitFor(target)) : undefined, history, afterTokens, "message-history"));
235
+ }
236
+ export function estimatedUsageSnapshot(target, current, estimatedTokens) {
237
+ const canonical = estimatedContextSnapshot(target, current ? contextSnapshotFromLegacy(current, limitFor(target)) : undefined, estimatedTokens);
238
+ return canonical ? toLegacyContextUsage(canonical) : undefined;
104
239
  }
105
240
  //# sourceMappingURL=session-context-usage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-context-usage.js","sourceRoot":"","sources":["../../../src/app/controllers/session-context-usage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-context-usage.js","sourceRoot":"","sources":["../../../src/app/controllers/session-context-usage.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import type { ChatMessage, Mode, ProviderId, TokenUsage, ToolResult } from "../../types.js";
2
2
  import { type CompactResult } from "../../agent/context-manager.js";
3
3
  import { type ContextUsageSnapshot } from "../../llm/token-usage.js";
4
+ import type { ContextAttemptReference, ContextSnapshotV1 } from "../../llm/context-snapshot.js";
4
5
  import { type PartialUsageSnapshot } from "./session-context-usage.js";
5
6
  import type { PreviousTurnSignal } from "../../agent/continue-orient.js";
6
7
  import { type SessionWorkspace } from "../../store/session-workspace.js";
@@ -29,6 +30,9 @@ export interface SessionState {
29
30
  readonly queued: readonly string[];
30
31
  readonly responder: ResponderRuntimeState;
31
32
  readonly title: string | undefined;
33
+ /** Canonical versioned context measurement for runtime consumers. */
34
+ readonly contextSnapshot: ContextSnapshotV1 | undefined;
35
+ /** Six-field legacy projection retained for existing renderers. */
32
36
  readonly contextUsage: ContextUsageSnapshot | undefined;
33
37
  readonly contextChip: string | undefined;
34
38
  }
@@ -52,6 +56,7 @@ export interface SessionControllerDeps {
52
56
  /** When true, never persist sessions or generate AI titles (CLI --no-history). */
53
57
  readonly noHistory?: boolean | undefined;
54
58
  readonly notifyResponderDelivery?: ((summary: string) => void) | undefined;
59
+ readonly titleCompleter?: ((messages: ChatMessage[]) => Promise<string>) | undefined;
55
60
  }
56
61
  export type TurnEndListener = (result: TurnResult) => void;
57
62
  export type SessionStateListener = () => void;
@@ -74,19 +79,20 @@ export declare class SessionController implements Disposable {
74
79
  private compactingFlag;
75
80
  private readonly activeCompactions;
76
81
  private compactAbort;
77
- /** Display name written into history.db (AI title or explicit /save name). */
82
+ /** Display name written into history.db. */
78
83
  private sessionTitle;
79
- /** User-message count at last successful AI title (classic refresh cadence). */
80
- private titledAtUserCount;
81
- private titleInFlight;
84
+ private readonly namer;
85
+ private lastMainRequestSnapshot;
82
86
  /** Throttle mid-turn history autosaves so abort/crash still keep tools on disk. */
83
87
  private lastAutosaveAt;
84
88
  private autosaveInFlight;
85
89
  /** Orders autosave, terminal, compaction, title, switch, and shutdown writes. */
86
90
  private readonly persistence;
87
91
  private static readonly AUTOSAVE_MIN_MS;
88
- /** Last known context / session token totals for the status strip. */
89
- private contextUsage;
92
+ /** Last known versioned context measurement for the session. */
93
+ private contextSnapshot;
94
+ /** Avoid applying the same manual compaction in both commit and event paths. */
95
+ private lastContextCompactionId;
90
96
  private readonly contextLimits;
91
97
  /** Bumped by reset/history load/dispose so late callbacks can be ignored. */
92
98
  private lifecycleGeneration;
@@ -102,9 +108,13 @@ export declare class SessionController implements Disposable {
102
108
  private contextUsageProjection;
103
109
  private get contextLimitTokens();
104
110
  private get usageTarget();
105
- private resolveContextUsage;
106
- recordTokenUsage(usage: TokenUsage, model?: string, provider?: ProviderId): void;
107
- noteContextCompacted(afterTokens?: number): void;
111
+ private contextTimestamp;
112
+ private setContextSnapshot;
113
+ private resolveContextSnapshot;
114
+ /** Next-request occupancy, only when a request-scoped measurement exists. */
115
+ private requestScopedContextTokens;
116
+ recordTokenUsage(usage: TokenUsage, model?: string, provider?: ProviderId, attempt?: ContextAttemptReference): void;
117
+ noteContextCompacted(afterTokens?: number, scope?: "message-history" | "assembled-request", compactionId?: string): void;
108
118
  noteContextEstimate(estimatedTokens: number): void;
109
119
  private refreshEstimatedContext;
110
120
  get messages(): readonly ChatMessage[];
@@ -147,7 +157,7 @@ export declare class SessionController implements Disposable {
147
157
  mintNewId?: boolean;
148
158
  }): void;
149
159
  /** Roll back history after a rejected plan-implement compaction. */
150
- restoreMessages(messages: readonly ChatMessage[], contextUsage?: ContextUsageSnapshot | undefined): void;
160
+ restoreMessages(messages: readonly ChatMessage[], contextSnapshot?: ContextSnapshotV1 | ContextUsageSnapshot | undefined): void;
151
161
  compact(sessionTranscript?: string, keepRecent?: number, signal?: AbortSignal, options?: {
152
162
  purpose?: "default" | "plan-implement" | undefined;
153
163
  /** Default true: emit compacted event + persist. */
@@ -156,7 +166,6 @@ export declare class SessionController implements Disposable {
156
166
  private settlePersistedResponderResults;
157
167
  private continuationCheckpoint;
158
168
  persistNow(name?: string): Promise<void>;
159
- maybeRefreshTitle(): Promise<void>;
160
169
  estimateContext(): {
161
170
  messages: number;
162
171
  tokens: number;