@antaif3ng/til-work 0.1.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 (150) hide show
  1. package/README.md +573 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +7 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/core/agent.d.ts +78 -0
  7. package/dist/core/agent.d.ts.map +1 -0
  8. package/dist/core/agent.js +372 -0
  9. package/dist/core/agent.js.map +1 -0
  10. package/dist/core/compaction.d.ts +40 -0
  11. package/dist/core/compaction.d.ts.map +1 -0
  12. package/dist/core/compaction.js +228 -0
  13. package/dist/core/compaction.js.map +1 -0
  14. package/dist/core/config.d.ts +54 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/config.js +257 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/core/llm.d.ts +29 -0
  19. package/dist/core/llm.d.ts.map +1 -0
  20. package/dist/core/llm.js +553 -0
  21. package/dist/core/llm.js.map +1 -0
  22. package/dist/core/markdown.d.ts +20 -0
  23. package/dist/core/markdown.d.ts.map +1 -0
  24. package/dist/core/markdown.js +173 -0
  25. package/dist/core/markdown.js.map +1 -0
  26. package/dist/core/memory.d.ts +30 -0
  27. package/dist/core/memory.d.ts.map +1 -0
  28. package/dist/core/memory.js +163 -0
  29. package/dist/core/memory.js.map +1 -0
  30. package/dist/core/pricing.d.ts +21 -0
  31. package/dist/core/pricing.d.ts.map +1 -0
  32. package/dist/core/pricing.js +70 -0
  33. package/dist/core/pricing.js.map +1 -0
  34. package/dist/core/session-manager.d.ts +83 -0
  35. package/dist/core/session-manager.d.ts.map +1 -0
  36. package/dist/core/session-manager.js +250 -0
  37. package/dist/core/session-manager.js.map +1 -0
  38. package/dist/core/session.d.ts +76 -0
  39. package/dist/core/session.d.ts.map +1 -0
  40. package/dist/core/session.js +270 -0
  41. package/dist/core/session.js.map +1 -0
  42. package/dist/core/skills.d.ts +49 -0
  43. package/dist/core/skills.d.ts.map +1 -0
  44. package/dist/core/skills.js +232 -0
  45. package/dist/core/skills.js.map +1 -0
  46. package/dist/core/system-prompt.d.ts +17 -0
  47. package/dist/core/system-prompt.d.ts.map +1 -0
  48. package/dist/core/system-prompt.js +77 -0
  49. package/dist/core/system-prompt.js.map +1 -0
  50. package/dist/core/tool-permissions.d.ts +12 -0
  51. package/dist/core/tool-permissions.d.ts.map +1 -0
  52. package/dist/core/tool-permissions.js +71 -0
  53. package/dist/core/tool-permissions.js.map +1 -0
  54. package/dist/core/types.d.ts +157 -0
  55. package/dist/core/types.d.ts.map +1 -0
  56. package/dist/core/types.js +21 -0
  57. package/dist/core/types.js.map +1 -0
  58. package/dist/extensions/builtin/mcp.d.ts +61 -0
  59. package/dist/extensions/builtin/mcp.d.ts.map +1 -0
  60. package/dist/extensions/builtin/mcp.js +407 -0
  61. package/dist/extensions/builtin/mcp.js.map +1 -0
  62. package/dist/extensions/index.d.ts +4 -0
  63. package/dist/extensions/index.d.ts.map +1 -0
  64. package/dist/extensions/index.js +3 -0
  65. package/dist/extensions/index.js.map +1 -0
  66. package/dist/extensions/loader.d.ts +19 -0
  67. package/dist/extensions/loader.d.ts.map +1 -0
  68. package/dist/extensions/loader.js +118 -0
  69. package/dist/extensions/loader.js.map +1 -0
  70. package/dist/extensions/runner.d.ts +28 -0
  71. package/dist/extensions/runner.d.ts.map +1 -0
  72. package/dist/extensions/runner.js +77 -0
  73. package/dist/extensions/runner.js.map +1 -0
  74. package/dist/extensions/types.d.ts +84 -0
  75. package/dist/extensions/types.d.ts.map +1 -0
  76. package/dist/extensions/types.js +6 -0
  77. package/dist/extensions/types.js.map +1 -0
  78. package/dist/index.d.ts +21 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +15 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/main.d.ts +5 -0
  83. package/dist/main.d.ts.map +1 -0
  84. package/dist/main.js +355 -0
  85. package/dist/main.js.map +1 -0
  86. package/dist/modes/interactive.d.ts +6 -0
  87. package/dist/modes/interactive.d.ts.map +1 -0
  88. package/dist/modes/interactive.js +961 -0
  89. package/dist/modes/interactive.js.map +1 -0
  90. package/dist/modes/oneshot.d.ts +8 -0
  91. package/dist/modes/oneshot.d.ts.map +1 -0
  92. package/dist/modes/oneshot.js +71 -0
  93. package/dist/modes/oneshot.js.map +1 -0
  94. package/dist/tools/bash.d.ts +3 -0
  95. package/dist/tools/bash.d.ts.map +1 -0
  96. package/dist/tools/bash.js +104 -0
  97. package/dist/tools/bash.js.map +1 -0
  98. package/dist/tools/edit.d.ts +3 -0
  99. package/dist/tools/edit.d.ts.map +1 -0
  100. package/dist/tools/edit.js +63 -0
  101. package/dist/tools/edit.js.map +1 -0
  102. package/dist/tools/file-manager.d.ts +3 -0
  103. package/dist/tools/file-manager.d.ts.map +1 -0
  104. package/dist/tools/file-manager.js +85 -0
  105. package/dist/tools/file-manager.js.map +1 -0
  106. package/dist/tools/index.d.ts +17 -0
  107. package/dist/tools/index.d.ts.map +1 -0
  108. package/dist/tools/index.js +42 -0
  109. package/dist/tools/index.js.map +1 -0
  110. package/dist/tools/read.d.ts +3 -0
  111. package/dist/tools/read.d.ts.map +1 -0
  112. package/dist/tools/read.js +65 -0
  113. package/dist/tools/read.js.map +1 -0
  114. package/dist/tools/system-info.d.ts +3 -0
  115. package/dist/tools/system-info.d.ts.map +1 -0
  116. package/dist/tools/system-info.js +101 -0
  117. package/dist/tools/system-info.js.map +1 -0
  118. package/dist/tools/web-fetch.d.ts +3 -0
  119. package/dist/tools/web-fetch.d.ts.map +1 -0
  120. package/dist/tools/web-fetch.js +117 -0
  121. package/dist/tools/web-fetch.js.map +1 -0
  122. package/dist/tools/web-search.d.ts +9 -0
  123. package/dist/tools/web-search.d.ts.map +1 -0
  124. package/dist/tools/web-search.js +124 -0
  125. package/dist/tools/web-search.js.map +1 -0
  126. package/dist/tools/write.d.ts +3 -0
  127. package/dist/tools/write.d.ts.map +1 -0
  128. package/dist/tools/write.js +30 -0
  129. package/dist/tools/write.js.map +1 -0
  130. package/dist/utils/autocomplete.d.ts +23 -0
  131. package/dist/utils/autocomplete.d.ts.map +1 -0
  132. package/dist/utils/autocomplete.js +191 -0
  133. package/dist/utils/autocomplete.js.map +1 -0
  134. package/dist/utils/file-processor.d.ts +19 -0
  135. package/dist/utils/file-processor.d.ts.map +1 -0
  136. package/dist/utils/file-processor.js +86 -0
  137. package/dist/utils/file-processor.js.map +1 -0
  138. package/dist/utils/path.d.ts +8 -0
  139. package/dist/utils/path.d.ts.map +1 -0
  140. package/dist/utils/path.js +60 -0
  141. package/dist/utils/path.js.map +1 -0
  142. package/dist/utils/shell.d.ts +6 -0
  143. package/dist/utils/shell.d.ts.map +1 -0
  144. package/dist/utils/shell.js +64 -0
  145. package/dist/utils/shell.js.map +1 -0
  146. package/dist/utils/truncate.d.ts +12 -0
  147. package/dist/utils/truncate.d.ts.map +1 -0
  148. package/dist/utils/truncate.js +46 -0
  149. package/dist/utils/truncate.js.map +1 -0
  150. package/package.json +58 -0
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Agent runtime: drives the LLM ↔ tool execution loop.
3
+ * Dual-loop architecture matching pi-mono:
4
+ * Outer loop — processes follow-up messages after agent would stop
5
+ * Inner loop — processes tool calls + steering (interrupt) messages
6
+ */
7
+ import { streamLLM } from "./llm.js";
8
+ import { compact, calculateContextTokens, isContextOverflow, shouldCompact, estimateAllTokens, DEFAULT_COMPACTION_SETTINGS, } from "./compaction.js";
9
+ export class Agent {
10
+ state;
11
+ listeners = new Set();
12
+ abortController;
13
+ maxTurns;
14
+ contextWindow;
15
+ compactionSettings;
16
+ compactionSummary;
17
+ getSteeringMessages;
18
+ getFollowUpMessages;
19
+ onToolCallRequest;
20
+ constructor(opts) {
21
+ this.maxTurns = opts.maxTurns ?? 200;
22
+ this.contextWindow = opts.contextWindow ?? opts.model.contextWindow ?? 128000;
23
+ this.compactionSettings = opts.compactionSettings ?? DEFAULT_COMPACTION_SETTINGS;
24
+ this.getSteeringMessages = opts.getSteeringMessages;
25
+ this.getFollowUpMessages = opts.getFollowUpMessages;
26
+ this.onToolCallRequest = opts.onToolCallRequest;
27
+ this.state = {
28
+ systemPrompt: opts.systemPrompt,
29
+ model: opts.model,
30
+ thinkingLevel: opts.thinkingLevel ?? "off",
31
+ tools: opts.tools ?? [],
32
+ messages: [],
33
+ isStreaming: false,
34
+ };
35
+ }
36
+ get currentState() {
37
+ return this.state;
38
+ }
39
+ subscribe(fn) {
40
+ this.listeners.add(fn);
41
+ return () => this.listeners.delete(fn);
42
+ }
43
+ setSystemPrompt(prompt) {
44
+ this.state.systemPrompt = prompt;
45
+ }
46
+ setModel(model) {
47
+ this.state.model = model;
48
+ }
49
+ setTools(tools) {
50
+ this.state.tools = tools;
51
+ }
52
+ clearMessages() {
53
+ this.state.messages = [];
54
+ }
55
+ /**
56
+ * Replace the message history (used when restoring a persisted session).
57
+ */
58
+ setMessages(messages) {
59
+ this.state.messages = [...messages];
60
+ }
61
+ abort() {
62
+ this.abortController?.abort();
63
+ }
64
+ /**
65
+ * Start a new agent loop with a user prompt.
66
+ */
67
+ async prompt(input) {
68
+ if (this.state.isStreaming) {
69
+ throw new Error("Agent is already processing. Wait for completion.");
70
+ }
71
+ const userMsg = {
72
+ role: "user",
73
+ content: input,
74
+ timestamp: Date.now(),
75
+ };
76
+ this.state.messages.push(userMsg);
77
+ await this.runLoop([userMsg]);
78
+ }
79
+ /**
80
+ * Continue the agent loop from the current context without adding a
81
+ * new message. Used for retry / resume scenarios.
82
+ */
83
+ async continue() {
84
+ if (this.state.isStreaming) {
85
+ throw new Error("Agent is already processing. Wait for completion.");
86
+ }
87
+ if (this.state.messages.length === 0) {
88
+ throw new Error("Cannot continue: no messages in context.");
89
+ }
90
+ const last = this.state.messages[this.state.messages.length - 1];
91
+ if (last.role === "assistant") {
92
+ throw new Error("Cannot continue from an assistant message.");
93
+ }
94
+ await this.runLoop([]);
95
+ }
96
+ // ── Core dual-loop ──
97
+ async runLoop(newMessages) {
98
+ this.abortController = new AbortController();
99
+ this.state.isStreaming = true;
100
+ this.state.error = undefined;
101
+ this.emit({ type: "agent_start" });
102
+ // Emit message events for the prompt(s) that started this loop
103
+ for (const msg of newMessages) {
104
+ this.emit({ type: "message_start", message: msg });
105
+ this.emit({ type: "message_end", message: msg });
106
+ }
107
+ try {
108
+ let turns = 0;
109
+ let pendingMessages = (await this.getSteeringMessages?.()) ?? [];
110
+ // Outer loop: continues when follow-up messages arrive after agent would stop
111
+ outer: while (true) {
112
+ let hasMoreToolCalls = true;
113
+ // Inner loop: process tool calls + steering messages
114
+ while (hasMoreToolCalls || pendingMessages.length > 0) {
115
+ if (turns >= this.maxTurns)
116
+ break outer;
117
+ turns++;
118
+ this.emit({ type: "turn_start" });
119
+ // Inject any pending (steering / follow-up) messages
120
+ if (pendingMessages.length > 0) {
121
+ for (const msg of pendingMessages) {
122
+ this.emit({ type: "message_start", message: msg });
123
+ this.emit({ type: "message_end", message: msg });
124
+ this.state.messages.push(msg);
125
+ }
126
+ pendingMessages = [];
127
+ }
128
+ // Stream LLM response
129
+ const assistantMsg = await this.streamAssistantResponse();
130
+ this.state.messages.push(assistantMsg);
131
+ this.emit({ type: "message_end", message: assistantMsg });
132
+ // Overflow → compact and retry this turn
133
+ if (assistantMsg.stopReason === "error" &&
134
+ isContextOverflow(assistantMsg, this.contextWindow)) {
135
+ // Remove the failed error message
136
+ this.state.messages.pop();
137
+ const retried = await this.runCompaction("overflow");
138
+ if (retried)
139
+ continue;
140
+ // If compaction can't help, fall through to error handling
141
+ this.state.messages.push(assistantMsg);
142
+ }
143
+ // Abort / error → stop immediately (like pi-mono agent-loop:144-148)
144
+ if (assistantMsg.stopReason === "error" ||
145
+ assistantMsg.stopReason === "aborted") {
146
+ this.emit({ type: "turn_end", message: assistantMsg, toolResults: [] });
147
+ this.emit({ type: "agent_end", messages: this.state.messages });
148
+ return;
149
+ }
150
+ // Extract tool calls
151
+ const toolCalls = assistantMsg.content.filter((c) => c.type === "toolCall");
152
+ hasMoreToolCalls = toolCalls.length > 0;
153
+ const toolResults = [];
154
+ let steeringAfterTools = null;
155
+ if (hasMoreToolCalls) {
156
+ const execution = await this.executeToolCalls(toolCalls);
157
+ toolResults.push(...execution.toolResults);
158
+ steeringAfterTools = execution.steeringMessages ?? null;
159
+ for (const result of toolResults) {
160
+ this.state.messages.push(result);
161
+ }
162
+ }
163
+ this.emit({ type: "turn_end", message: assistantMsg, toolResults });
164
+ // Threshold compaction check after each turn
165
+ await this.checkThresholdCompaction(assistantMsg);
166
+ // Gather pending messages for the next inner-loop iteration
167
+ if (steeringAfterTools && steeringAfterTools.length > 0) {
168
+ pendingMessages = steeringAfterTools;
169
+ }
170
+ else {
171
+ pendingMessages =
172
+ (await this.getSteeringMessages?.()) ?? [];
173
+ }
174
+ }
175
+ // Agent would stop here. Check for follow-up messages.
176
+ const followUp = (await this.getFollowUpMessages?.()) ?? [];
177
+ if (followUp.length > 0) {
178
+ pendingMessages = followUp;
179
+ continue;
180
+ }
181
+ break;
182
+ }
183
+ this.emit({ type: "agent_end", messages: this.state.messages });
184
+ }
185
+ catch (err) {
186
+ if (err.message === "aborted" ||
187
+ err.name === "AbortError" ||
188
+ this.abortController?.signal.aborted) {
189
+ this.state.error = "Request was aborted";
190
+ }
191
+ else {
192
+ this.state.error = err.message || String(err);
193
+ }
194
+ const errorMsg = {
195
+ role: "assistant",
196
+ content: [{ type: "text", text: `Error: ${this.state.error}` }],
197
+ stopReason: "error",
198
+ errorMessage: this.state.error,
199
+ timestamp: Date.now(),
200
+ };
201
+ this.state.messages.push(errorMsg);
202
+ this.emit({ type: "agent_end", messages: [errorMsg] });
203
+ }
204
+ finally {
205
+ this.state.isStreaming = false;
206
+ this.abortController = undefined;
207
+ }
208
+ }
209
+ // ── LLM streaming ──
210
+ async streamAssistantResponse() {
211
+ const toolDefs = this.state.tools.map((t) => ({
212
+ name: t.name,
213
+ description: t.description,
214
+ parameters: t.parameters,
215
+ }));
216
+ return new Promise((resolve, reject) => {
217
+ const callbacks = {
218
+ onToken: (text) => {
219
+ this.emit({
220
+ type: "message_update",
221
+ message: {
222
+ role: "assistant",
223
+ content: [{ type: "text", text }],
224
+ timestamp: Date.now(),
225
+ },
226
+ delta: text,
227
+ });
228
+ },
229
+ onDone: (msg) => resolve(msg),
230
+ onError: (err) => reject(err),
231
+ };
232
+ streamLLM(this.state.model, this.state.systemPrompt, this.state.messages, toolDefs, callbacks, this.abortController?.signal).catch(reject);
233
+ });
234
+ }
235
+ // ── Tool execution with steering support ──
236
+ async executeToolCalls(toolCalls) {
237
+ const results = [];
238
+ let steeringMessages;
239
+ for (let i = 0; i < toolCalls.length; i++) {
240
+ const tc = toolCalls[i];
241
+ const tool = this.state.tools.find((t) => t.name === tc.name);
242
+ if (!tool) {
243
+ const notFound = this.makeToolResult(tc, [{ type: "text", text: `Tool not found: ${tc.name}` }], true);
244
+ results.push(notFound);
245
+ this.emit({ type: "tool_execution_start", toolCallId: tc.id, toolName: tc.name, args: tc.arguments });
246
+ this.emit({ type: "tool_execution_end", toolCallId: tc.id, toolName: tc.name, result: notFound.content, isError: true });
247
+ continue;
248
+ }
249
+ // Permission check before execution
250
+ if (this.onToolCallRequest) {
251
+ try {
252
+ const perm = await this.onToolCallRequest(tc.name, tc.arguments);
253
+ if (perm.block) {
254
+ const reason = perm.reason || "Tool execution blocked by permission check";
255
+ const errorContent = [{ type: "text", text: reason }];
256
+ results.push(this.makeToolResult(tc, errorContent, true));
257
+ this.emit({ type: "tool_execution_start", toolCallId: tc.id, toolName: tc.name, args: tc.arguments });
258
+ this.emit({ type: "tool_execution_end", toolCallId: tc.id, toolName: tc.name, result: errorContent, isError: true });
259
+ continue;
260
+ }
261
+ }
262
+ catch { /* permission check failed — allow execution */ }
263
+ }
264
+ this.emit({ type: "tool_execution_start", toolCallId: tc.id, toolName: tc.name, args: tc.arguments });
265
+ try {
266
+ const result = await tool.execute(tc.id, tc.arguments, this.abortController?.signal, (partial) => {
267
+ this.emit({
268
+ type: "tool_execution_update",
269
+ toolCallId: tc.id,
270
+ toolName: tc.name,
271
+ partialResult: partial,
272
+ });
273
+ });
274
+ results.push(this.makeToolResult(tc, result.content, false));
275
+ this.emit({
276
+ type: "tool_execution_end",
277
+ toolCallId: tc.id,
278
+ toolName: tc.name,
279
+ result: result.content,
280
+ isError: false,
281
+ });
282
+ }
283
+ catch (err) {
284
+ const errorContent = [{ type: "text", text: err.message || String(err) }];
285
+ results.push(this.makeToolResult(tc, errorContent, true));
286
+ this.emit({
287
+ type: "tool_execution_end",
288
+ toolCallId: tc.id,
289
+ toolName: tc.name,
290
+ result: errorContent,
291
+ isError: true,
292
+ });
293
+ }
294
+ // Check for steering messages after each tool (skip remaining if interrupted)
295
+ if (this.getSteeringMessages) {
296
+ const steering = await this.getSteeringMessages();
297
+ if (steering.length > 0) {
298
+ steeringMessages = steering;
299
+ // Skip remaining tool calls
300
+ for (const skipped of toolCalls.slice(i + 1)) {
301
+ results.push(this.skipToolCall(skipped));
302
+ }
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ return { toolResults: results, steeringMessages };
308
+ }
309
+ skipToolCall(tc) {
310
+ const content = [{ type: "text", text: "Skipped due to queued user message." }];
311
+ this.emit({ type: "tool_execution_start", toolCallId: tc.id, toolName: tc.name, args: tc.arguments });
312
+ this.emit({ type: "tool_execution_end", toolCallId: tc.id, toolName: tc.name, result: content, isError: true });
313
+ return this.makeToolResult(tc, content, true);
314
+ }
315
+ makeToolResult(tc, content, isError) {
316
+ return {
317
+ role: "toolResult",
318
+ toolCallId: tc.id,
319
+ toolName: tc.name,
320
+ content,
321
+ isError,
322
+ timestamp: Date.now(),
323
+ };
324
+ }
325
+ // ── Compaction ──
326
+ async checkThresholdCompaction(lastAssistant) {
327
+ if (!this.compactionSettings.enabled)
328
+ return;
329
+ const contextTokens = lastAssistant.usage
330
+ ? calculateContextTokens(lastAssistant.usage)
331
+ : estimateAllTokens(this.state.messages);
332
+ if (shouldCompact(contextTokens, this.contextWindow, this.compactionSettings)) {
333
+ await this.runCompaction("threshold");
334
+ }
335
+ }
336
+ async runCompaction(reason) {
337
+ if (this.state.messages.length < 4)
338
+ return false;
339
+ this.emit({ type: "compaction_start", reason });
340
+ try {
341
+ const result = await compact(this.state.messages, this.state.model, this.compactionSettings, this.compactionSummary);
342
+ this.compactionSummary = result.summary;
343
+ // Replace messages: inject summary as a system-like user message, then kept messages
344
+ const summaryMsg = {
345
+ role: "user",
346
+ content: `[Previous conversation summary]\n\n${result.summary}`,
347
+ timestamp: Date.now(),
348
+ };
349
+ this.state.messages = [summaryMsg, ...result.keptMessages];
350
+ this.emit({
351
+ type: "compaction_end",
352
+ tokensBefore: result.tokensBefore,
353
+ tokensAfter: result.tokensAfter,
354
+ });
355
+ return true;
356
+ }
357
+ catch {
358
+ this.emit({
359
+ type: "compaction_end",
360
+ tokensBefore: estimateAllTokens(this.state.messages),
361
+ tokensAfter: estimateAllTokens(this.state.messages),
362
+ });
363
+ return false;
364
+ }
365
+ }
366
+ emit(event) {
367
+ for (const listener of this.listeners) {
368
+ listener(event);
369
+ }
370
+ }
371
+ }
372
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Context compaction engine.
3
+ * When the conversation grows beyond the model's context window, older messages
4
+ * are summarised by the LLM and replaced with a compact summary.
5
+ *
6
+ * Architecture mirrors pi-mono packages/coding-agent/src/core/compaction/.
7
+ */
8
+ import type { AssistantMessage, Message, ModelConfig, Usage } from "./types.js";
9
+ export interface CompactionSettings {
10
+ enabled: boolean;
11
+ /** Tokens reserved for the next response (threshold gap) */
12
+ reserveTokens: number;
13
+ /** Minimum tokens to keep from the recent end of the conversation */
14
+ keepRecentTokens: number;
15
+ }
16
+ export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
17
+ export declare function estimateTokens(message: Message): number;
18
+ export declare function estimateAllTokens(messages: Message[]): number;
19
+ export declare function calculateContextTokens(usage: Usage): number;
20
+ export declare function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean;
21
+ export declare function isContextOverflow(message: AssistantMessage, contextWindow?: number): boolean;
22
+ export interface CutResult {
23
+ /** Index of the first message to keep */
24
+ keepFromIndex: number;
25
+ /** Messages to be summarised (before keepFromIndex) */
26
+ summariseMessages: Message[];
27
+ /** Messages to keep (from keepFromIndex onwards) */
28
+ keptMessages: Message[];
29
+ }
30
+ export declare function findCutPoint(messages: Message[], keepRecentTokens: number): CutResult;
31
+ export declare function generateSummary(messages: Message[], model: ModelConfig, previousSummary?: string): Promise<string>;
32
+ export interface CompactionResult {
33
+ summary: string;
34
+ keptMessages: Message[];
35
+ tokensBefore: number;
36
+ tokensAfter: number;
37
+ previousSummary?: string;
38
+ }
39
+ export declare function compact(messages: Message[], model: ModelConfig, settings: CompactionSettings, previousSummary?: string): Promise<CompactionResult>;
40
+ //# sourceMappingURL=compaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/core/compaction.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAe,KAAK,EAAE,MAAM,YAAY,CAAC;AAI7F,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,2BAA2B,EAAE,kBAIzC,CAAC;AAIF,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAmCvD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAE7D;AAID,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE3D;AAID,wBAAgB,aAAa,CAC5B,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,kBAAkB,GAC1B,OAAO,CAGT;AAuBD,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,gBAAgB,EACzB,aAAa,CAAC,EAAE,MAAM,GACpB,OAAO,CAgBT;AAID,MAAM,WAAW,SAAS;IACzB,yCAAyC;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,iBAAiB,EAAE,OAAO,EAAE,CAAC;IAC7B,oDAAoD;IACpD,YAAY,EAAE,OAAO,EAAE,CAAC;CACxB;AAED,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,OAAO,EAAE,EACnB,gBAAgB,EAAE,MAAM,GACtB,SAAS,CA2CX;AAsED,wBAAsB,eAAe,CACpC,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,WAAW,EAClB,eAAe,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAID,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,OAAO,CAC5B,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAa3B"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Context compaction engine.
3
+ * When the conversation grows beyond the model's context window, older messages
4
+ * are summarised by the LLM and replaced with a compact summary.
5
+ *
6
+ * Architecture mirrors pi-mono packages/coding-agent/src/core/compaction/.
7
+ */
8
+ import { completeLLM } from "./llm.js";
9
+ export const DEFAULT_COMPACTION_SETTINGS = {
10
+ enabled: true,
11
+ reserveTokens: 16384,
12
+ keepRecentTokens: 20000,
13
+ };
14
+ // ── Token estimation (chars / 4 heuristic, same as pi-mono) ──
15
+ export function estimateTokens(message) {
16
+ let chars = 0;
17
+ switch (message.role) {
18
+ case "user": {
19
+ if (typeof message.content === "string") {
20
+ chars = message.content.length;
21
+ }
22
+ else {
23
+ for (const c of message.content) {
24
+ if (c.type === "text")
25
+ chars += c.text.length;
26
+ else
27
+ chars += 4800; // image placeholder
28
+ }
29
+ }
30
+ break;
31
+ }
32
+ case "assistant": {
33
+ for (const c of message.content) {
34
+ if (c.type === "text")
35
+ chars += c.text.length;
36
+ else if (c.type === "thinking")
37
+ chars += c.thinking.length;
38
+ else if (c.type === "toolCall") {
39
+ chars += c.name.length + JSON.stringify(c.arguments).length;
40
+ }
41
+ }
42
+ break;
43
+ }
44
+ case "toolResult": {
45
+ for (const c of message.content) {
46
+ if (c.type === "text")
47
+ chars += c.text.length;
48
+ else
49
+ chars += 4800;
50
+ }
51
+ break;
52
+ }
53
+ }
54
+ return Math.ceil(chars / 4);
55
+ }
56
+ export function estimateAllTokens(messages) {
57
+ return messages.reduce((sum, m) => sum + estimateTokens(m), 0);
58
+ }
59
+ // ── Context token calculation from real usage data ──
60
+ export function calculateContextTokens(usage) {
61
+ return usage.totalTokens || (usage.input + usage.output + usage.cacheRead + usage.cacheWrite);
62
+ }
63
+ // ── Threshold check ──
64
+ export function shouldCompact(contextTokens, contextWindow, settings) {
65
+ if (!settings.enabled)
66
+ return false;
67
+ return contextTokens > contextWindow - settings.reserveTokens;
68
+ }
69
+ // ── Overflow detection ──
70
+ const OVERFLOW_PATTERNS = [
71
+ /prompt is too long/i,
72
+ /maximum context length/i,
73
+ /context.length.*exceeded/i,
74
+ /token limit/i,
75
+ /context window/i,
76
+ /too many tokens/i,
77
+ /input.*too long/i,
78
+ /request too large/i,
79
+ /max_tokens.*exceeded/i,
80
+ /content.*length.*limit/i,
81
+ /exceeds.*model.*maximum/i,
82
+ /reduce.*prompt/i,
83
+ /Please reduce/i,
84
+ /context_length_exceeded/i,
85
+ // Cerebras-style: 400/413 with no body
86
+ /^4(00|13)\s*(status code)?\s*\(no body\)/i,
87
+ ];
88
+ export function isContextOverflow(message, contextWindow) {
89
+ if (message.stopReason === "error" && message.errorMessage) {
90
+ if (OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage))) {
91
+ return true;
92
+ }
93
+ }
94
+ // Silent overflow: successful response but usage exceeds context window
95
+ if (contextWindow && message.stopReason !== "error" && message.usage) {
96
+ const inputTokens = message.usage.input + message.usage.cacheRead;
97
+ if (inputTokens > contextWindow) {
98
+ return true;
99
+ }
100
+ }
101
+ return false;
102
+ }
103
+ export function findCutPoint(messages, keepRecentTokens) {
104
+ let accumulatedTokens = 0;
105
+ let cutIndex = 0;
106
+ // Walk backwards accumulating tokens
107
+ for (let i = messages.length - 1; i >= 0; i--) {
108
+ accumulatedTokens += estimateTokens(messages[i]);
109
+ if (accumulatedTokens >= keepRecentTokens) {
110
+ cutIndex = i;
111
+ break;
112
+ }
113
+ }
114
+ // Don't cut on a toolResult — move forward to include the full turn
115
+ while (cutIndex < messages.length && messages[cutIndex].role === "toolResult") {
116
+ cutIndex++;
117
+ }
118
+ // Don't cut inside an assistant+toolResult pair — if we land on an assistant
119
+ // message that has tool calls, include its tool results too
120
+ if (cutIndex > 0 && cutIndex < messages.length) {
121
+ const prev = messages[cutIndex - 1];
122
+ if (prev.role === "assistant") {
123
+ const hasToolCalls = prev.content.some((c) => c.type === "toolCall");
124
+ if (hasToolCalls) {
125
+ while (cutIndex < messages.length && messages[cutIndex].role === "toolResult") {
126
+ cutIndex++;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ // Ensure we're keeping at least 1 message
132
+ if (cutIndex >= messages.length)
133
+ cutIndex = Math.max(0, messages.length - 1);
134
+ // Ensure we're actually cutting something
135
+ if (cutIndex <= 0)
136
+ cutIndex = Math.min(1, messages.length);
137
+ return {
138
+ keepFromIndex: cutIndex,
139
+ summariseMessages: messages.slice(0, cutIndex),
140
+ keptMessages: messages.slice(cutIndex),
141
+ };
142
+ }
143
+ // ── Summary generation ──
144
+ const SUMMARIZATION_SYSTEM_PROMPT = `You are a conversation summariser. Given a conversation, produce a structured summary that captures all important context needed for the AI assistant to continue effectively.
145
+
146
+ Use this format:
147
+
148
+ ## Goal
149
+ Brief description of what the user is trying to accomplish.
150
+
151
+ ## Progress
152
+ - Done: what has been completed
153
+ - In Progress: what is currently being worked on
154
+ - Blocked: any blockers or issues
155
+
156
+ ## Key Decisions
157
+ Important decisions or preferences expressed during the conversation.
158
+
159
+ ## Next Steps
160
+ What should happen next based on the conversation.
161
+
162
+ ## Critical Context
163
+ Any file paths, variable names, error messages, or technical details that must not be lost.`;
164
+ const SUMMARIZATION_PROMPT = `Please summarise the following conversation. Preserve all technical details, file paths, decisions, and context needed to continue the task.
165
+
166
+ <conversation>
167
+ {CONVERSATION}
168
+ </conversation>`;
169
+ const UPDATE_SUMMARIZATION_PROMPT = `Please update the following summary with the new conversation content. Merge and deduplicate information while preserving all important context.
170
+
171
+ <previous-summary>
172
+ {PREVIOUS_SUMMARY}
173
+ </previous-summary>
174
+
175
+ <new-conversation>
176
+ {CONVERSATION}
177
+ </new-conversation>`;
178
+ function serializeMessages(messages) {
179
+ const parts = [];
180
+ for (const msg of messages) {
181
+ if (msg.role === "user") {
182
+ const text = typeof msg.content === "string"
183
+ ? msg.content
184
+ : msg.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
185
+ parts.push(`[User]: ${text}`);
186
+ }
187
+ else if (msg.role === "assistant") {
188
+ const texts = [];
189
+ for (const c of msg.content) {
190
+ if (c.type === "text")
191
+ texts.push(c.text);
192
+ else if (c.type === "toolCall")
193
+ texts.push(`[Tool Call: ${c.name}(${JSON.stringify(c.arguments).slice(0, 200)})]`);
194
+ }
195
+ parts.push(`[Assistant]: ${texts.join("\n")}`);
196
+ }
197
+ else if (msg.role === "toolResult") {
198
+ const text = msg.content
199
+ .filter((c) => c.type === "text")
200
+ .map((c) => c.text)
201
+ .join("\n")
202
+ .slice(0, 500);
203
+ parts.push(`[Tool Result (${msg.toolName})]: ${text}`);
204
+ }
205
+ }
206
+ return parts.join("\n\n");
207
+ }
208
+ export async function generateSummary(messages, model, previousSummary) {
209
+ const conversation = serializeMessages(messages);
210
+ const maxTokens = Math.floor(0.8 * (DEFAULT_COMPACTION_SETTINGS.reserveTokens));
211
+ const prompt = previousSummary
212
+ ? UPDATE_SUMMARIZATION_PROMPT
213
+ .replace("{PREVIOUS_SUMMARY}", previousSummary)
214
+ .replace("{CONVERSATION}", conversation)
215
+ : SUMMARIZATION_PROMPT.replace("{CONVERSATION}", conversation);
216
+ return completeLLM(model, SUMMARIZATION_SYSTEM_PROMPT, prompt, maxTokens);
217
+ }
218
+ export async function compact(messages, model, settings, previousSummary) {
219
+ const tokensBefore = estimateAllTokens(messages);
220
+ const { summariseMessages, keptMessages } = findCutPoint(messages, settings.keepRecentTokens);
221
+ if (summariseMessages.length === 0) {
222
+ return { summary: previousSummary || "", keptMessages: messages, tokensBefore, tokensAfter: tokensBefore };
223
+ }
224
+ const summary = await generateSummary(summariseMessages, model, previousSummary);
225
+ const tokensAfter = estimateAllTokens(keptMessages) + Math.ceil(summary.length / 4);
226
+ return { summary, keptMessages, tokensBefore, tokensAfter, previousSummary };
227
+ }
228
+ //# sourceMappingURL=compaction.js.map