@aexol/spectral 0.9.58 → 0.9.60

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 (90) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +43 -0
  3. package/dist/agent/index.d.ts +6 -1
  4. package/dist/agent/index.d.ts.map +1 -1
  5. package/dist/agent/index.js +133 -14
  6. package/dist/extensions/kanban-bridge.d.ts.map +1 -1
  7. package/dist/extensions/kanban-bridge.js +21 -1
  8. package/dist/extensions/web/index.d.ts +10 -0
  9. package/dist/extensions/web/index.d.ts.map +1 -0
  10. package/dist/extensions/web/index.js +11 -0
  11. package/dist/extensions/web/tools/fetch.d.ts +3 -0
  12. package/dist/extensions/web/tools/fetch.d.ts.map +1 -0
  13. package/dist/extensions/web/tools/fetch.js +80 -0
  14. package/dist/extensions/web/utils/fetcher.d.ts +34 -0
  15. package/dist/extensions/web/utils/fetcher.d.ts.map +1 -0
  16. package/dist/extensions/web/utils/fetcher.js +289 -0
  17. package/dist/extensions/web/utils/parser.d.ts +15 -0
  18. package/dist/extensions/web/utils/parser.d.ts.map +1 -0
  19. package/dist/extensions/web/utils/parser.js +205 -0
  20. package/dist/memory/branch.d.ts.map +1 -1
  21. package/dist/memory/branch.js +16 -8
  22. package/dist/memory/commands/status.d.ts.map +1 -1
  23. package/dist/memory/commands/status.js +3 -2
  24. package/dist/memory/config.d.ts +12 -0
  25. package/dist/memory/config.d.ts.map +1 -1
  26. package/dist/memory/config.js +21 -2
  27. package/dist/memory/hooks/compaction-trigger.d.ts.map +1 -1
  28. package/dist/memory/hooks/compaction-trigger.js +19 -3
  29. package/dist/memory/index.d.ts.map +1 -1
  30. package/dist/memory/index.js +2 -0
  31. package/dist/memory/testing/random-text.js +1 -1
  32. package/dist/memory/tool-output-compressor.d.ts +14 -20
  33. package/dist/memory/tool-output-compressor.d.ts.map +1 -1
  34. package/dist/memory/tool-output-compressor.js +391 -137
  35. package/dist/memory/tools/compact-context.d.ts +5 -0
  36. package/dist/memory/tools/compact-context.d.ts.map +1 -0
  37. package/dist/memory/tools/compact-context.js +772 -0
  38. package/dist/relay/dispatcher.d.ts +1 -1
  39. package/dist/relay/dispatcher.d.ts.map +1 -1
  40. package/dist/relay/dispatcher.js +61 -1
  41. package/dist/sdk/coding-agent/core/agent-session.d.ts +56 -3
  42. package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
  43. package/dist/sdk/coding-agent/core/agent-session.js +408 -210
  44. package/dist/sdk/coding-agent/core/compaction/compaction.d.ts +57 -7
  45. package/dist/sdk/coding-agent/core/compaction/compaction.d.ts.map +1 -1
  46. package/dist/sdk/coding-agent/core/compaction/compaction.js +146 -27
  47. package/dist/sdk/coding-agent/core/compaction/dcp-lite.d.ts +24 -0
  48. package/dist/sdk/coding-agent/core/compaction/dcp-lite.d.ts.map +1 -0
  49. package/dist/sdk/coding-agent/core/compaction/dcp-lite.js +411 -0
  50. package/dist/sdk/coding-agent/core/compaction/index.d.ts +2 -0
  51. package/dist/sdk/coding-agent/core/compaction/index.d.ts.map +1 -1
  52. package/dist/sdk/coding-agent/core/compaction/index.js +2 -0
  53. package/dist/sdk/coding-agent/core/compaction/policy.d.ts +71 -0
  54. package/dist/sdk/coding-agent/core/compaction/policy.d.ts.map +1 -0
  55. package/dist/sdk/coding-agent/core/compaction/policy.js +147 -0
  56. package/dist/sdk/coding-agent/core/extensions/native-extensions.d.ts.map +1 -1
  57. package/dist/sdk/coding-agent/core/extensions/native-extensions.js +9 -0
  58. package/dist/sdk/coding-agent/core/extensions/types.d.ts +17 -0
  59. package/dist/sdk/coding-agent/core/extensions/types.d.ts.map +1 -1
  60. package/dist/sdk/coding-agent/core/settings-manager.d.ts +4 -10
  61. package/dist/sdk/coding-agent/core/settings-manager.d.ts.map +1 -1
  62. package/dist/sdk/coding-agent/core/settings-manager.js +17 -17
  63. package/dist/sdk/coding-agent/index.d.ts +1 -1
  64. package/dist/sdk/coding-agent/index.d.ts.map +1 -1
  65. package/dist/server/agent-bridge.d.ts +12 -5
  66. package/dist/server/agent-bridge.d.ts.map +1 -1
  67. package/dist/server/agent-bridge.js +65 -17
  68. package/dist/server/handlers/paths-home.d.ts +11 -0
  69. package/dist/server/handlers/paths-home.d.ts.map +1 -0
  70. package/dist/server/handlers/paths-home.js +10 -0
  71. package/dist/server/handlers/paths-list.d.ts +24 -0
  72. package/dist/server/handlers/paths-list.d.ts.map +1 -0
  73. package/dist/server/handlers/paths-list.js +56 -0
  74. package/dist/server/handlers/paths-pick-directory.d.ts.map +1 -1
  75. package/dist/server/handlers/paths-pick-directory.js +2 -1
  76. package/dist/server/handlers/sessions.d.ts +11 -1
  77. package/dist/server/handlers/sessions.d.ts.map +1 -1
  78. package/dist/server/handlers/sessions.js +22 -2
  79. package/dist/server/handlers/settings.d.ts +18 -1
  80. package/dist/server/handlers/settings.d.ts.map +1 -1
  81. package/dist/server/handlers/settings.js +63 -13
  82. package/dist/server/session-stream.d.ts +65 -37
  83. package/dist/server/session-stream.d.ts.map +1 -1
  84. package/dist/server/session-stream.js +525 -119
  85. package/dist/server/storage.d.ts +3 -0
  86. package/dist/server/storage.d.ts.map +1 -1
  87. package/dist/server/storage.js +25 -0
  88. package/dist/server/wire.d.ts +127 -2
  89. package/dist/server/wire.d.ts.map +1 -1
  90. package/package.json +2 -1
