clanka 0.3.1 → 0.4.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 (69) hide show
  1. package/dist/Acp.d.ts.map +1 -1
  2. package/dist/Acp.js +3 -0
  3. package/dist/Acp.js.map +1 -1
  4. package/dist/Acp.test.js +58 -0
  5. package/dist/Acp.test.js.map +1 -1
  6. package/dist/Agent.d.ts.map +1 -1
  7. package/dist/Agent.js +86 -8
  8. package/dist/Agent.js.map +1 -1
  9. package/dist/Agent.test.js +671 -0
  10. package/dist/Agent.test.js.map +1 -1
  11. package/dist/AgentExecutor.d.ts +5 -0
  12. package/dist/AgentExecutor.d.ts.map +1 -1
  13. package/dist/AgentExecutor.js +22 -0
  14. package/dist/AgentExecutor.js.map +1 -1
  15. package/dist/AgentOutput.d.ts +49 -4
  16. package/dist/AgentOutput.d.ts.map +1 -1
  17. package/dist/AgentOutput.js +45 -0
  18. package/dist/AgentOutput.js.map +1 -1
  19. package/dist/AgentSkills.d.ts +56 -0
  20. package/dist/AgentSkills.d.ts.map +1 -0
  21. package/dist/AgentSkills.js +126 -0
  22. package/dist/AgentSkills.js.map +1 -0
  23. package/dist/AgentSkills.test.d.ts +2 -0
  24. package/dist/AgentSkills.test.d.ts.map +1 -0
  25. package/dist/AgentSkills.test.js +356 -0
  26. package/dist/AgentSkills.test.js.map +1 -0
  27. package/dist/Codex.js +1 -1
  28. package/dist/Codex.js.map +1 -1
  29. package/dist/Compaction.d.ts +342 -0
  30. package/dist/Compaction.d.ts.map +1 -0
  31. package/dist/Compaction.js +566 -0
  32. package/dist/Compaction.js.map +1 -0
  33. package/dist/Compaction.test.d.ts +2 -0
  34. package/dist/Compaction.test.d.ts.map +1 -0
  35. package/dist/Compaction.test.js +576 -0
  36. package/dist/Compaction.test.js.map +1 -0
  37. package/dist/CompactionTransport.test.d.ts +2 -0
  38. package/dist/CompactionTransport.test.d.ts.map +1 -0
  39. package/dist/CompactionTransport.test.js +123 -0
  40. package/dist/CompactionTransport.test.js.map +1 -0
  41. package/dist/Copilot.d.ts.map +1 -1
  42. package/dist/Copilot.js +7 -2
  43. package/dist/Copilot.js.map +1 -1
  44. package/dist/OutputFormatter.d.ts.map +1 -1
  45. package/dist/OutputFormatter.js +9 -0
  46. package/dist/OutputFormatter.js.map +1 -1
  47. package/dist/cli.js +13 -4
  48. package/dist/cli.js.map +1 -1
  49. package/dist/index.d.ts +5 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +5 -0
  52. package/dist/index.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/Acp.test.ts +85 -0
  55. package/src/Acp.ts +2 -0
  56. package/src/Agent.test.ts +994 -0
  57. package/src/Agent.ts +127 -6
  58. package/src/AgentExecutor.ts +27 -0
  59. package/src/AgentOutput.ts +58 -0
  60. package/src/AgentSkills.test.ts +652 -0
  61. package/src/AgentSkills.ts +155 -0
  62. package/src/Codex.ts +3 -1
  63. package/src/Compaction.test.ts +824 -0
  64. package/src/Compaction.ts +788 -0
  65. package/src/CompactionTransport.test.ts +228 -0
  66. package/src/Copilot.ts +8 -1
  67. package/src/OutputFormatter.ts +9 -0
  68. package/src/cli.ts +26 -5
  69. package/src/index.ts +6 -0
