@namzu/sdk 53.2.1 → 54.0.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 (129) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/compaction/context-breakdown.d.ts +85 -0
  3. package/dist/compaction/context-breakdown.d.ts.map +1 -0
  4. package/dist/compaction/context-breakdown.js +149 -0
  5. package/dist/compaction/context-breakdown.js.map +1 -0
  6. package/dist/compaction/token-estimate.d.ts +2 -0
  7. package/dist/compaction/token-estimate.d.ts.map +1 -1
  8. package/dist/compaction/token-estimate.js +4 -0
  9. package/dist/compaction/token-estimate.js.map +1 -1
  10. package/dist/public-runtime.d.ts +7 -2
  11. package/dist/public-runtime.d.ts.map +1 -1
  12. package/dist/public-runtime.js +6 -1
  13. package/dist/public-runtime.js.map +1 -1
  14. package/dist/runtime/cache-clock.d.ts +39 -0
  15. package/dist/runtime/cache-clock.d.ts.map +1 -0
  16. package/dist/runtime/cache-clock.js +48 -0
  17. package/dist/runtime/cache-clock.js.map +1 -0
  18. package/dist/runtime/query/compact-session.d.ts +37 -2
  19. package/dist/runtime/query/compact-session.d.ts.map +1 -1
  20. package/dist/runtime/query/compact-session.js +77 -3
  21. package/dist/runtime/query/compact-session.js.map +1 -1
  22. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  23. package/dist/runtime/query/executor/tool-call-admission.js +3 -0
  24. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  25. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  26. package/dist/runtime/query/iteration/index.js +8 -0
  27. package/dist/runtime/query/iteration/index.js.map +1 -1
  28. package/dist/store/budget/disk.js +4 -1
  29. package/dist/store/budget/disk.js.map +1 -1
  30. package/dist/tools/admit-facts.d.ts.map +1 -1
  31. package/dist/tools/admit-facts.js +6 -0
  32. package/dist/tools/admit-facts.js.map +1 -1
  33. package/dist/tools/builtins/bash.d.ts.map +1 -1
  34. package/dist/tools/builtins/bash.js +23 -9
  35. package/dist/tools/builtins/bash.js.map +1 -1
  36. package/dist/tools/builtins/browser.js +1 -1
  37. package/dist/tools/builtins/browser.js.map +1 -1
  38. package/dist/tools/builtins/computer-use.js +2 -2
  39. package/dist/tools/builtins/computer-use.js.map +1 -1
  40. package/dist/tools/builtins/edit-apply.d.ts +7 -4
  41. package/dist/tools/builtins/edit-apply.d.ts.map +1 -1
  42. package/dist/tools/builtins/edit-apply.js +3 -0
  43. package/dist/tools/builtins/edit-apply.js.map +1 -1
  44. package/dist/tools/builtins/edit.d.ts.map +1 -1
  45. package/dist/tools/builtins/edit.js +27 -7
  46. package/dist/tools/builtins/edit.js.map +1 -1
  47. package/dist/tools/builtins/exit-semantics.d.ts +31 -0
  48. package/dist/tools/builtins/exit-semantics.d.ts.map +1 -0
  49. package/dist/tools/builtins/exit-semantics.js +198 -0
  50. package/dist/tools/builtins/exit-semantics.js.map +1 -0
  51. package/dist/tools/builtins/write-file.js +7 -2
  52. package/dist/tools/builtins/write-file.js.map +1 -1
  53. package/dist/tools/coordinator/ask-user-question.js +1 -1
  54. package/dist/tools/coordinator/ask-user-question.js.map +1 -1
  55. package/dist/tools/coordinator/index.js +2 -2
  56. package/dist/tools/coordinator/index.js.map +1 -1
  57. package/dist/tools/memory/delete.js +1 -1
  58. package/dist/tools/memory/delete.js.map +1 -1
  59. package/dist/tools/memory/fields.js +1 -1
  60. package/dist/tools/memory/fields.js.map +1 -1
  61. package/dist/tools/memory/read.js +1 -1
  62. package/dist/tools/memory/read.js.map +1 -1
  63. package/dist/tools/memory/save.d.ts.map +1 -1
  64. package/dist/tools/memory/save.js +4 -3
  65. package/dist/tools/memory/save.js.map +1 -1
  66. package/dist/tools/memory/search.js +1 -1
  67. package/dist/tools/memory/search.js.map +1 -1
  68. package/dist/tools/memory/update.js +1 -1
  69. package/dist/tools/memory/update.js.map +1 -1
  70. package/dist/tools/schedules/schedule-tool.js +3 -3
  71. package/dist/tools/schedules/schedule-tool.js.map +1 -1
  72. package/dist/toolsets/manager.d.ts.map +1 -1
  73. package/dist/toolsets/manager.js +6 -1
  74. package/dist/toolsets/manager.js.map +1 -1
  75. package/dist/types/common/index.d.ts +19 -0
  76. package/dist/types/common/index.d.ts.map +1 -1
  77. package/dist/types/common/index.js +9 -0
  78. package/dist/types/common/index.js.map +1 -1
  79. package/dist/types/provider/chat.d.ts +8 -0
  80. package/dist/types/provider/chat.d.ts.map +1 -1
  81. package/dist/types/provider/config.d.ts +6 -0
  82. package/dist/types/provider/config.d.ts.map +1 -1
  83. package/dist/types/session/checkpoint.d.ts +52 -0
  84. package/dist/types/session/checkpoint.d.ts.map +1 -1
  85. package/dist/types/session/checkpoint.js +5 -0
  86. package/dist/types/session/checkpoint.js.map +1 -1
  87. package/dist/types/session/events.d.ts +9 -0
  88. package/dist/types/session/events.d.ts.map +1 -1
  89. package/dist/types/session/events.js.map +1 -1
  90. package/dist/types/session/records.d.ts +181 -6
  91. package/dist/types/session/records.d.ts.map +1 -1
  92. package/dist/types/session/records.js +1 -1
  93. package/dist/types/session/records.js.map +1 -1
  94. package/dist/types/tool/presentation.d.ts +17 -1
  95. package/dist/types/tool/presentation.d.ts.map +1 -1
  96. package/package.json +1 -1
  97. package/src/compaction/context-breakdown.ts +228 -0
  98. package/src/compaction/token-estimate.ts +5 -0
  99. package/src/public-runtime.ts +23 -2
  100. package/src/runtime/cache-clock.ts +67 -0
  101. package/src/runtime/query/compact-session.ts +101 -3
  102. package/src/runtime/query/executor/tool-call-admission.ts +3 -0
  103. package/src/runtime/query/iteration/index.ts +8 -0
  104. package/src/store/budget/disk.ts +4 -1
  105. package/src/tools/admit-facts.ts +6 -0
  106. package/src/tools/builtins/bash.ts +25 -9
  107. package/src/tools/builtins/browser.ts +1 -1
  108. package/src/tools/builtins/computer-use.ts +2 -2
  109. package/src/tools/builtins/edit-apply.ts +12 -2
  110. package/src/tools/builtins/edit.ts +34 -8
  111. package/src/tools/builtins/exit-semantics.ts +198 -0
  112. package/src/tools/builtins/write-file.ts +7 -2
  113. package/src/tools/coordinator/ask-user-question.ts +1 -1
  114. package/src/tools/coordinator/index.ts +2 -2
  115. package/src/tools/memory/delete.ts +1 -1
  116. package/src/tools/memory/fields.ts +1 -1
  117. package/src/tools/memory/read.ts +1 -1
  118. package/src/tools/memory/save.ts +4 -3
  119. package/src/tools/memory/search.ts +1 -1
  120. package/src/tools/memory/update.ts +1 -1
  121. package/src/tools/schedules/schedule-tool.ts +3 -3
  122. package/src/toolsets/manager.ts +6 -1
  123. package/src/types/common/index.ts +27 -0
  124. package/src/types/provider/chat.ts +8 -0
  125. package/src/types/provider/config.ts +6 -0
  126. package/src/types/session/checkpoint.ts +5 -0
  127. package/src/types/session/events.ts +6 -0
  128. package/src/types/session/records.ts +1 -1
  129. package/src/types/tool/presentation.ts +16 -0
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../../src/types/tool/presentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../../src/types/tool/presentation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/sdk",
3
- "version": "53.2.1",
3
+ "version": "54.0.0",
4
4
  "description": "Open-source AI kernel for TypeScript: runs an agent the way an operating system runs a process, with an identity and a budget, scheduled tool calls and checkpointed turns.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "engines": {
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Where the context window goes: the arithmetic behind a `/context` view.
3
+ *
4
+ * Pure. A host hands in what it knows (sizes of the system prompt, the tool
5
+ * catalogue, instruction files, skills, agents, and the conversation) and gets
6
+ * the categories back in the order they are drawn, with the free room and the
7
+ * compaction buffer accounted for. Nothing here reads a provider or a file.
8
+ *
9
+ * The conversation's own share is never counted separately: it is whatever the
10
+ * measured prompt size is once the fixed parts are taken out, so the categories
11
+ * always add up to the figure the provider reported.
12
+ */
13
+
14
+ import { CHARS_PER_TOKEN } from '../constants/limits.js'
15
+ import type { Message } from '../types/message/index.js'
16
+ import type { LLMToolSchema } from '../types/tool/index.js'
17
+ import { TRIGGER_BUFFER_TOKENS, TRIGGER_OUTPUT_RESERVE_CAP_TOKENS } from './context-window.js'
18
+ import { estimateMessageTokens, estimateTextTokens } from './token-estimate.js'
19
+
20
+ /** The categories, in the order they are laid out. */
21
+ export const CONTEXT_CATEGORY_ORDER = [
22
+ 'system-prompt',
23
+ 'system-tools',
24
+ 'mcp-tools',
25
+ 'mcp-instructions',
26
+ 'agents',
27
+ 'memory',
28
+ 'skills',
29
+ 'messages',
30
+ ] as const
31
+
32
+ export type ContextCategoryId = (typeof CONTEXT_CATEGORY_ORDER)[number] | 'buffer' | 'free'
33
+ export type ContextCategoryKind = 'used' | 'free' | 'buffer'
34
+
35
+ export interface ContextCategory {
36
+ readonly id: ContextCategoryId
37
+ readonly name: string
38
+ readonly tokens: number
39
+ readonly kind: ContextCategoryKind
40
+ }
41
+
42
+ const NAMES: Record<(typeof CONTEXT_CATEGORY_ORDER)[number], string> = {
43
+ 'system-prompt': 'System prompt',
44
+ 'system-tools': 'System tools',
45
+ 'mcp-tools': 'MCP tools',
46
+ 'mcp-instructions': 'MCP server instructions',
47
+ agents: 'Custom agents',
48
+ memory: 'Memory files',
49
+ skills: 'Skills',
50
+ messages: 'Messages',
51
+ }
52
+
53
+ export interface ContextUsageInput {
54
+ readonly windowTokens: number
55
+ /**
56
+ * `auto` when the window is what the provider or model table declares.
57
+ * Anything else (`config`, `default`) means the figure was overridden or
58
+ * guessed, and the compaction buffer is then drawn.
59
+ */
60
+ readonly windowSource: 'auto' | 'config' | 'default'
61
+ /** What the model may write in one reply; absent reserves the full cap. */
62
+ readonly maxOutputTokens?: number
63
+ /** Whether the session summarises on its own. */
64
+ readonly autoCompact: boolean
65
+ /**
66
+ * The size of everything being sent: counted by the provider, or estimated.
67
+ * Absent, the conversation is estimated from `messages`.
68
+ */
69
+ readonly contextTokens?: number
70
+ readonly systemPromptTokens?: number
71
+ /** Tokens of the built-in tool definitions. */
72
+ readonly systemToolTokens?: number
73
+ readonly mcpToolTokens?: number
74
+ readonly mcpInstructionTokens?: number
75
+ readonly agentTokens?: number
76
+ readonly memoryTokens?: number
77
+ readonly skillTokens?: number
78
+ /** The conversation, for the estimate and for the per-tool breakdown. */
79
+ readonly messages?: readonly Message[]
80
+ }
81
+
82
+ export interface ContextMessageBreakdown {
83
+ /** Tokens of the calls the model wrote, by tool name. */
84
+ readonly toolCallsByType: Readonly<Record<string, number>>
85
+ /** Tokens of the results that came back, by the name of the tool called. */
86
+ readonly toolResultsByType: Readonly<Record<string, number>>
87
+ readonly assistantTokens: number
88
+ readonly userTokens: number
89
+ }
90
+
91
+ export interface ContextBreakdown {
92
+ readonly categories: readonly ContextCategory[]
93
+ readonly windowTokens: number
94
+ /** Everything in use, which can exceed the window. */
95
+ readonly totalTokens: number
96
+ /** Whole percent of the window in use. */
97
+ readonly percentage: number
98
+ /** The compaction buffer, 0 when it is not drawn. */
99
+ readonly bufferTokens: number
100
+ /** Whether the session summarises on its own; names the buffer. */
101
+ readonly autoCompact: boolean
102
+ /** How far past the window the context is; 0 while it fits. */
103
+ readonly overflowTokens: number
104
+ readonly messageBreakdown: ContextMessageBreakdown
105
+ }
106
+
107
+ /** Per-tool size of a catalogue already rendered the way it is sent. */
108
+ export function describeToolCatalogTokens(
109
+ tools: readonly LLMToolSchema[],
110
+ ): { name: string; tokens: number }[] {
111
+ return tools.map((tool) => {
112
+ let length = 0
113
+ try {
114
+ length = JSON.stringify(tool).length
115
+ } catch {
116
+ // A tool that cannot render is the model call's problem to report.
117
+ }
118
+ return { name: tool.function.name, tokens: Math.ceil(length / CHARS_PER_TOKEN) }
119
+ })
120
+ }
121
+
122
+ function nonNegative(value: number | undefined): number {
123
+ return value !== undefined && Number.isFinite(value) && value > 0 ? Math.round(value) : 0
124
+ }
125
+
126
+ function bufferFor(input: ContextUsageInput): number {
127
+ if (input.autoCompact) {
128
+ // Drawn only when the window was overridden: on a declared window the
129
+ // room kept for a reply is not a thing the person chose.
130
+ if (input.windowSource === 'auto') return 0
131
+ const reserve = Math.min(
132
+ input.maxOutputTokens !== undefined && input.maxOutputTokens > 0
133
+ ? input.maxOutputTokens
134
+ : TRIGGER_OUTPUT_RESERVE_CAP_TOKENS,
135
+ TRIGGER_OUTPUT_RESERVE_CAP_TOKENS,
136
+ )
137
+ return reserve + TRIGGER_BUFFER_TOKENS
138
+ }
139
+ return COMPACT_BUFFER_TOKENS
140
+ }
141
+
142
+ /** Room kept for a manual compaction when nothing summarises on its own. */
143
+ export const COMPACT_BUFFER_TOKENS = 3_000
144
+
145
+ function tokensOfContent(message: Message): number {
146
+ return estimateMessageTokens(message)
147
+ }
148
+
149
+ function breakdownMessages(messages: readonly Message[]): ContextMessageBreakdown {
150
+ const toolCallsByType: Record<string, number> = {}
151
+ const toolResultsByType: Record<string, number> = {}
152
+ const nameOfCall = new Map<string, string>()
153
+ let assistantTokens = 0
154
+ let userTokens = 0
155
+ for (const message of messages) {
156
+ if (message.role === 'assistant') {
157
+ let calls = 0
158
+ for (const call of message.toolCalls ?? []) {
159
+ nameOfCall.set(call.id, call.function.name)
160
+ const tokens = estimateTextTokens(call.function.name + call.function.arguments)
161
+ toolCallsByType[call.function.name] = (toolCallsByType[call.function.name] ?? 0) + tokens
162
+ calls += tokens
163
+ }
164
+ assistantTokens += Math.max(0, tokensOfContent(message) - calls)
165
+ } else if (message.role === 'tool') {
166
+ const name = nameOfCall.get(message.toolCallId) ?? 'unknown'
167
+ toolResultsByType[name] = (toolResultsByType[name] ?? 0) + tokensOfContent(message)
168
+ } else if (message.role === 'user') {
169
+ userTokens += tokensOfContent(message)
170
+ }
171
+ }
172
+ return { toolCallsByType, toolResultsByType, assistantTokens, userTokens }
173
+ }
174
+
175
+ /** Split a window into the parts that fill it. */
176
+ export function analyzeContextUsage(input: ContextUsageInput): ContextBreakdown {
177
+ const windowTokens = Math.max(0, Math.round(input.windowTokens))
178
+ const fixed: Record<(typeof CONTEXT_CATEGORY_ORDER)[number], number> = {
179
+ 'system-prompt': nonNegative(input.systemPromptTokens),
180
+ 'system-tools': nonNegative(input.systemToolTokens),
181
+ 'mcp-tools': nonNegative(input.mcpToolTokens),
182
+ 'mcp-instructions': nonNegative(input.mcpInstructionTokens),
183
+ agents: nonNegative(input.agentTokens),
184
+ memory: nonNegative(input.memoryTokens),
185
+ skills: nonNegative(input.skillTokens),
186
+ messages: 0,
187
+ }
188
+ const fixedTotal = Object.values(fixed).reduce((sum, tokens) => sum + tokens, 0)
189
+ const messages = input.messages ?? []
190
+ const bufferTokens = Math.min(bufferFor(input), windowTokens)
191
+
192
+ // The conversation is what the measured size leaves once the fixed parts
193
+ // are taken out; without a measurement it is counted from the messages.
194
+ const measured = nonNegative(input.contextTokens)
195
+ const rawMessages =
196
+ measured > 0
197
+ ? Math.max(0, measured - fixedTotal)
198
+ : messages.reduce((sum, message) => sum + tokensOfContent(message), 0)
199
+ fixed.messages = Math.min(rawMessages, Math.max(0, windowTokens - fixedTotal - bufferTokens))
200
+
201
+ const totalTokens = measured > 0 ? Math.max(measured, fixedTotal) : fixedTotal + rawMessages
202
+ const used = fixedTotal + fixed.messages
203
+ const categories: ContextCategory[] = []
204
+ for (const id of CONTEXT_CATEGORY_ORDER) {
205
+ if (fixed[id] > 0) categories.push({ id, name: NAMES[id], tokens: fixed[id], kind: 'used' })
206
+ }
207
+ const free = Math.max(0, windowTokens - used - bufferTokens)
208
+ if (bufferTokens > 0) {
209
+ categories.push({
210
+ id: 'buffer',
211
+ name: input.autoCompact ? 'Autocompact buffer' : 'Compact buffer',
212
+ tokens: bufferTokens,
213
+ kind: 'buffer',
214
+ })
215
+ }
216
+ categories.push({ id: 'free', name: 'Free space', tokens: free, kind: 'free' })
217
+
218
+ return {
219
+ categories,
220
+ windowTokens,
221
+ totalTokens,
222
+ percentage: windowTokens > 0 ? Math.round((totalTokens / windowTokens) * 100) : 0,
223
+ bufferTokens,
224
+ autoCompact: input.autoCompact,
225
+ overflowTokens: Math.max(0, totalTokens - windowTokens),
226
+ messageBreakdown: breakdownMessages(messages),
227
+ }
228
+ }
@@ -52,6 +52,11 @@ export function estimateMessageTokens(message: Message): number {
52
52
  return Math.ceil(chars / CHARS_PER_TOKEN) + rich
53
53
  }