@@ -0,0 +1,411 @@
1
+ import { deduplicateToolCalls, estimateCompactionTokenMetrics, } from "./compaction.js";
2
+ import { computeFileLists, formatFileOperations } from "./utils.js";
3
+ const DCP_LITE_VERSION = 1;
4
+ const MAX_SUMMARY_CHARS = 12_000;
5
+ const MAX_PREVIOUS_SUMMARY_CHARS = 3_000;
6
+ const MAX_EXCERPT_CHARS = 480;
7
+ const MAX_RESULT_SIGNAL_CHARS = 360;
8
+ const MAX_TOOL_ARGS_CHARS = 220;
9
+ const MAX_EXCERPTS_PER_SECTION = 6;
10
+ const MAX_TOOL_CALLS_LISTED = 8;
11
+ const MAX_SIGNALS_LISTED = 10;
12
+ const MIN_CORE_SUMMARY_CHARS = 1_200;
13
+ const MAX_FILE_OPERATIONS_CHARS = 2_000;
14
+ const MAX_FILES_PER_OPERATION_SECTION = 40;
15
+ const MAX_FILE_PATH_CHARS = 160;
16
+ /**
17
+ * Deterministic, local-only compaction for manual DCP-lite mode.
18
+ *
19
+ * This intentionally performs no model, provider, extension, or network calls.
20
+ * It preserves bounded excerpts and counters from CompactionPreparation so the
21
+ * resulting summary is stable and usually much smaller than the discarded span.
22
+ */
23
+ export function compactDcpLite(preparation) {
24
+ const dedupedMessages = deduplicateToolCalls(preparation.messagesToSummarize);
25
+ const dedupedTurnPrefix = deduplicateToolCalls(preparation.turnPrefixMessages);
26
+ const { readFiles, modifiedFiles } = computeFileLists(preparation.fileOps);
27
+ const messageCounts = countMessages(dedupedMessages);
28
+ const turnPrefixCounts = countMessages(dedupedTurnPrefix);
29
+ const userExcerpts = collectRoleExcerpts(dedupedMessages, "user", MAX_EXCERPTS_PER_SECTION);
30
+ const assistantExcerpts = collectRoleExcerpts(dedupedMessages, "assistant", MAX_EXCERPTS_PER_SECTION);
31
+ const toolCalls = collectToolCalls(dedupedMessages, MAX_TOOL_CALLS_LISTED);
32
+ const toolCounts = countToolCalls(dedupedMessages);
33
+ const signals = collectErrorSignals(dedupedMessages, MAX_SIGNALS_LISTED);
34
+ const splitTurnExcerpts = preparation.isSplitTurn
35
+ ? collectAnyExcerpts(dedupedTurnPrefix, MAX_EXCERPTS_PER_SECTION)
36
+ : [];
37
+ const sourceChars = estimateSourceChars(preparation.messagesToSummarize, preparation.turnPrefixMessages);
38
+ const maxSummaryChars = calculateSummaryBudget(sourceChars);
39
+ const sections = [
40
+ "# DCP-lite compaction summary",
41
+ formatContextSection(preparation, messageCounts, turnPrefixCounts),
42
+ formatPreviousSummary(preparation.previousSummary),
43
+ formatExcerptSection("User intent / request excerpts", userExcerpts),
44
+ formatExcerptSection("Assistant progress excerpts", assistantExcerpts),
45
+ formatToolSection(toolCounts, toolCalls, signals),
46
+ ];
47
+ if (preparation.isSplitTurn) {
48
+ sections.push(formatExcerptSection("Split-turn context", splitTurnExcerpts));
49
+ }
50
+ let coreSummary = sections.join("\n\n").replace(/\n{3,}/g, "\n\n").trim();
51
+ const fileOperations = formatBoundedFileOperations(readFiles, modifiedFiles, maxSummaryChars);
52
+ const coreBudget = fileOperations ? Math.max(MIN_CORE_SUMMARY_CHARS, maxSummaryChars - fileOperations.length) : maxSummaryChars;
53
+ coreSummary = truncateText(coreSummary, coreBudget);
54
+ const summary = `${coreSummary}${fileOperations}`;
55
+ const tokenMetrics = estimateCompactionTokenMetrics(preparation, summary);
56
+ return {
57
+ summary,
58
+ firstKeptEntryId: preparation.firstKeptEntryId,
59
+ tokensBefore: preparation.tokensBefore,
60
+ ...tokenMetrics,
61
+ details: {
62
+ readFiles,
63
+ modifiedFiles,
64
+ method: "dcp-lite",
65
+ version: DCP_LITE_VERSION,
66
+ compactionNumber: preparation.compactionNumber,
67
+ tokensCompacted: tokenMetrics.tokensCompacted,
68
+ tokensRemoved: tokenMetrics.tokensRemoved,
69
+ summaryTokens: tokenMetrics.summaryTokens,
70
+ reductionPercent: tokenMetrics.reductionPercent,
71
+ largestTokenSources: tokenMetrics.largestTokenSources ?? [],
72
+ summarizedMessages: dedupedMessages.length,
73
+ turnPrefixMessages: dedupedTurnPrefix.length,
74
+ isSplitTurn: preparation.isSplitTurn,
75
+ },
76
+ };
77
+ }
78
+ function formatBoundedFileOperations(readFiles, modifiedFiles, maxSummaryChars) {
79
+ const fullFileOperations = formatFileOperations(readFiles, modifiedFiles);
80
+ if (!fullFileOperations)
81
+ return "";
82
+ const maxFileOperationsChars = Math.min(MAX_FILE_OPERATIONS_CHARS, maxSummaryChars - MIN_CORE_SUMMARY_CHARS);
83
+ const hasTooManyFiles = readFiles.length > MAX_FILES_PER_OPERATION_SECTION || modifiedFiles.length > MAX_FILES_PER_OPERATION_SECTION;
84
+ if (!hasTooManyFiles && fullFileOperations.length <= maxFileOperationsChars) {
85
+ return fullFileOperations;
86
+ }
87
+ let readLimit = Math.min(readFiles.length, MAX_FILES_PER_OPERATION_SECTION);
88
+ let modifiedLimit = Math.min(modifiedFiles.length, MAX_FILES_PER_OPERATION_SECTION);
89
+ while (readLimit > 0 || modifiedLimit > 0) {
90
+ const candidate = formatFileOperations(formatFileListForSummary(readFiles, readLimit), formatFileListForSummary(modifiedFiles, modifiedLimit));
91
+ if (candidate.length <= maxFileOperationsChars) {
92
+ return candidate;
93
+ }
94
+ if (readLimit >= modifiedLimit && readLimit > 0) {
95
+ readLimit -= 1;
96
+ }
97
+ else {
98
+ modifiedLimit -= 1;
99
+ }
100
+ }
101
+ return formatFileOperations(formatFileListForSummary(readFiles, 0), formatFileListForSummary(modifiedFiles, 0));
102
+ }
103
+ function formatFileListForSummary(files, limit) {
104
+ if (files.length === 0)
105
+ return [];
106
+ const listedCount = Math.min(files.length, Math.max(0, limit));
107
+ const displayed = files.slice(0, listedCount).map((file) => truncateText(file, MAX_FILE_PATH_CHARS));
108
+ const omitted = files.length - listedCount;
109
+ if (omitted > 0) {
110
+ displayed.push(`… [${omitted} files omitted]`);
111
+ }
112
+ return displayed;
113
+ }
114
+ function countMessages(messages) {
115
+ const counts = {
116
+ total: messages.length,
117
+ user: 0,
118
+ assistant: 0,
119
+ toolResult: 0,
120
+ custom: 0,
121
+ bashExecution: 0,
122
+ branchSummary: 0,
123
+ compactionSummary: 0,
124
+ other: 0,
125
+ };
126
+ for (const message of messages) {
127
+ switch (message.role) {
128
+ case "user":
129
+ counts.user += 1;
130
+ break;
131
+ case "assistant":
132
+ counts.assistant += 1;
133
+ break;
134
+ case "toolResult":
135
+ counts.toolResult += 1;
136
+ break;
137
+ case "custom":
138
+ counts.custom += 1;
139
+ break;
140
+ case "bashExecution":
141
+ counts.bashExecution += 1;
142
+ break;
143
+ case "branchSummary":
144
+ counts.branchSummary += 1;
145
+ break;
146
+ case "compactionSummary":
147
+ counts.compactionSummary += 1;
148
+ break;
149
+ default:
150
+ counts.other += 1;
151
+ }
152
+ }
153
+ return counts;
154
+ }
155
+ function formatContextSection(preparation, messageCounts, turnPrefixCounts) {
156
+ return [
157
+ "## Context counters",
158
+ `- method: dcp-lite deterministic local summary`,
159
+ `- compaction: #${preparation.compactionNumber}`,
160
+ `- messages summarized: ${messageCounts.total} (${formatCounts(messageCounts)})`,
161
+ `- split turn: ${preparation.isSplitTurn ? "yes" : "no"} (turn prefix messages: ${turnPrefixCounts.total})`,
162
+ `- tokensBefore: ${preparation.tokensBefore}`,
163
+ `- firstKeptEntryId: ${preparation.firstKeptEntryId}`,
164
+ ].join("\n");
165
+ }
166
+ function formatCounts(counts) {
167
+ const parts = [
168
+ ["user", counts.user],
169
+ ["assistant", counts.assistant],
170
+ ["toolResult", counts.toolResult],
171
+ ["custom", counts.custom],
172
+ ["bashExecution", counts.bashExecution],
173
+ ["branchSummary", counts.branchSummary],
174
+ ["compactionSummary", counts.compactionSummary],
175
+ ["other", counts.other],
176
+ ];
177
+ return parts.filter(([, value]) => value > 0).map(([label, value]) => `${label} ${value}`).join(", ") || "none";
178
+ }
179
+ function formatPreviousSummary(previousSummary) {
180
+ if (!previousSummary?.trim()) {
181
+ return "## Previous summary\n- none";
182
+ }
183
+ return `## Previous summary\n${truncateBlock(previousSummary, MAX_PREVIOUS_SUMMARY_CHARS)}`;
184
+ }
185
+ function formatExcerptSection(title, excerpts) {
186
+ if (excerpts.length === 0) {
187
+ return `## ${title}\n- none captured`;
188
+ }
189
+ return [`## ${title}`, ...excerpts.map((excerpt) => `- m${excerpt.index + 1} ${excerpt.role}: ${excerpt.text}`)].join("\n");
190
+ }
191
+ function formatToolSection(toolCounts, toolCalls, signals) {
192
+ const lines = ["## Tool activity and error signals"];
193
+ if (toolCounts.size === 0) {
194
+ lines.push("- tool calls: none captured");
195
+ }
196
+ else {
197
+ const counts = [...toolCounts.entries()]
198
+ .sort(([a], [b]) => a.localeCompare(b))
199
+ .map(([name, count]) => `${name}: ${count}`)
200
+ .join("; ");
201
+ lines.push(`- tool calls: ${counts}`);
202
+ }
203
+ if (toolCalls.length > 0) {
204
+ lines.push("- recent tool calls:");
205
+ for (const call of toolCalls) {
206
+ lines.push(` - m${call.index + 1} ${call.name} ${call.args}`);
207
+ }
208
+ }
209
+ if (signals.length > 0) {
210
+ lines.push("- signals:");
211
+ for (const signal of signals) {
212
+ lines.push(` - m${signal.index + 1} ${signal.label}: ${signal.text}`);
213
+ }
214
+ }
215
+ else {
216
+ lines.push("- signals: none captured");
217
+ }
218
+ return lines.join("\n");
219
+ }
220
+ function collectRoleExcerpts(messages, role, limit) {
221
+ const excerpts = [];
222
+ for (let index = 0; index < messages.length; index += 1) {
223
+ const message = messages[index];
224
+ if (message.role !== role)
225
+ continue;
226
+ const text = normalizeInline(extractMessageText(message));
227
+ if (!text)
228
+ continue;
229
+ excerpts.push({ index, role, text: truncateText(text, MAX_EXCERPT_CHARS) });
230
+ }
231
+ return selectBoundaryItems(excerpts, limit);
232
+ }
233
+ function collectAnyExcerpts(messages, limit) {
234
+ const excerpts = [];
235
+ for (let index = 0; index < messages.length; index += 1) {
236
+ const message = messages[index];
237
+ const text = normalizeInline(extractMessageText(message));
238
+ if (!text)
239
+ continue;
240
+ excerpts.push({ index, role: message.role, text: truncateText(text, MAX_EXCERPT_CHARS) });
241
+ }
242
+ return selectBoundaryItems(excerpts, limit);
243
+ }
244
+ function selectBoundaryItems(items, limit) {
245
+ if (items.length <= limit)
246
+ return items;
247
+ const firstCount = Math.min(2, limit);
248
+ const lastCount = Math.max(0, limit - firstCount);
249
+ return [...items.slice(0, firstCount), ...items.slice(items.length - lastCount)];
250
+ }
251
+ function collectToolCalls(messages, limit) {
252
+ const calls = [];
253
+ for (let index = 0; index < messages.length; index += 1) {
254
+ const message = messages[index];
255
+ if (message.role !== "assistant")
256
+ continue;
257
+ for (const block of message.content) {
258
+ if (block.type !== "toolCall")
259
+ continue;
260
+ calls.push({
261
+ index,
262
+ name: block.name,
263
+ args: truncateText(stableJson(block.arguments), MAX_TOOL_ARGS_CHARS),
264
+ });
265
+ }
266
+ }
267
+ return calls.slice(Math.max(0, calls.length - limit));
268
+ }
269
+ function countToolCalls(messages) {
270
+ const counts = new Map();
271
+ for (const message of messages) {
272
+ if (message.role !== "assistant")
273
+ continue;
274
+ for (const block of message.content) {
275
+ if (block.type !== "toolCall")
276
+ continue;
277
+ counts.set(block.name, (counts.get(block.name) ?? 0) + 1);
278
+ }
279
+ }
280
+ return counts;
281
+ }
282
+ function collectErrorSignals(messages, limit) {
283
+ const signals = [];
284
+ for (let index = 0; index < messages.length; index += 1) {
285
+ const message = messages[index];
286
+ if (message.role === "assistant") {
287
+ if (message.stopReason === "error") {
288
+ signals.push({
289
+ index,
290
+ label: "assistant stopReason=error",
291
+ text: truncateText(normalizeInline(message.errorMessage ?? extractMessageText(message)), MAX_RESULT_SIGNAL_CHARS),
292
+ });
293
+ }
294
+ else if (message.stopReason === "length") {
295
+ signals.push({
296
+ index,
297
+ label: "assistant stopReason=length",
298
+ text: truncateText(normalizeInline(extractMessageText(message)), MAX_RESULT_SIGNAL_CHARS),
299
+ });
300
+ }
301
+ continue;
302
+ }
303
+ if (message.role === "toolResult" && message.isError) {
304
+ signals.push({
305
+ index,
306
+ label: `${message.toolName} toolResult error=true`,
307
+ text: truncateText(normalizeInline(extractMessageText(message)), MAX_RESULT_SIGNAL_CHARS),
308
+ });
309
+ continue;
310
+ }
311
+ if (message.role === "bashExecution") {
312
+ if (message.cancelled || message.truncated || (message.exitCode !== undefined && message.exitCode !== 0)) {
313
+ const flags = [
314
+ message.cancelled ? "cancelled" : undefined,
315
+ message.truncated ? "truncated" : undefined,
316
+ message.exitCode !== undefined && message.exitCode !== 0 ? `exitCode=${message.exitCode}` : undefined,
317
+ ]
318
+ .filter((flag) => Boolean(flag))
319
+ .join(", ");
320
+ signals.push({
321
+ index,
322
+ label: `bashExecution ${flags}`,
323
+ text: truncateText(normalizeInline(`${message.command}\n${message.output}`), MAX_RESULT_SIGNAL_CHARS),
324
+ });
325
+ }
326
+ }
327
+ }
328
+ return signals.slice(0, limit);
329
+ }
330
+ function extractMessageText(message) {
331
+ switch (message.role) {
332
+ case "user":
333
+ return contentToText(message.content);
334
+ case "assistant":
335
+ return message.content
336
+ .filter((block) => block.type === "text")
337
+ .map((block) => block.text)
338
+ .join("\n");
339
+ case "toolResult":
340
+ return contentToText(message.content);
341
+ case "custom":
342
+ return contentToText(message.content);
343
+ case "bashExecution":
344
+ return `${message.command}\n${message.output}`;
345
+ case "branchSummary":
346
+ return message.summary;
347
+ case "compactionSummary":
348
+ return message.summary;
349
+ default:
350
+ return "";
351
+ }
352
+ }
353
+ function contentToText(content) {
354
+ if (typeof content === "string")
355
+ return content;
356
+ return content
357
+ .filter((block) => block.type === "text" && typeof block.text === "string")
358
+ .map((block) => block.text)
359
+ .join("\n");
360
+ }
361
+ function estimateSourceChars(messagesToSummarize, turnPrefixMessages) {
362
+ let chars = 0;
363
+ for (const message of [...messagesToSummarize, ...turnPrefixMessages]) {
364
+ chars += extractMessageText(message).length;
365
+ if (message.role === "assistant") {
366
+ for (const block of message.content) {
367
+ if (block.type === "toolCall") {
368
+ chars += block.name.length + stableJson(block.arguments).length;
369
+ }
370
+ }
371
+ }
372
+ }
373
+ return chars;
374
+ }
375
+ function calculateSummaryBudget(sourceChars) {
376
+ if (sourceChars >= 12_000) {
377
+ return Math.min(MAX_SUMMARY_CHARS, Math.max(3_000, Math.floor(sourceChars * 0.4)));
378
+ }
379
+ return MAX_SUMMARY_CHARS;
380
+ }
381
+ function truncateBlock(text, maxChars) {
382
+ return truncateText(text.trim(), maxChars);
383
+ }
384
+ function truncateText(text, maxChars) {
385
+ if (text.length <= maxChars)
386
+ return text;
387
+ const omitted = text.length - maxChars;
388
+ return `${text.slice(0, Math.max(0, maxChars - 36)).trimEnd()}… [${omitted} chars omitted]`;
389
+ }
390
+ function normalizeInline(text) {
391
+ return text.replace(/\s+/g, " ").trim();
392
+ }
393
+ function stableJson(value) {
394
+ const seen = new WeakSet();
395
+ const normalize = (input) => {
396
+ if (input === null || typeof input !== "object")
397
+ return input;
398
+ if (seen.has(input))
399
+ return "[Circular]";
400
+ seen.add(input);
401
+ if (Array.isArray(input))
402
+ return input.map((item) => normalize(item));
403
+ const record = input;
404
+ const sorted = {};
405
+ for (const key of Object.keys(record).sort()) {
406
+ sorted[key] = normalize(record[key]);
407
+ }
408
+ return sorted;
409
+ };
410
+ return JSON.stringify(normalize(value)) ?? "null";
411
+ }
@@ -3,5 +3,7 @@
3
3
  */
4
4
  export * from "./branch-summarization.js";
5
5
  export * from "./compaction.js";
6
+ export * from "./dcp-lite.js";
7
+ export * from "./policy.js";
6
8
  export * from "./utils.js";
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/sdk/coding-agent/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/sdk/coding-agent/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -3,4 +3,6 @@
3
3
  */
4
4
  export * from "./branch-summarization.js";
5
5
  export * from "./compaction.js";
6
+ export * from "./dcp-lite.js";
7
+ export * from "./policy.js";
6
8
  export * from "./utils.js";
@@ -0,0 +1,71 @@
1
+ export interface ConversationCompactionPolicy {
2
+ enabled: boolean;
3
+ reserveTokens: number;
4
+ keepRecentTokens: number;
5
+ contextLimitRatio: number;
6
+ }
7
+ export interface ManualCompactionPolicy {
8
+ keepRecentTokens: number;
9
+ minKeepRecentTokens: number;
10
+ maxKeepRecentTokens: number;
11
+ }
12
+ export interface AutoOlderHistoryCompactionPolicy {
13
+ enabled: boolean;
14
+ contextLimitRatio: number;
15
+ keepRecentTokens: number;
16
+ cooldownTurns: number;
17
+ minRawTokens: number;
18
+ }
19
+ export interface AgentDrivenCompactionPolicy {
20
+ enabled: boolean;
21
+ cooldownTurns: number;
22
+ minRawTokens: number;
23
+ olderHistoryKeepRecentTokens: number;
24
+ olderHistoryMinKeepRecentTokens: number;
25
+ olderHistoryMaxKeepRecentTokens: number;
26
+ olderHistoryMinCompactableTokens: number;
27
+ }
28
+ export interface ToolOutputCompressorPolicy {
29
+ enabled: boolean;
30
+ maxResultChars: number;
31
+ maxReadLines: number;
32
+ maxLsLines: number;
33
+ maxSearchLines: number;
34
+ stripAnsi: boolean;
35
+ stripComments: boolean;
36
+ testFailuresOnly: boolean;
37
+ compactGit: boolean;
38
+ }
39
+ export interface TruncationContinuationPolicy {
40
+ maxAttempts: number;
41
+ totalOutputTokenBudget: number;
42
+ }
43
+ export interface CompactionPolicy {
44
+ conversation: ConversationCompactionPolicy;
45
+ manual: ManualCompactionPolicy;
46
+ autoOlderHistory: AutoOlderHistoryCompactionPolicy;
47
+ agentDriven: AgentDrivenCompactionPolicy;
48
+ toolOutputCompressor: ToolOutputCompressorPolicy;
49
+ truncationContinuation: TruncationContinuationPolicy;
50
+ }
51
+ export interface CompactionPolicySettings {
52
+ /** Legacy/current conversation compaction flag. Defaults to true. */
53
+ enabled?: boolean;
54
+ /** Legacy/current reserve tokens for compaction prompt/output. */
55
+ reserveTokens?: number;
56
+ /** Legacy/current recent raw suffix for automatic older-history compaction. */
57
+ keepRecentTokens?: number;
58
+ /** Context-window pressure ratio for automatic older-history compaction. */
59
+ contextLimitRatio?: number;
60
+ manual?: Partial<ManualCompactionPolicy>;
61
+ autoOlderHistory?: Partial<AutoOlderHistoryCompactionPolicy>;
62
+ agentDriven?: Partial<AgentDrivenCompactionPolicy>;
63
+ toolOutputCompressor?: Partial<ToolOutputCompressorPolicy>;
64
+ truncationContinuation?: Partial<TruncationContinuationPolicy>;
65
+ }
66
+ export declare const DEFAULT_COMPACTION_POLICY: CompactionPolicy;
67
+ export declare function normalizeManualKeepRecentTokens(value: unknown, manualPolicy?: ManualCompactionPolicy): number;
68
+ export declare function normalizeAgentDrivenOlderHistoryKeepRecentTokens(value: unknown, agentPolicy?: AgentDrivenCompactionPolicy): number;
69
+ export declare function getAutoOlderHistoryContextThresholdTokens(policy: CompactionPolicy, contextWindow: number | null | undefined): number | null;
70
+ export declare function normalizeCompactionPolicy(settings?: CompactionPolicySettings): CompactionPolicy;
71
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../../../src/sdk/coding-agent/core/compaction/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ export const DEFAULT_COMPACTION_POLICY = {
2
+ conversation: {
3
+ enabled: true,
4
+ reserveTokens: 16_384,
5
+ keepRecentTokens: 20_000,
6
+ contextLimitRatio: 0.8,
7
+ },
8
+ manual: {
9
+ keepRecentTokens: 8_000,
10
+ minKeepRecentTokens: 1_000,
11
+ maxKeepRecentTokens: 100_000,
12
+ },
13
+ autoOlderHistory: {
14
+ enabled: true,
15
+ contextLimitRatio: 0.4,
16
+ keepRecentTokens: 12_000,
17
+ cooldownTurns: 0,
18
+ minRawTokens: 0,
19
+ },
20
+ agentDriven: {
21
+ enabled: true,
22
+ cooldownTurns: 3,
23
+ minRawTokens: 8_000,
24
+ olderHistoryKeepRecentTokens: 12_000,
25
+ olderHistoryMinKeepRecentTokens: 1_000,
26
+ olderHistoryMaxKeepRecentTokens: 100_000,
27
+ olderHistoryMinCompactableTokens: 1_000,
28
+ },
29
+ toolOutputCompressor: {
30
+ enabled: true,
31
+ maxResultChars: 8_000,
32
+ maxReadLines: 500,
33
+ maxLsLines: 100,
34
+ maxSearchLines: 200,
35
+ stripAnsi: true,
36
+ stripComments: true,
37
+ testFailuresOnly: true,
38
+ compactGit: true,
39
+ },
40
+ truncationContinuation: {
41
+ maxAttempts: 3,
42
+ totalOutputTokenBudget: 32_000,
43
+ },
44
+ };
45
+ function normalizeBoolean(value, fallback) {
46
+ return typeof value === "boolean" ? value : fallback;
47
+ }
48
+ function normalizeInteger(value, fallback, min, max) {
49
+ if (typeof value !== "number" || !Number.isFinite(value))
50
+ return fallback;
51
+ const integer = Math.trunc(value);
52
+ return Math.min(max, Math.max(min, integer));
53
+ }
54
+ function normalizeNonNegativeInteger(value, fallback) {
55
+ return normalizeInteger(value, fallback, 0, Number.MAX_SAFE_INTEGER);
56
+ }
57
+ function normalizePositiveInteger(value, fallback) {
58
+ return normalizeInteger(value, fallback, 1, Number.MAX_SAFE_INTEGER);
59
+ }
60
+ function normalizeRatio(value, fallback) {
61
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0 || value > 1)
62
+ return fallback;
63
+ return value;
64
+ }
65
+ export function normalizeManualKeepRecentTokens(value, manualPolicy = DEFAULT_COMPACTION_POLICY.manual) {
66
+ return normalizeInteger(value, manualPolicy.keepRecentTokens, manualPolicy.minKeepRecentTokens, manualPolicy.maxKeepRecentTokens);
67
+ }
68
+ export function normalizeAgentDrivenOlderHistoryKeepRecentTokens(value, agentPolicy = DEFAULT_COMPACTION_POLICY.agentDriven) {
69
+ return normalizeInteger(value, agentPolicy.olderHistoryKeepRecentTokens, agentPolicy.olderHistoryMinKeepRecentTokens, agentPolicy.olderHistoryMaxKeepRecentTokens);
70
+ }
71
+ export function getAutoOlderHistoryContextThresholdTokens(policy, contextWindow) {
72
+ if (!policy.conversation.enabled || !policy.autoOlderHistory.enabled)
73
+ return null;
74
+ if (typeof contextWindow !== "number" || !Number.isFinite(contextWindow) || contextWindow <= 0)
75
+ return null;
76
+ return Math.max(1, Math.floor(contextWindow * policy.autoOlderHistory.contextLimitRatio));
77
+ }
78
+ function normalizeManualPolicy(settings) {
79
+ const defaults = DEFAULT_COMPACTION_POLICY.manual;
80
+ const manual = settings?.manual;
81
+ const minKeepRecentTokens = normalizePositiveInteger(manual?.minKeepRecentTokens, defaults.minKeepRecentTokens);
82
+ const maxKeepRecentTokens = Math.max(minKeepRecentTokens, normalizePositiveInteger(manual?.maxKeepRecentTokens, defaults.maxKeepRecentTokens));
83
+ const fallbackKeepRecentTokens = normalizeInteger(defaults.keepRecentTokens, defaults.keepRecentTokens, minKeepRecentTokens, maxKeepRecentTokens);
84
+ const keepRecentTokens = normalizeInteger(manual?.keepRecentTokens, fallbackKeepRecentTokens, minKeepRecentTokens, maxKeepRecentTokens);
85
+ return { keepRecentTokens, minKeepRecentTokens, maxKeepRecentTokens };
86
+ }
87
+ function normalizeAgentDrivenPolicy(settings) {
88
+ const defaults = DEFAULT_COMPACTION_POLICY.agentDriven;
89
+ const agentDriven = settings?.agentDriven;
90
+ const olderHistoryMinKeepRecentTokens = normalizePositiveInteger(agentDriven?.olderHistoryMinKeepRecentTokens, defaults.olderHistoryMinKeepRecentTokens);
91
+ const olderHistoryMaxKeepRecentTokens = Math.max(olderHistoryMinKeepRecentTokens, normalizePositiveInteger(agentDriven?.olderHistoryMaxKeepRecentTokens, defaults.olderHistoryMaxKeepRecentTokens));
92
+ const fallbackOlderHistoryKeepRecentTokens = normalizeInteger(defaults.olderHistoryKeepRecentTokens, defaults.olderHistoryKeepRecentTokens, olderHistoryMinKeepRecentTokens, olderHistoryMaxKeepRecentTokens);
93
+ return {
94
+ enabled: normalizeBoolean(agentDriven?.enabled, defaults.enabled),
95
+ cooldownTurns: normalizeNonNegativeInteger(agentDriven?.cooldownTurns, defaults.cooldownTurns),
96
+ minRawTokens: normalizeNonNegativeInteger(agentDriven?.minRawTokens, defaults.minRawTokens),
97
+ olderHistoryKeepRecentTokens: normalizeInteger(agentDriven?.olderHistoryKeepRecentTokens, fallbackOlderHistoryKeepRecentTokens, olderHistoryMinKeepRecentTokens, olderHistoryMaxKeepRecentTokens),
98
+ olderHistoryMinKeepRecentTokens,
99
+ olderHistoryMaxKeepRecentTokens,
100
+ olderHistoryMinCompactableTokens: normalizeNonNegativeInteger(agentDriven?.olderHistoryMinCompactableTokens, defaults.olderHistoryMinCompactableTokens),
101
+ };
102
+ }
103
+ function normalizeToolOutputCompressorPolicy(settings) {
104
+ const defaults = DEFAULT_COMPACTION_POLICY.toolOutputCompressor;
105
+ const compressor = settings?.toolOutputCompressor;
106
+ return {
107
+ enabled: normalizeBoolean(compressor?.enabled, defaults.enabled),
108
+ maxResultChars: normalizePositiveInteger(compressor?.maxResultChars, defaults.maxResultChars),
109
+ maxReadLines: normalizePositiveInteger(compressor?.maxReadLines, defaults.maxReadLines),
110
+ maxLsLines: normalizePositiveInteger(compressor?.maxLsLines, defaults.maxLsLines),
111
+ maxSearchLines: normalizePositiveInteger(compressor?.maxSearchLines, defaults.maxSearchLines),
112
+ stripAnsi: normalizeBoolean(compressor?.stripAnsi, defaults.stripAnsi),
113
+ stripComments: normalizeBoolean(compressor?.stripComments, defaults.stripComments),
114
+ testFailuresOnly: normalizeBoolean(compressor?.testFailuresOnly, defaults.testFailuresOnly),
115
+ compactGit: normalizeBoolean(compressor?.compactGit, defaults.compactGit),
116
+ };
117
+ }
118
+ export function normalizeCompactionPolicy(settings) {
119
+ const defaults = DEFAULT_COMPACTION_POLICY;
120
+ const conversation = {
121
+ enabled: normalizeBoolean(settings?.enabled, defaults.conversation.enabled),
122
+ reserveTokens: normalizePositiveInteger(settings?.reserveTokens, defaults.conversation.reserveTokens),
123
+ keepRecentTokens: normalizePositiveInteger(settings?.keepRecentTokens, defaults.conversation.keepRecentTokens),
124
+ contextLimitRatio: normalizeRatio(settings?.contextLimitRatio, defaults.conversation.contextLimitRatio),
125
+ };
126
+ const autoOlderHistory = settings?.autoOlderHistory;
127
+ const autoContextLimitRatioFallback = normalizeRatio(settings?.contextLimitRatio, defaults.autoOlderHistory.contextLimitRatio);
128
+ const autoPolicy = {
129
+ enabled: normalizeBoolean(autoOlderHistory?.enabled, conversation.enabled),
130
+ contextLimitRatio: normalizeRatio(autoOlderHistory?.contextLimitRatio, autoContextLimitRatioFallback),
131
+ keepRecentTokens: normalizePositiveInteger(autoOlderHistory?.keepRecentTokens, conversation.keepRecentTokens),
132
+ cooldownTurns: normalizeNonNegativeInteger(autoOlderHistory?.cooldownTurns, defaults.autoOlderHistory.cooldownTurns),
133
+ minRawTokens: normalizeNonNegativeInteger(autoOlderHistory?.minRawTokens, defaults.autoOlderHistory.minRawTokens),
134
+ };
135
+ const truncationContinuation = settings?.truncationContinuation;
136
+ return {
137
+ conversation,
138
+ manual: normalizeManualPolicy(settings),
139
+ autoOlderHistory: autoPolicy,
140
+ agentDriven: normalizeAgentDrivenPolicy(settings),
141
+ toolOutputCompressor: normalizeToolOutputCompressorPolicy(settings),
142
+ truncationContinuation: {
143
+ maxAttempts: normalizeNonNegativeInteger(truncationContinuation?.maxAttempts, defaults.truncationContinuation.maxAttempts),
144
+ totalOutputTokenBudget: normalizeNonNegativeInteger(truncationContinuation?.totalOutputTokenBudget, defaults.truncationContinuation.totalOutputTokenBudget),
145
+ },
146
+ };
147
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"native-extensions.d.ts","sourceRoot":"","sources":["../../../../../src/sdk/coding-agent/core/extensions/native-extensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,uBAAuB;IACtC,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,aAAa,CAAC;IAChD;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,cAAc,EAAE,OAAO,CAAC;IACxB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,uBAAuB,EA8EtD,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAElF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAIjF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC,CASD"}
1
+ {"version":3,"file":"native-extensions.d.ts","sourceRoot":"","sources":["../../../../../src/sdk/coding-agent/core/extensions/native-extensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,uBAAuB;IACtC,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,aAAa,CAAC;IAChD;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,cAAc,EAAE,OAAO,CAAC;IACxB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,uBAAuB,EAuFtD,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAElF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAIjF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC,CASD"}