@@ -0,0 +1,566 @@
1
+ /**
2
+ * Context compaction for the shared Agent loop.
3
+ *
4
+ * Two independent mechanisms live here:
5
+ *
6
+ * 1. An always-on cap on `execute` results before they enter the Prompt
7
+ * (`capOutput`). It runs on every surface and is not affected by the
8
+ * compaction kill switch.
9
+ * 2. Auto-compaction of the live Prompt (`compactIfNeeded` before a model
10
+ * call, `compactAfterOverflow` after a context-length error). Both rewrite
11
+ * the Prompt to `system + <compaction-summary> user message + kept tail`.
12
+ *
13
+ * @since 1.0.0
14
+ */
15
+ import * as Context from "effect/Context";
16
+ import * as Effect from "effect/Effect";
17
+ import { identity } from "effect/Function";
18
+ import * as Layer from "effect/Layer";
19
+ import * as Option from "effect/Option";
20
+ import * as Predicate from "effect/Predicate";
21
+ import * as Stream from "effect/Stream";
22
+ import * as AiError from "effect/unstable/ai/AiError";
23
+ import * as LanguageModel from "effect/unstable/ai/LanguageModel";
24
+ import * as Prompt from "effect/unstable/ai/Prompt";
25
+ /**
26
+ * @since 1.0.0
27
+ * @category Configuration
28
+ */
29
+ export const defaultConfig = {
30
+ enabled: true,
31
+ contextWindow: 236_000,
32
+ reserveTokens: 16_000,
33
+ keepRecentTokens: 20_000,
34
+ };
35
+ /**
36
+ * @since 1.0.0
37
+ * @category Configuration
38
+ */
39
+ export class CompactionConfig extends Context.Reference("clanka/Compaction/CompactionConfig", { defaultValue: () => defaultConfig }) {
40
+ static layer = (options) => Layer.succeed(CompactionConfig, { ...defaultConfig, ...options });
41
+ }
42
+ /**
43
+ * Wraps the summarizer model call so a provider can apply request overrides
44
+ * (e.g. Copilot's `max_output_tokens`). Defaults to the identity.
45
+ *
46
+ * @since 1.0.0
47
+ * @category Configuration
48
+ */
49
+ export class SummarizerTransform extends Context.Reference("clanka/Compaction/SummarizerTransform", {
50
+ defaultValue: () => identity,
51
+ }) {
52
+ }
53
+ // =============================================================================
54
+ // Constants
55
+ // =============================================================================
56
+ /**
57
+ * Hard cap, in characters, applied to every `execute` success string before it
58
+ * is appended to the Prompt. Always on.
59
+ *
60
+ * @since 1.0.0
61
+ * @category Constants
62
+ */
63
+ export const executeOutputCapChars = 32_000;
64
+ /** Cap applied to `execute` results rendered into the summarizer input. */
65
+ const summarizerToolResultCapChars = 2_000;
66
+ /**
67
+ * Cap applied to `execute` results that remain in the kept tail when the tail
68
+ * itself still exceeds `keepRecentTokens` after reasoning has been dropped.
69
+ *
70
+ * @since 1.0.0
71
+ * @category Constants
72
+ */
73
+ export const keptToolResultStubChars = 2_000;
74
+ /**
75
+ * Maximum output tokens requested by providers that support a summary cap.
76
+ * Copilot uses this limit; Codex rejects max_output_tokens and has no
77
+ * configured summary output-token cap.
78
+ *
79
+ * @since 1.0.0
80
+ * @category Constants
81
+ */
82
+ export const summarizerMaxOutputTokens = 4_000;
83
+ /**
84
+ * The synthetic summary user message is wrapped in these tags so a later
85
+ * compaction can locate it without a new Prompt schema.
86
+ *
87
+ * @since 1.0.0
88
+ * @category Constants
89
+ */
90
+ export const summaryOpenTag = "<compaction-summary>";
91
+ /**
92
+ * @since 1.0.0
93
+ * @category Constants
94
+ */
95
+ export const summaryCloseTag = "</compaction-summary>";
96
+ /**
97
+ * System prompt included in the summarizer's Prompt.
98
+ *
99
+ * @since 1.0.0
100
+ * @category Constants
101
+ */
102
+ export const summarizerSystem = `You compact the conversation history of a coding agent so the agent can continue with less context.
103
+ Reply with the summary only. No preamble, no commentary, no markdown fences.`;
104
+ /**
105
+ * Cap a string to `maxChars` characters, keeping the head and the tail and
106
+ * inserting a marker in between. Inputs at or under the cap are returned
107
+ * unchanged.
108
+ *
109
+ * @since 1.0.0
110
+ * @category Cap
111
+ */
112
+ export const capOutput = (output, maxChars = executeOutputCapChars) => {
113
+ const charsBefore = output.length;
114
+ if (charsBefore <= maxChars) {
115
+ return { output, capped: false, charsBefore, charsAfter: charsBefore };
116
+ }
117
+ const headChars = Math.floor(maxChars / 2);
118
+ const tailChars = maxChars - headChars;
119
+ const omitted = charsBefore - maxChars;
120
+ const marker = `\n\n[... output capped: ${omitted} of ${charsBefore} chars omitted from the middle. ` +
121
+ `Do not re-run this as is. Narrow the read instead: use readFile with startLine/endLine, ` +
122
+ `search for what you need, or print smaller logs ...]\n\n`;
123
+ const capped = output.slice(0, headChars) + marker + output.slice(charsBefore - tailChars);
124
+ return {
125
+ output: capped,
126
+ capped: true,
127
+ charsBefore,
128
+ charsAfter: capped.length,
129
+ };
130
+ };
131
+ // =============================================================================
132
+ // Token accounting
133
+ // =============================================================================
134
+ /**
135
+ * Cheap token estimate for a Prompt: JSON length / 4. Used when no
136
+ * `contextTokens` usage has been observed yet (first turn, ACP session load)
137
+ * and for sizing the kept tail.
138
+ *
139
+ * @since 1.0.0
140
+ * @category Tokens
141
+ */
142
+ export const estimateTokens = (prompt) => Math.ceil(JSON.stringify(prompt.content).length / 4);
143
+ /**
144
+ * Token estimate for a single message. Same measure as `estimateTokens`.
145
+ *
146
+ * @since 1.0.0
147
+ * @category Tokens
148
+ */
149
+ export const estimateMessageTokens = (message) => Math.ceil(JSON.stringify(message).length / 4);
150
+ /**
151
+ * Whether the threshold trigger fires for the next model call.
152
+ *
153
+ * `contextTokens` is the `inputTokens.total` from the most recent `finish`
154
+ * part, or `undefined` when no usage has been observed yet, in which case
155
+ * `estimateTokens(prompt)` is used instead.
156
+ *
157
+ * Always `false` when `config.enabled` is `false`.
158
+ *
159
+ * @since 1.0.0
160
+ * @category Tokens
161
+ */
162
+ export const shouldCompact = (options) => {
163
+ if (!options.config.enabled)
164
+ return false;
165
+ const tokens = options.contextTokens ?? estimateTokens(options.prompt);
166
+ return tokens > options.config.contextWindow - options.config.reserveTokens;
167
+ };
168
+ // =============================================================================
169
+ // Overflow detection
170
+ // =============================================================================
171
+ const contextLengthPattern = /context[_ ]?(length|window)|too many tokens|prompt is too long|prompt token count|exceeds the (context|token|input )?limit|input token limit|exceeds the model'?s? (context|token|input)/i;
172
+ const contextLengthCode = "context_length_exceeded";
173
+ /**
174
+ * Provider error code from `reason.metadata`, either at the top level or
175
+ * under a provider key (`metadata.openai.errorCode`).
176
+ */
177
+ const errorCode = (metadata) => {
178
+ if (!Predicate.isObject(metadata))
179
+ return undefined;
180
+ if (Predicate.isString(metadata.errorCode))
181
+ return metadata.errorCode;
182
+ for (const value of Object.values(metadata)) {
183
+ if (Predicate.isObject(value) && Predicate.isString(value.errorCode)) {
184
+ return value.errorCode;
185
+ }
186
+ }
187
+ return undefined;
188
+ };
189
+ /**
190
+ * Whether an `AiError` is a context-length overflow from a known provider
191
+ * (Codex / Copilot), as opposed to any other request or transport failure.
192
+ *
193
+ * Any request, unknown or provider error counts when it carries a 413 status,
194
+ * a `context_length_exceeded` code, or a context-length description. These
195
+ * errors are never retried as-is; the Agent compacts first.
196
+ *
197
+ * @since 1.0.0
198
+ * @category Overflow
199
+ */
200
+ export const isContextLengthError = (error) => {
201
+ const reason = error.reason;
202
+ switch (reason._tag) {
203
+ case "InvalidRequestError":
204
+ case "UnknownError":
205
+ case "InternalProviderError":
206
+ return (reason.http?.response?.status === 413 ||
207
+ errorCode(reason.metadata) === contextLengthCode ||
208
+ (reason.description !== undefined &&
209
+ contextLengthPattern.test(reason.description)));
210
+ default:
211
+ return false;
212
+ }
213
+ };
214
+ const summaryText = (message) => {
215
+ if (message.role !== "user" || message.content.length !== 1) {
216
+ return Option.none();
217
+ }
218
+ const part = message.content[0];
219
+ if (part.type !== "text")
220
+ return Option.none();
221
+ const text = part.text.trim();
222
+ if (!text.startsWith(summaryOpenTag) || !text.endsWith(summaryCloseTag)) {
223
+ return Option.none();
224
+ }
225
+ return Option.some(text
226
+ .slice(summaryOpenTag.length, text.length - summaryCloseTag.length)
227
+ .trim());
228
+ };
229
+ /**
230
+ * Whether a message is the synthetic `<compaction-summary>` user message
231
+ * produced by `rewrite`. Surfaces that replay history (ACP) skip it.
232
+ *
233
+ * @since 1.0.0
234
+ * @category Cut points
235
+ */
236
+ export const isSummaryMessage = (message) => Option.isSome(summaryText(message));
237
+ /**
238
+ * Peel the system message and a previous summary off a prompt, returning the
239
+ * remaining conversation messages.
240
+ */
241
+ const peel = (prompt) => {
242
+ let system = Option.none();
243
+ let previousSummary = Option.none();
244
+ const messages = [];
245
+ for (const message of prompt.content) {
246
+ if (message.role === "system") {
247
+ if (Option.isNone(system))
248
+ system = Option.some(message);
249
+ continue;
250
+ }
251
+ if (messages.length === 0 && Option.isNone(previousSummary)) {
252
+ const summary = summaryText(message);
253
+ if (Option.isSome(summary)) {
254
+ previousSummary = summary;
255
+ continue;
256
+ }
257
+ }
258
+ messages.push(message);
259
+ }
260
+ return { system, previousSummary, messages };
261
+ };
262
+ /**
263
+ * Choose the cut point for a compaction.
264
+ *
265
+ * Walks back from the newest message, accumulating `estimateMessageTokens`,
266
+ * and stops at the first message boundary where the accumulated tail would
267
+ * exceed `keepRecentTokens`. The cut is then adjusted so that an `execute`
268
+ * tool-call (assistant message) and its tool-result (tool message) are never
269
+ * separated: if the boundary falls between them the assistant message is kept
270
+ * as well. The kept tail always contains at least the newest complete unit.
271
+ *
272
+ * Returns `None` when there is nothing to summarize, which happens when the
273
+ * kept tail is the whole prompt (ignoring the system message and a previous
274
+ * summary message). Callers treat `None` as a no-op.
275
+ *
276
+ * @since 1.0.0
277
+ * @category Cut points
278
+ */
279
+ export const split = (prompt, keepRecentTokens) => {
280
+ const { system, previousSummary, messages } = peel(prompt);
281
+ if (messages.length === 0)
282
+ return Option.none();
283
+ let cut = messages.length;
284
+ let tokens = 0;
285
+ while (cut > 0) {
286
+ const messageTokens = estimateMessageTokens(messages[cut - 1]);
287
+ // Always keep the newest message, even when it alone exceeds the budget.
288
+ if (cut < messages.length && tokens + messageTokens > keepRecentTokens) {
289
+ break;
290
+ }
291
+ tokens += messageTokens;
292
+ cut--;
293
+ }
294
+ // Never leave a tool result without its call at the head of the tail.
295
+ while (cut > 0 && messages[cut].role === "tool") {
296
+ cut--;
297
+ }
298
+ if (cut === 0)
299
+ return Option.none();
300
+ return Option.some({
301
+ system,
302
+ previousSummary,
303
+ toSummarize: messages.slice(0, cut),
304
+ kept: messages.slice(cut),
305
+ });
306
+ };
307
+ /**
308
+ * Find the text of a previous compaction summary in a Prompt, if present.
309
+ *
310
+ * @since 1.0.0
311
+ * @category Cut points
312
+ */
313
+ export const findPreviousSummary = (prompt) => peel(prompt).previousSummary;
314
+ /**
315
+ * Shrink a kept tail that still exceeds `keepRecentTokens`:
316
+ *
317
+ * 1. Drop `reasoning` parts from assistant messages, oldest first, until the
318
+ * tail fits.
319
+ * 2. If it still does not fit, stub `execute` tool-result strings in place,
320
+ * oldest first, using `capOutput(result, keptToolResultStubChars)`.
321
+ *
322
+ * Message order, message count and tool-call / tool-result ids are never
323
+ * changed, so call/result pairing stays valid. Returns the input unchanged
324
+ * when it already fits.
325
+ *
326
+ * @since 1.0.0
327
+ * @category Cut points
328
+ */
329
+ export const trimKept = (kept, keepRecentTokens) => {
330
+ const sizes = kept.map(estimateMessageTokens);
331
+ let total = sizes.reduce((n, size) => n + size, 0);
332
+ if (total <= keepRecentTokens)
333
+ return kept;
334
+ const result = kept.slice();
335
+ const replace = (index, message) => {
336
+ result[index] = message;
337
+ const size = estimateMessageTokens(message);
338
+ total += size - sizes[index];
339
+ sizes[index] = size;
340
+ };
341
+ for (let i = 0; i < result.length; i++) {
342
+ if (total <= keepRecentTokens)
343
+ break;
344
+ const message = result[i];
345
+ if (message.role !== "assistant" ||
346
+ !message.content.some((part) => part.type === "reasoning")) {
347
+ continue;
348
+ }
349
+ replace(i, Prompt.makeMessage("assistant", {
350
+ content: message.content.filter((part) => part.type !== "reasoning"),
351
+ options: message.options,
352
+ }));
353
+ }
354
+ for (let i = 0; i < result.length; i++) {
355
+ if (total <= keepRecentTokens)
356
+ break;
357
+ const message = result[i];
358
+ if (message.role !== "tool")
359
+ continue;
360
+ let changed = false;
361
+ const content = message.content.map((part) => {
362
+ if (part.type !== "tool-result" ||
363
+ typeof part.result !== "string" ||
364
+ part.result.length <= keptToolResultStubChars) {
365
+ return part;
366
+ }
367
+ changed = true;
368
+ return Prompt.makePart("tool-result", {
369
+ id: part.id,
370
+ name: part.name,
371
+ isFailure: part.isFailure,
372
+ providerExecuted: part.providerExecuted,
373
+ result: capOutput(part.result, keptToolResultStubChars).output,
374
+ options: part.options,
375
+ });
376
+ });
377
+ if (changed) {
378
+ replace(i, Prompt.makeMessage("tool", { content, options: message.options }));
379
+ }
380
+ }
381
+ return result;
382
+ };
383
+ // =============================================================================
384
+ // Prompt rewrite
385
+ // =============================================================================
386
+ const renderResult = (result) => {
387
+ const text = typeof result === "string" ? result : JSON.stringify(result);
388
+ return capOutput(text ?? "", summarizerToolResultCapChars).output;
389
+ };
390
+ const renderMessage = (message) => {
391
+ switch (message.role) {
392
+ case "system":
393
+ return "";
394
+ case "user": {
395
+ const text = message.content
396
+ .flatMap((part) => (part.type === "text" ? [part.text] : []))
397
+ .join("\n");
398
+ return `[user]\n${text}`;
399
+ }
400
+ case "assistant": {
401
+ const lines = [];
402
+ for (const part of message.content) {
403
+ switch (part.type) {
404
+ case "text":
405
+ lines.push(part.text);
406
+ break;
407
+ case "tool-call": {
408
+ const params = part.params;
409
+ const script = typeof params?.script === "string"
410
+ ? params.script
411
+ : JSON.stringify(part.params);
412
+ lines.push(`[executed script]\n${script}`);
413
+ break;
414
+ }
415
+ default:
416
+ break;
417
+ }
418
+ }
419
+ return `[assistant]\n${lines.join("\n")}`;
420
+ }
421
+ case "tool": {
422
+ const lines = message.content.flatMap((part) => part.type === "tool-result"
423
+ ? [
424
+ `[script output${part.isFailure ? " (error)" : ""}]\n${renderResult(part.result)}`,
425
+ ]
426
+ : []);
427
+ return lines.join("\n");
428
+ }
429
+ }
430
+ };
431
+ /**
432
+ * Build the Prompt sent to the summarizer model call.
433
+ *
434
+ * The conversation is rendered as text using the OpenCode-style summary
435
+ * template. `reasoning` parts are omitted, `execute` tool results are capped
436
+ * to `summarizerToolResultCapChars`, and `previousSummary` is folded in so the
437
+ * new summary supersedes it. No tools, no system prompt from the agent.
438
+ *
439
+ * @since 1.0.0
440
+ * @category Rewrite
441
+ */
442
+ export const summarizerPrompt = (options) => {
443
+ const conversation = options.messages
444
+ .map(renderMessage)
445
+ .filter((text) => text.length > 0)
446
+ .join("\n\n");
447
+ const previous = Option.match(options.previousSummary, {
448
+ onNone: () => "",
449
+ onSome: (summary) => `A previous summary already covers the conversation before the messages below. Fold it into the new summary so nothing is lost:
450
+
451
+ <previous-summary>
452
+ ${summary}
453
+ </previous-summary>
454
+
455
+ `,
456
+ });
457
+ const text = `Summarize the conversation below so the coding agent can continue the task without the original messages.
458
+
459
+ Write the summary as a compact briefing. Include:
460
+ - The user's goals, and any constraints or preferences they stated
461
+ - What has been done so far: concrete file paths, commands, and their results
462
+ - Key findings and decisions, with the reasons behind them
463
+ - Errors encountered and how they were resolved
464
+ - What remains to be done, in order
465
+
466
+ Be precise. Prefer exact identifiers (paths, symbols, commands) over prose. Do not include commentary about the summary itself.
467
+
468
+ ${previous}<conversation>
469
+ ${conversation}
470
+ </conversation>`;
471
+ return Prompt.make(text).pipe(Prompt.setSystem(summarizerSystem));
472
+ };
473
+ /**
474
+ * Wrap a summary in the `<compaction-summary>` tags used for the synthetic
475
+ * user message.
476
+ *
477
+ * @since 1.0.0
478
+ * @category Rewrite
479
+ */
480
+ export const wrapSummary = (summary) => `${summaryOpenTag}\n${summary}\n${summaryCloseTag}`;
481
+ /**
482
+ * Assemble the compacted Prompt: `[system?, user(wrapSummary(summary)),
483
+ * ...kept]`. The system message is passed through untouched.
484
+ *
485
+ * @since 1.0.0
486
+ * @category Rewrite
487
+ */
488
+ export const rewrite = (options) => Prompt.fromMessages([
489
+ ...Option.toArray(options.system),
490
+ Prompt.makeMessage("user", {
491
+ content: [
492
+ Prompt.makePart("text", { text: wrapSummary(options.summary) }),
493
+ ],
494
+ }),
495
+ ...options.kept,
496
+ ]);
497
+ /**
498
+ * Run one compaction of `prompt`.
499
+ *
500
+ * Returns `None` without calling the model when compaction is disabled or
501
+ * when `split` finds nothing to summarize. Otherwise `onStart` runs, the
502
+ * summarizer is called with `streamText` (the Codex backend rejects
503
+ * non-streaming requests) through `SummarizerTransform`, and the prompt is
504
+ * rewritten to `system + summary + trimKept(kept)`.
505
+ *
506
+ * Fails with the summarizer's `AiError`. Callers decide whether that is fatal.
507
+ *
508
+ * @since 1.0.0
509
+ * @category Compaction
510
+ */
511
+ export const compact = Effect.fnUntraced(function* (options) {
512
+ const config = yield* CompactionConfig;
513
+ if (!config.enabled)
514
+ return Option.none();
515
+ const parts = split(options.prompt, config.keepRecentTokens);
516
+ if (Option.isNone(parts))
517
+ return Option.none();
518
+ const { system, previousSummary, toSummarize, kept } = parts.value;
519
+ if (options.onStart) {
520
+ yield* options.onStart(options.reason);
521
+ }
522
+ const ai = yield* LanguageModel.LanguageModel;
523
+ const transform = yield* SummarizerTransform;
524
+ const summary = (yield* transform(ai
525
+ .streamText({
526
+ prompt: summarizerPrompt({ previousSummary, messages: toSummarize }),
527
+ })
528
+ .pipe(Stream.runFold(() => "", (text, part) => part.type === "text-delta" ? text + part.delta : text)))).trim();
529
+ if (summary.length === 0) {
530
+ return yield* AiError.make({
531
+ module: "clanka/Compaction",
532
+ method: "compact",
533
+ reason: new AiError.InvalidOutputError({
534
+ description: "The summarizer returned no text",
535
+ }),
536
+ });
537
+ }
538
+ const rewritten = rewrite({
539
+ system,
540
+ summary,
541
+ kept: trimKept(kept, config.keepRecentTokens),
542
+ });
543
+ return Option.some({
544
+ reason: options.reason,
545
+ prompt: rewritten,
546
+ tokensBefore: estimateTokens(options.prompt),
547
+ tokensAfter: estimateTokens(rewritten),
548
+ });
549
+ });
550
+ /**
551
+ * Compact before the next model call when `shouldCompact` fires.
552
+ *
553
+ * Returns `None` when compaction is disabled, not needed, or a no-op. A
554
+ * failing summarizer is swallowed here: the caller proceeds with the
555
+ * uncompacted prompt and relies on the overflow path.
556
+ *
557
+ * @since 1.0.0
558
+ * @category Compaction
559
+ */
560
+ export const compactIfNeeded = Effect.fnUntraced(function* (options) {
561
+ const config = yield* CompactionConfig;
562
+ if (!shouldCompact({ ...options, config }))
563
+ return Option.none();
564
+ return yield* compact({ ...options, reason: "threshold" }).pipe(Effect.catch((error) => Effect.logWarning("Compaction failed, continuing with the uncompacted prompt", error).pipe(Effect.as(Option.none()))));
565
+ });
566
+ //# sourceMappingURL=Compaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Compaction.js","sourceRoot":"","sources":["../src/Compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAA;AACrD,OAAO,KAAK,aAAa,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,MAAM,MAAM,2BAA2B,CAAA;AA6BnD;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAA4B;IACpD,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,OAAO;IACtB,aAAa,EAAE,MAAM;IACrB,gBAAgB,EAAE,MAAM;CACzB,CAAA;AAED;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,OAAO,CAAC,SAAS,CACrD,oCAAoC,EACpC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CACtC;IACC,MAAM,CAAU,KAAK,GAAG,CACtB,OAAyC,EACrB,EAAE,CACtB,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;CACpE;AAED;;;;;;GAMG;AACH,MAAM,OAAO,mBAAoB,SAAQ,OAAO,CAAC,SAAS,CAExD,uCAAuC,EAAE;IACzC,YAAY,EAAE,GAAG,EAAE,CAAC,QAAQ;CAC7B,CAAC;CAAG;AAEL,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAA;AAE3C,2EAA2E;AAC3E,MAAM,4BAA4B,GAAG,KAAK,CAAA;AAE1C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAA;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,sBAAsB,CAAA;AAEpD;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;6EAC6C,CAAA;AAsB7E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,MAAc,EACd,QAAQ,GAAW,qBAAqB,EAC7B,EAAE;IACb,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAA;IACjC,IAAI,WAAW,IAAI,QAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;IACxE,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAA;IAC1C,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,MAAM,OAAO,GAAG,WAAW,GAAG,QAAQ,CAAA;IACtC,MAAM,MAAM,GACV,2BAA2B,OAAO,OAAO,WAAW,kCAAkC;QACtF,0FAA0F;QAC1F,0DAA0D,CAAA;IAC5D,MAAM,MAAM,GACV,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IAC7E,OAAO;QACL,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,IAAI;QACZ,WAAW;QACX,UAAU,EAAE,MAAM,CAAC,MAAM;KAC1B,CAAA;AACH,CAAC,CAAA;AAED,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAqB,EAAU,EAAE,CAC9D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAuB,EAAU,EAAE,CACvE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAE/C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAI7B,EAAW,EAAE;IACZ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IACzC,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,IAAI,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACtE,OAAO,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAA;AAC7E,CAAC,CAAA;AAED,gFAAgF;AAChF,qBAAqB;AACrB,gFAAgF;AAEhF,MAAM,oBAAoB,GACxB,2LAA2L,CAAA;AAE7L,MAAM,iBAAiB,GAAG,yBAAyB,CAAA;AAEnD;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,QAAiB,EAAsB,EAAE;IAC1D,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IACnD,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC,SAAS,CAAA;IACrE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YACrE,OAAO,KAAK,CAAC,SAAS,CAAA;QACxB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAsB,EAAW,EAAE;IACtE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;IAC3B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,qBAAqB,CAAC;QAC3B,KAAK,cAAc,CAAC;QACpB,KAAK,uBAAuB;YAC1B,OAAO,CACL,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,GAAG;gBACrC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,iBAAiB;gBAChD,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS;oBAC/B,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CACjD,CAAA;QACH;YACE,OAAO,KAAK,CAAA;IAChB,CAAC;AACH,CAAC,CAAA;AA2BD,MAAM,WAAW,GAAG,CAAC,OAAuB,EAAyB,EAAE;IACrE,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACtB,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAA;IAChC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACxE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACtB,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAChB,IAAI;SACD,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;SAClE,IAAI,EAAE,CACV,CAAA;AACH,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAuB,EAAW,EAAE,CACnE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAA;AAErC;;;GAGG;AACH,MAAM,IAAI,GAAG,CAAC,MAAqB,EAAE,EAAE;IACrC,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,EAAwB,CAAA;IAChD,IAAI,eAAe,GAAG,MAAM,CAAC,IAAI,EAAU,CAAA;IAC3C,MAAM,QAAQ,GAA0B,EAAE,CAAA;IAC1C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;gBAAE,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACxD,SAAQ;QACV,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;YAC5D,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;YACpC,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,eAAe,GAAG,OAAO,CAAA;gBACzB,SAAQ;YACV,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAA;AAC9C,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,MAAqB,EACrB,gBAAwB,EACF,EAAE;IACxB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IAC1D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IAE/C,IAAI,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAA;IACzB,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,aAAa,GAAG,qBAAqB,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAE,CAAC,CAAA;QAC/D,yEAAyE;QACzE,IAAI,GAAG,GAAG,QAAQ,CAAC,MAAM,IAAI,MAAM,GAAG,aAAa,GAAG,gBAAgB,EAAE,CAAC;YACvE,MAAK;QACP,CAAC;QACD,MAAM,IAAI,aAAa,CAAA;QACvB,GAAG,EAAE,CAAA;IACP,CAAC;IACD,sEAAsE;IACtE,OAAO,GAAG,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACjD,GAAG,EAAE,CAAA;IACP,CAAC;IACD,IAAI,GAAG,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IAEnC,OAAO,MAAM,CAAC,IAAI,CAAC;QACjB,MAAM;QACN,eAAe;QACf,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;QACnC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;KAC1B,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,MAAqB,EACE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAA;AAExD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,IAAmC,EACnC,gBAAwB,EACO,EAAE;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IAC7C,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAA;IAClD,IAAI,KAAK,IAAI,gBAAgB;QAAE,OAAO,IAAI,CAAA;IAE1C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,OAAuB,EAAE,EAAE;QACzD,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAA;QACvB,MAAM,IAAI,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAA;QAC3C,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAE,CAAA;QAC7B,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IACrB,CAAC,CAAA;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,KAAK,IAAI,gBAAgB;YAAE,MAAK;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;QAC1B,IACE,OAAO,CAAC,IAAI,KAAK,WAAW;YAC5B,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,EAC1D,CAAC;YACD,SAAQ;QACV,CAAC;QACD,OAAO,CACL,CAAC,EACD,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE;YAC9B,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;YACpE,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,KAAK,IAAI,gBAAgB;YAAE,MAAK;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;QAC1B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;YAAE,SAAQ;QACrC,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAC3C,IACE,IAAI,CAAC,IAAI,KAAK,aAAa;gBAC3B,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAC/B,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,uBAAuB,EAC7C,CAAC;gBACD,OAAO,IAAI,CAAA;YACb,CAAC;YACD,OAAO,GAAG,IAAI,CAAA;YACd,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE;gBACpC,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;gBACvC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,MAAM;gBAC9D,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CACL,CAAC,EACD,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAClE,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,MAAM,YAAY,GAAG,CAAC,MAAe,EAAU,EAAE;IAC/C,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACzE,OAAO,SAAS,CAAC,IAAI,IAAI,EAAE,EAAE,4BAA4B,CAAC,CAAC,MAAM,CAAA;AACnE,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,CAAC,OAAuB,EAAU,EAAE;IACxD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,EAAE,CAAA;QACX,KAAK,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO;iBACzB,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;iBAC5D,IAAI,CAAC,IAAI,CAAC,CAAA;YACb,OAAO,WAAW,IAAI,EAAE,CAAA;QAC1B,CAAC;QACD,KAAK,WAAW,EAAE,CAAC;YACjB,MAAM,KAAK,GAAkB,EAAE,CAAA;YAC/B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACnC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;oBAClB,KAAK,MAAM;wBACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;wBACrB,MAAK;oBACP,KAAK,WAAW,EAAE,CAAC;wBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAuC,CAAA;wBAC3D,MAAM,MAAM,GACV,OAAO,MAAM,EAAE,MAAM,KAAK,QAAQ;4BAChC,CAAC,CAAC,MAAM,CAAC,MAAM;4BACf,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;wBACjC,KAAK,CAAC,IAAI,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAA;wBAC1C,MAAK;oBACP,CAAC;oBACD;wBACE,MAAK;gBACT,CAAC;YACH,CAAC;YACD,OAAO,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;QAC3C,CAAC;QACD,KAAK,MAAM,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAC7C,IAAI,CAAC,IAAI,KAAK,aAAa;gBACzB,CAAC,CAAC;oBACE,iBAAiB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;iBACnF;gBACH,CAAC,CAAC,EAAE,CACP,CAAA;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAGhC,EAAiB,EAAE;IAClB,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ;SAClC,GAAG,CAAC,aAAa,CAAC;SAClB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SACjC,IAAI,CAAC,MAAM,CAAC,CAAA;IAEf,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE;QACrD,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE;QAChB,MAAM,EAAE,CACN,OAAO,EACP,EAAE,CAAC;;;EAGP,OAAO;;;CAGR;KACE,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG;;;;;;;;;;;EAWb,QAAQ;EACR,YAAY;gBACE,CAAA;IAEd,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAA;AACnE,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,EAAU,EAAE,CACrD,GAAG,cAAc,KAAK,OAAO,KAAK,eAAe,EAAE,CAAA;AAErD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAIvB,EAAiB,EAAE,CAClB,MAAM,CAAC,YAAY,CAAC;IAClB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;IACjC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE;QACzB,OAAO,EAAE;YACP,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;SAChE;KACF,CAAC;IACF,GAAG,OAAO,CAAC,IAAI;CAChB,CAAC,CAAA;AA0BJ;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,OAAO,GAahB,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAA;IACtC,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAC5D,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IAC9C,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,CAAA;IAElE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,aAAa,CAAA;IAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAA;IAC5C,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,SAAS,CAC/B,EAAE;SACC,UAAU,CAAC;QACV,MAAM,EAAE,gBAAgB,CAAC,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;KACrE,CAAC;SACD,IAAI,CACH,MAAM,CAAC,OAAO,CACZ,GAAG,EAAE,CAAC,EAAE,EACR,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CACb,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CACxD,CACF,CACJ,CAAC,CAAC,IAAI,EAAE,CAAA;IAET,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;YACzB,MAAM,EAAE,mBAAmB;YAC3B,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,IAAI,OAAO,CAAC,kBAAkB,CAAC;gBACrC,WAAW,EAAE,iCAAiC;aAC/C,CAAC;SACH,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC;QACxB,MAAM;QACN,OAAO;QACP,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;KAC9C,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC;QACjB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;QAC5C,WAAW,EAAE,cAAc,CAAC,SAAS,CAAC;KACvC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GASxB,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAA;IACtC,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IAChE,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,CAC7D,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACrB,MAAM,CAAC,UAAU,CACf,2DAA2D,EAC3D,KAAK,CACN,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAoB,CAAC,CAAC,CACnD,CACF,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Compaction.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Compaction.test.d.ts","sourceRoot":"","sources":["../src/Compaction.test.ts"],"names":[],"mappings":""}