54
54
 
55
+ /** Tokens in a piece of text by the same characters-per-token approximation. */
56
+ export function estimateTextTokens(text: string): number {
57
+ return Math.ceil(text.length / CHARS_PER_TOKEN)
58
+ }
59
+
55
60
  export function estimateMessagesTokens(messages: readonly Message[]): number {
56
61
  return messages.reduce((total, message) => total + estimateMessageTokens(message), 0)
57
62
  }
@@ -404,8 +404,13 @@ export type {
404
404
  // session between turns.
405
405
  export { abandonTurn } from './runtime/query/abandon-turn.js'
406
406
  export type { AbandonTurnOptions, SessionLocatorOptions } from './runtime/query/abandon-turn.js'
407
- export { compactSession } from './runtime/query/compact-session.js'
408
- export type { CompactSessionParams } from './runtime/query/compact-session.js'
407
+ export { CacheClock } from './runtime/cache-clock.js'
408
+ export type { CacheClockState } from './runtime/cache-clock.js'
409
+ export { compactSession, compactSessionRange } from './runtime/query/compact-session.js'
410
+ export type {
411
+ CompactSessionParams,
412
+ CompactSessionRangeParams,
413
+ } from './runtime/query/compact-session.js'
409
414
  export { prepareForkState } from './runtime/query/fork/prepare.js'
410
415
  export { listCheckpoints } from './runtime/query/fork/list.js'
411
416
  export { DecisionParser, FallbackResolver } from './runtime/decision/index.js'
@@ -1563,6 +1568,22 @@ export {
1563
1568
  // The gate is the reason this is a list rather than a fourth accident.
1564
1569
  export type { ResolvedContextWindow } from './compaction/context-window.js'
1565
1570
  export { resolveTriggerThreshold } from './compaction/context-window.js'
1571
+ // What the context window is made of, for a host that draws the answer to
1572
+ // "where did my context go".
1573
+ export {
1574
+ analyzeContextUsage,
1575
+ describeToolCatalogTokens,
1576
+ CONTEXT_CATEGORY_ORDER,
1577
+ } from './compaction/context-breakdown.js'
1578
+ export type {
1579
+ ContextBreakdown,
1580
+ ContextCategory,
1581
+ ContextCategoryId,
1582
+ ContextCategoryKind,
1583
+ ContextMessageBreakdown,
1584
+ ContextUsageInput,
1585
+ } from './compaction/context-breakdown.js'
1586
+ export { estimateTextTokens } from './compaction/token-estimate.js'
1566
1587
  export type { CompactRegionInput } from './compaction/manual.js'
1567
1588
  export type {
1568
1589
  CompactionVerificationOptions,
@@ -0,0 +1,67 @@
1
+ import type { TokenUsage } from '../types/common/index.js'
2
+
3
+ /** What the clock knows about the prompt cache after the latest model call. */
4
+ export interface CacheClockState {
5
+ /** When the last call that touched the cache finished (ms since epoch). */
6
+ readonly lastActivityAt: number
7
+ /** How long the provider keeps the cache, as that call reported it. */
8
+ readonly ttlMs: number
9
+ /**
10
+ * When the cache lapses: `lastActivityAt + ttlMs`. Only set when the call
11
+ * actually read or wrote cache; a call that touched none leaves the cache
12
+ * (and so its expiry) unknown rather than assumed.
13
+ */
14
+ readonly expiresAt: number | null
15
+ }
16
+
17
+ /**
18
+ * Tracks when a conversation's prompt cache will lapse.
19
+ *
20
+ * Fed by each completed model call. The lifetime is never guessed: a call whose
21
+ * usage carries no `cacheTtlMs` (a driver that does not report one) clears the
22
+ * clock, so nothing downstream can act on a lifetime nobody stated. Pure of
23
+ * timers: the caller passes `now`.
24
+ */
25
+ export class CacheClock {
26
+ #state: CacheClockState | null = null
27
+
28
+ /** Record a finished call. `usage` is that call's own usage, not a turn total. */
29
+ record(usage: TokenUsage, at: number): void {
30
+ if (usage.cacheTtlMs === undefined || !(usage.cacheTtlMs > 0)) {
31
+ this.#state = null
32
+ return
33
+ }
34
+ const touched = usage.cachedTokens + usage.cacheWriteTokens > 0
35
+ this.#state = {
36
+ lastActivityAt: at,
37
+ ttlMs: usage.cacheTtlMs,
38
+ expiresAt: touched ? at + usage.cacheTtlMs : null,
39
+ }
40
+ }
41
+
42
+ /** Forget everything (the conversation was replaced or its context rewritten). */
43
+ reset(): void {
44
+ this.#state = null
45
+ }
46
+
47
+ get state(): CacheClockState | null {
48
+ return this.#state
49
+ }
50
+
51
+ /** Whether the cache is still alive at `now`. False when unknown. */
52
+ warm(now: number): boolean {
53
+ const state = this.#state
54
+ return state !== null && state.expiresAt !== null && now < state.expiresAt
55
+ }
56
+
57
+ /**
58
+ * The moment `fraction` of the cache's remaining life since the last
59
+ * activity has passed: `lastActivityAt + (expiresAt - lastActivityAt) * fraction`.
60
+ * `null` when the expiry is unknown.
61
+ */
62
+ dueAt(fraction: number): number | null {
63
+ const state = this.#state
64
+ if (state === null || state.expiresAt === null) return null
65
+ return state.lastActivityAt + (state.expiresAt - state.lastActivityAt) * fraction
66
+ }
67
+ }
@@ -1,4 +1,9 @@
1
- import { type CompactNowInput, type CompactionResult, compactNow } from '../../compaction/manual.js'
1
+ import {
2
+ type CompactNowInput,
3
+ type CompactionResult,
4
+ compactNow,
5
+ compactRegion,
6
+ } from '../../compaction/manual.js'
2
7
  import { readFoldedHistory } from '../../manager/session/turn-recorder.js'
3
8
  import { NamzuError } from '../../types/errors/index.js'
4
9
  import type { MessageId, SessionId } from '../../types/ids/index.js'
@@ -10,13 +15,19 @@ import { type SessionLocatorOptions, locateSessionLog, withSessionLease } from '
10
15
  /** A compaction a host asks for between turns. */
11
16
  export interface CompactSessionParams extends Omit<CompactNowInput, 'messages' | 'onShed'> {
12
17
  readonly sessionId: SessionId
18
+ /**
19
+ * Who asked. `'manual'` (the default) is a person's request; `'idle'` is a
20
+ * host compacting a conversation nobody is using before its prompt cache
21
+ * lapses. Recorded on the `compaction` record.
22
+ */
23
+ readonly trigger?: 'manual' | 'idle'
13
24
  /** Where to find the session's log, and the lease to append under. */
14
25
  readonly locator?: SessionLocatorOptions
15
26
  }
16
27
 
17
28
  /**
18
29
  * Compact a session outside any turn. Reads the session's context from its
19
- * log, compacts it, and appends a `compaction{ trigger: 'manual' }` record
30
+ * log, compacts it, and appends a `compaction{ trigger }` record (`'manual'` unless the host says `'idle'`)
20
31
  * with no `turnId`: the messages the pass kept are named by id, the summary
21
32
  * is recorded in full, and the shed messages stay in the log for audit.
22
33
  *
@@ -26,7 +37,7 @@ export interface CompactSessionParams extends Omit<CompactNowInput, 'messages' |
26
37
  export async function compactSession(
27
38
  params: CompactSessionParams,
28
39
  ): Promise<CompactionResult | null> {
29
- const { sessionId, locator = {}, ...input } = params
40
+ const { sessionId, locator = {}, trigger = 'manual', ...input } = params
30
41
  const log = await locateSessionLog(sessionId, locator)
31
42
  return withSessionLease(log, locator.lease, async (lease) => {
32
43
  const active = await log.activeTurn({ lease })
@@ -47,6 +58,93 @@ export async function compactSession(
47
58
  })
48
59
  }
49
60
  const { summary, keptMessageIds } = compactionShape(result.messages, ids)
61
+ await log.append(lease, {
62
+ type: 'compaction',
63
+ compactionId: generateMessageId(),
64
+ strategy: input.config.strategy,
65
+ trigger,
66
+ replacesSeqRange: [1, head.pointer.seq],
67
+ summary,
68
+ keptMessageIds,
69
+ tokensBefore: 0,
70
+ tokensAfter: 0,
71
+ })
72
+ return result
73
+ })
74
+ }
75
+
76
+ /** A compaction of one span of a session's context, asked for between turns. */
77
+ export interface CompactSessionRangeParams extends CompactSessionParams {
78
+ /**
79
+ * The first message to summarise, by the id the log recorded it under.
80
+ * Omitted: the span starts at the beginning of the context.
81
+ */
82
+ readonly from?: MessageId
83
+ /**
84
+ * The message the span stops before; it and everything after it stay as
85
+ * they are. Omitted: the span runs to the end of the context.
86
+ */
87
+ readonly until?: MessageId
88
+ }
89
+
90
+ /**
91
+ * Compact one span of a session's context outside any turn.
92
+ *
93
+ * Like {@link compactSession}, but only the messages from `from` up to (not
94
+ * including) `until` are summarised; the rest of the context stays verbatim.
95
+ * A host uses it to fold away "everything before this message" or "this
96
+ * message and everything after it" without touching the other side. Pinned
97
+ * (`retain`) messages inside the span stay as they are.
98
+ *
99
+ * Throws `not_found` when `from` or `until` is not in the session's current
100
+ * context (a compaction may already have folded it away), and
101
+ * `invalid_config` when a boundary would split a tool call from its result.
102
+ * `null` when the span holds nothing worth summarising; nothing is appended
103
+ * then. Refused while a turn is active (`TurnInProgressError`).
104
+ */
105
+ export async function compactSessionRange(
106
+ params: CompactSessionRangeParams,
107
+ ): Promise<CompactionResult | null> {
108
+ const { sessionId, locator = {}, from, until, ...input } = params
109
+ const log = await locateSessionLog(sessionId, locator)
110
+ return withSessionLease(log, locator.lease, async (lease) => {
111
+ const active = await log.activeTurn({ lease })
112
+ if (active) {
113
+ throw new TurnInProgressError({ sessionId, activeTurnId: active.turnId, state: active.state })
114
+ }
115
+ const history = await readFoldedHistory(log)
116
+ const position = (id: MessageId | undefined, fallback: number): number => {
117
+ if (id === undefined) return fallback
118
+ const at = history.findIndex((entry) => entry.messageId === id)
119
+ if (at < 0) {
120
+ throw new NamzuError({
121
+ code: 'not_found',
122
+ message: `Message ${id} is not in session ${sessionId}'s current context; it may already have been summarised.`,
123
+ details: { sessionId, messageId: id },
124
+ })
125
+ }
126
+ return at
127
+ }
128
+ const start = position(from, 0)
129
+ const end = position(until, history.length)
130
+ const ids = new Map<Message, MessageId>()
131
+ for (const entry of history) if (entry.messageId) ids.set(entry.message, entry.messageId)
132
+ const result = await compactRegion({
133
+ ...input,
134
+ messages: history.map((entry) => entry.message),
135
+ start,
136
+ end,
137
+ })
138
+ if (!result) return null
139
+ const head = await log.head()
140
+ if (!head) {
141
+ throw new NamzuError({
142
+ code: 'not_found',
143
+ message: `Session ${sessionId} has an empty log; there is nothing to compact.`,
144
+ details: { sessionId },
145
+ })
146
+ }
147
+ const { summary, keptMessageIds } = compactionShape(result.messages, ids)
50
148
  await log.append(lease, {
51
149
  type: 'compaction',
52
150
  compactionId: generateMessageId(),
@@ -290,6 +290,9 @@ export async function prepareDirectCall(
290
290
  ...(providerInput && !repairUsed && preparation.inputFailure
291
291
  ? { inputFailure: preparation.inputFailure }
292
292
  : {}),
293
+ // The registry's typed reason (e.g. invalid arguments) is what a
294
+ // host keys its short label on; the message alone is wording.
295
+ ...(preparation.result.facts ? { facts: preparation.result.facts } : {}),
293
296
  }
294
297
  }
295
298
 
@@ -1201,6 +1201,14 @@ export class IterationOrchestrator {
1201
1201
  usage: recorder.tokenUsage,
1202
1202
  budget: recorder.budget?.summary(),
1203
1203
  cost: recorder.costInfo,
1204
+ ...(response.usage.cacheTtlMs !== undefined
1205
+ ? {
1206
+ cache: {
1207
+ ttlMs: response.usage.cacheTtlMs,
1208
+ touched: response.usage.cachedTokens + response.usage.cacheWriteTokens > 0,
1209
+ },
1210
+ }
1211
+ : {}),
1204
1212
  ...contextFigures,
1205
1213
  })
1206
1214
 
@@ -238,6 +238,9 @@ function usageAtLeast(current: TokenUsage | undefined, previous: TokenUsage | un
238
238
  if (current === undefined) return false
239
239
  return Object.entries(previous).every(
240
240
  ([field, amount]) =>
241
- typeof amount !== 'number' || (current[field as keyof TokenUsage] ?? 0) >= amount,
241
+ typeof amount !== 'number' ||
242
+ field === 'cacheTtlMs' ||
243
+ // `cacheTtlMs` is a per-call lifetime, not a running count: it has no order.
244
+ ((current as unknown as Record<string, number | undefined>)[field] ?? 0) >= amount,
242
245
  )
243
246
  }
@@ -10,6 +10,11 @@ const FAILURE_REASONS: readonly ToolFailureReason[] = [
10
10
  'unknown_tool',
11
11
  'timed_out',
12
12
  'invalid_input',
13
+ 'not_read',
14
+ 'changed_on_disk',
15
+ 'text_not_found',
16
+ 'not_unique',
17
+ 'invalid_arguments',
13
18
  ]
14
19
 
15
20
  const WRITE_OPERATIONS = ['created', 'updated', 'unchanged', 'wrote'] as const
@@ -105,6 +110,7 @@ export function admitToolFacts(value: unknown): ToolFacts | undefined {
105
110
  typeof value.exitCode === 'number' && Number.isSafeInteger(value.exitCode)
106
111
  ? value.exitCode
107
112
  : undefined,
113
+ exitNote: text(value.exitNote),
108
114
  timedOut: flag(value.timedOut),
109
115
  signal: text(value.signal),
110
116
  binary: