@wrongstack/core 0.3.1 → 0.3.2
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.
- package/dist/{compactor-BUU6Zm_3.d.ts → compactor-DpJBI1YH.d.ts} +7 -1
- package/dist/{config-CKLYPkCi.d.ts → config-D2qvAxVd.d.ts} +38 -1
- package/dist/coordination/index.d.ts +3 -3
- package/dist/coordination/index.js +283 -244
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +7 -7
- package/dist/defaults/index.js +803 -524
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-CNB9PALO.d.ts → events-BHIQs4o1.d.ts} +7 -0
- package/dist/execution/index.d.ts +10 -7
- package/dist/execution/index.js +166 -18
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +3 -3
- package/dist/extension/index.js +14 -7
- package/dist/extension/index.js.map +1 -1
- package/dist/{index-BDb0cAMP.d.ts → index-hWNybrNZ.d.ts} +3 -5
- package/dist/index.d.ts +12 -12
- package/dist/index.js +629 -299
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +5 -5
- package/dist/infrastructure/index.js +191 -20
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +4 -4
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-DR35ojJZ.d.ts → mcp-servers-C2OopXOn.d.ts} +20 -4
- package/dist/observability/index.d.ts +1 -1
- package/dist/{path-resolver-Cl_q0u-R.d.ts → path-resolver--59rCou3.d.ts} +1 -1
- package/dist/{provider-runner-BXuADQqQ.d.ts → provider-runner-B39miKRw.d.ts} +1 -1
- package/dist/sdd/index.d.ts +1 -1
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +180 -13
- package/dist/storage/index.js.map +1 -1
- package/dist/{tool-executor-DKu4A6nB.d.ts → tool-executor-HsBLGRaA.d.ts} +2 -2
- package/dist/types/index.d.ts +7 -7
- package/dist/types/index.js +206 -9
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +23 -2
- package/dist/utils/index.js +93 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -153,6 +153,13 @@ interface EventMap {
|
|
|
153
153
|
used: number;
|
|
154
154
|
limit: number;
|
|
155
155
|
};
|
|
156
|
+
'context.repaired': {
|
|
157
|
+
ctx: Context;
|
|
158
|
+
changed: boolean;
|
|
159
|
+
removedToolUses: string[];
|
|
160
|
+
removedToolResults: string[];
|
|
161
|
+
removedMessages: number;
|
|
162
|
+
};
|
|
156
163
|
'compaction.fired': {
|
|
157
164
|
before: number;
|
|
158
165
|
after: number;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-
|
|
1
|
+
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-HsBLGRaA.js';
|
|
2
2
|
import { g as Provider, a0 as Context } from '../context-IovtuTf8.js';
|
|
3
|
-
import {
|
|
3
|
+
import { a as Compactor, C as CompactReport } from '../compactor-DpJBI1YH.js';
|
|
4
4
|
import { M as MessageSelector } from '../selector-wT2fv9Fg.js';
|
|
5
|
-
import { E as EventBus } from '../events-
|
|
5
|
+
import { E as EventBus } from '../events-BHIQs4o1.js';
|
|
6
6
|
import { c as MiddlewareHandler } from '../system-prompt-Dk1qm8ey.js';
|
|
7
|
-
import {
|
|
7
|
+
import { e as ContextWindowAggressiveOn, i as ContextWindowPolicy } from '../config-D2qvAxVd.js';
|
|
8
|
+
import { r as Agent, R as RunResult } from '../index-hWNybrNZ.js';
|
|
8
9
|
import { D as DoneCondition } from '../multi-agent-B9a6sflH.js';
|
|
9
10
|
import { a as SkillLoader, b as SkillManifest, S as SkillEntry } from '../skill-C_7znCIC.js';
|
|
10
11
|
import { a as WstackPaths } from '../wstack-paths-BGu2INTm.js';
|
|
@@ -12,7 +13,6 @@ import '../models-registry-Y2xbog0E.js';
|
|
|
12
13
|
import '../logger-BMQgxvdy.js';
|
|
13
14
|
import '../observability-BhnVLBLS.js';
|
|
14
15
|
import '../secret-scrubber-CgG2tV2B.js';
|
|
15
|
-
import '../config-CKLYPkCi.js';
|
|
16
16
|
|
|
17
17
|
interface SkillLoaderOptions {
|
|
18
18
|
paths: WstackPaths;
|
|
@@ -147,6 +147,7 @@ declare class SelectiveCompactor implements Compactor {
|
|
|
147
147
|
compact(ctx: Context, opts?: {
|
|
148
148
|
aggressive?: boolean;
|
|
149
149
|
}): Promise<CompactReport>;
|
|
150
|
+
private repairProtocolAdjacency;
|
|
150
151
|
/**
|
|
151
152
|
* Run the LLM selector to decide what to keep vs collapse.
|
|
152
153
|
* Returns the token savings achieved.
|
|
@@ -173,9 +174,10 @@ declare class SelectiveCompactor implements Compactor {
|
|
|
173
174
|
|
|
174
175
|
type CompactionFailureMode = 'throw' | 'throw_on_hard' | 'continue';
|
|
175
176
|
interface AutoCompactionOptions {
|
|
176
|
-
aggressiveOn?:
|
|
177
|
+
aggressiveOn?: ContextWindowAggressiveOn;
|
|
177
178
|
events?: EventBus;
|
|
178
179
|
failureMode?: CompactionFailureMode;
|
|
180
|
+
policyProvider?: (ctx: Context) => Pick<ContextWindowPolicy, 'thresholds' | 'aggressiveOn'> | null | undefined;
|
|
179
181
|
}
|
|
180
182
|
/**
|
|
181
183
|
* Pipeline middleware that monitors context token load and automatically
|
|
@@ -193,6 +195,7 @@ declare class AutoCompactionMiddleware {
|
|
|
193
195
|
private readonly aggressiveOn;
|
|
194
196
|
private readonly events?;
|
|
195
197
|
private readonly failureMode;
|
|
198
|
+
private readonly policyProvider?;
|
|
196
199
|
/**
|
|
197
200
|
* @param compactor Compactor to use for compaction.
|
|
198
201
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -208,7 +211,7 @@ declare class AutoCompactionMiddleware {
|
|
|
208
211
|
warn: number;
|
|
209
212
|
soft: number;
|
|
210
213
|
hard: number;
|
|
211
|
-
}, optsOrAggressiveOn?: AutoCompactionOptions |
|
|
214
|
+
}, optsOrAggressiveOn?: AutoCompactionOptions | ContextWindowAggressiveOn, events?: EventBus);
|
|
212
215
|
handler(): MiddlewareHandler<Context>;
|
|
213
216
|
private compact;
|
|
214
217
|
}
|
package/dist/execution/index.js
CHANGED
|
@@ -35,6 +35,98 @@ function estimateTextTokens(text) {
|
|
|
35
35
|
return RoughTokenEstimate(text);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// src/utils/message-invariants.ts
|
|
39
|
+
function repairToolUseAdjacency(messages) {
|
|
40
|
+
const removedToolUses = [];
|
|
41
|
+
const removedToolResults = [];
|
|
42
|
+
let removedMessages = 0;
|
|
43
|
+
let changed = false;
|
|
44
|
+
const out = [];
|
|
45
|
+
for (let i = 0; i < messages.length; i++) {
|
|
46
|
+
const original = messages[i];
|
|
47
|
+
let msg = original;
|
|
48
|
+
if (hasToolUse(msg)) {
|
|
49
|
+
const nextIds = toolResultIds(messages[i + 1]);
|
|
50
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
51
|
+
const next = [];
|
|
52
|
+
for (const block of blocks) {
|
|
53
|
+
if (block.type === "tool_use" && !nextIds.has(block.id)) {
|
|
54
|
+
removedToolUses.push(block.id);
|
|
55
|
+
changed = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
next.push(block);
|
|
59
|
+
}
|
|
60
|
+
return next;
|
|
61
|
+
});
|
|
62
|
+
msg = filtered ?? msg;
|
|
63
|
+
}
|
|
64
|
+
if (hasToolResult(msg)) {
|
|
65
|
+
const allowed = toolUseIds(out[out.length - 1]);
|
|
66
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
67
|
+
const next = [];
|
|
68
|
+
for (const block of blocks) {
|
|
69
|
+
if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
|
|
70
|
+
removedToolResults.push(block.tool_use_id);
|
|
71
|
+
changed = true;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
next.push(block);
|
|
75
|
+
}
|
|
76
|
+
return next;
|
|
77
|
+
});
|
|
78
|
+
msg = filtered ?? msg;
|
|
79
|
+
}
|
|
80
|
+
if (isEmptyMessage(msg)) {
|
|
81
|
+
removedMessages++;
|
|
82
|
+
changed = true;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
out.push(msg);
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
messages: changed ? out : messages,
|
|
89
|
+
report: { changed, removedToolUses, removedToolResults, removedMessages }
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function hasToolUse(msg) {
|
|
93
|
+
return contentBlocks(msg).some((b) => b.type === "tool_use");
|
|
94
|
+
}
|
|
95
|
+
function hasToolResult(msg) {
|
|
96
|
+
return contentBlocks(msg).some((b) => b.type === "tool_result");
|
|
97
|
+
}
|
|
98
|
+
function toolUseIds(msg) {
|
|
99
|
+
const ids = /* @__PURE__ */ new Set();
|
|
100
|
+
if (!msg || msg.role !== "assistant") return ids;
|
|
101
|
+
for (const block of contentBlocks(msg)) {
|
|
102
|
+
if (block.type === "tool_use") ids.add(block.id);
|
|
103
|
+
}
|
|
104
|
+
return ids;
|
|
105
|
+
}
|
|
106
|
+
function toolResultIds(msg) {
|
|
107
|
+
const ids = /* @__PURE__ */ new Set();
|
|
108
|
+
if (!msg || msg.role !== "user") return ids;
|
|
109
|
+
for (const block of contentBlocks(msg)) {
|
|
110
|
+
if (block.type === "tool_result") ids.add(block.tool_use_id);
|
|
111
|
+
}
|
|
112
|
+
return ids;
|
|
113
|
+
}
|
|
114
|
+
function contentBlocks(msg) {
|
|
115
|
+
return msg && Array.isArray(msg.content) ? msg.content : [];
|
|
116
|
+
}
|
|
117
|
+
function mapContent(msg, fn) {
|
|
118
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
119
|
+
const next = fn(msg.content);
|
|
120
|
+
if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
|
|
121
|
+
return msg;
|
|
122
|
+
}
|
|
123
|
+
return { ...msg, content: next };
|
|
124
|
+
}
|
|
125
|
+
function isEmptyMessage(msg) {
|
|
126
|
+
if (typeof msg.content === "string") return msg.content.trim().length === 0;
|
|
127
|
+
return msg.content.length === 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
38
130
|
// src/execution/compactor.ts
|
|
39
131
|
var HybridCompactor = class {
|
|
40
132
|
preserveK;
|
|
@@ -48,20 +140,36 @@ var HybridCompactor = class {
|
|
|
48
140
|
async compact(ctx, opts = {}) {
|
|
49
141
|
const beforeTokens = this.estimateMessages(ctx.messages);
|
|
50
142
|
const reductions = [];
|
|
51
|
-
const
|
|
143
|
+
const policy = readContextWindowPolicy(ctx);
|
|
144
|
+
const preserveK = policy?.preserveK ?? this.preserveK;
|
|
145
|
+
const eliseThreshold = policy?.eliseThreshold ?? this.eliseThreshold;
|
|
146
|
+
const phase1Saved = this.eliseOldToolResults(ctx, preserveK, eliseThreshold);
|
|
52
147
|
if (phase1Saved > 0) reductions.push({ phase: "elision", saved: phase1Saved });
|
|
53
148
|
if (opts.aggressive) {
|
|
54
|
-
const phase2Saved = this.collapseAncientTurns(ctx);
|
|
149
|
+
const phase2Saved = this.collapseAncientTurns(ctx, preserveK);
|
|
55
150
|
if (phase2Saved > 0) reductions.push({ phase: "summary", saved: phase2Saved });
|
|
56
151
|
}
|
|
152
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
153
|
+
if (repaired.report.changed) {
|
|
154
|
+
ctx.state.replaceMessages(repaired.messages);
|
|
155
|
+
}
|
|
57
156
|
const afterTokens = this.estimateMessages(ctx.messages);
|
|
58
|
-
return {
|
|
157
|
+
return {
|
|
158
|
+
before: beforeTokens,
|
|
159
|
+
after: afterTokens,
|
|
160
|
+
reductions,
|
|
161
|
+
repaired: repaired.report.changed ? {
|
|
162
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
163
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
164
|
+
removedMessages: repaired.report.removedMessages
|
|
165
|
+
} : void 0
|
|
166
|
+
};
|
|
59
167
|
}
|
|
60
|
-
eliseOldToolResults(ctx) {
|
|
168
|
+
eliseOldToolResults(ctx, preserveK = this.preserveK, eliseThreshold = this.eliseThreshold) {
|
|
61
169
|
const messages = ctx.messages;
|
|
62
170
|
let pairCount = 0;
|
|
63
171
|
let preserveStart = messages.length;
|
|
64
|
-
for (let i = messages.length - 1; i >= 0 && pairCount <
|
|
172
|
+
for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
|
|
65
173
|
const m = messages[i];
|
|
66
174
|
if (!m) continue;
|
|
67
175
|
if (m.role === "user" || m.role === "assistant") {
|
|
@@ -85,7 +193,7 @@ var HybridCompactor = class {
|
|
|
85
193
|
const newContent = msg.content.map((b) => {
|
|
86
194
|
if (b.type !== "tool_result") return b;
|
|
87
195
|
const tokens = estimateToolResultTokens(b.content);
|
|
88
|
-
if (tokens <
|
|
196
|
+
if (tokens < eliseThreshold) return b;
|
|
89
197
|
saved += tokens;
|
|
90
198
|
const elided = {
|
|
91
199
|
type: "tool_result",
|
|
@@ -105,9 +213,9 @@ var HybridCompactor = class {
|
|
|
105
213
|
if (changed) ctx.state.replaceMessages(nextMessages);
|
|
106
214
|
return saved;
|
|
107
215
|
}
|
|
108
|
-
collapseAncientTurns(ctx) {
|
|
216
|
+
collapseAncientTurns(ctx, preserveK = this.preserveK) {
|
|
109
217
|
const messages = ctx.messages;
|
|
110
|
-
const cutTarget = Math.max(0, messages.length -
|
|
218
|
+
const cutTarget = Math.max(0, messages.length - preserveK * 2);
|
|
111
219
|
if (cutTarget <= 0) return 0;
|
|
112
220
|
let boundary = -1;
|
|
113
221
|
for (let i = cutTarget; i < messages.length; i++) {
|
|
@@ -148,6 +256,15 @@ var HybridCompactor = class {
|
|
|
148
256
|
return total;
|
|
149
257
|
}
|
|
150
258
|
};
|
|
259
|
+
function readContextWindowPolicy(ctx) {
|
|
260
|
+
const policy = ctx.meta?.["contextWindowPolicy"];
|
|
261
|
+
if (!policy || typeof policy !== "object") return null;
|
|
262
|
+
const candidate = policy;
|
|
263
|
+
if (typeof candidate.preserveK !== "number" || typeof candidate.eliseThreshold !== "number") {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
return candidate;
|
|
267
|
+
}
|
|
151
268
|
function hasTextContent(m) {
|
|
152
269
|
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
153
270
|
return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
|
|
@@ -194,8 +311,19 @@ var IntelligentCompactor = class {
|
|
|
194
311
|
const saved2 = this.lightweightCompact(ctx);
|
|
195
312
|
if (saved2 > 0) reductions.push({ phase: "elision", saved: saved2 });
|
|
196
313
|
}
|
|
314
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
315
|
+
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
197
316
|
const afterTokens = this.estimateTokens(ctx.messages);
|
|
198
|
-
return {
|
|
317
|
+
return {
|
|
318
|
+
before: beforeTokens,
|
|
319
|
+
after: afterTokens,
|
|
320
|
+
reductions,
|
|
321
|
+
repaired: repaired.report.changed ? {
|
|
322
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
323
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
324
|
+
removedMessages: repaired.report.removedMessages
|
|
325
|
+
} : void 0
|
|
326
|
+
};
|
|
199
327
|
}
|
|
200
328
|
async summarizeAncientTurns(ctx) {
|
|
201
329
|
const messages = ctx.messages;
|
|
@@ -235,8 +363,8 @@ var IntelligentCompactor = class {
|
|
|
235
363
|
const m = messages[i];
|
|
236
364
|
if (!m) continue;
|
|
237
365
|
if (m.role === "assistant") {
|
|
238
|
-
const
|
|
239
|
-
if (!
|
|
366
|
+
const hasToolUse2 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
|
|
367
|
+
if (!hasToolUse2) {
|
|
240
368
|
return i + 1;
|
|
241
369
|
}
|
|
242
370
|
} else if (m.role !== "user") ; else {
|
|
@@ -542,8 +670,9 @@ var SelectiveCompactor = class {
|
|
|
542
670
|
if (!shouldCompact) {
|
|
543
671
|
const saved = this.eliseOldToolResults(ctx);
|
|
544
672
|
if (saved > 0) reductions.push({ phase: "elision", saved });
|
|
673
|
+
const repair2 = this.repairProtocolAdjacency(ctx);
|
|
545
674
|
const afterTokens2 = this.estimateTokens(ctx.messages);
|
|
546
|
-
return { before: beforeTokens, after: afterTokens2, reductions };
|
|
675
|
+
return { before: beforeTokens, after: afterTokens2, reductions, repaired: repair2 };
|
|
547
676
|
}
|
|
548
677
|
const savedElision = this.eliseOldToolResults(ctx);
|
|
549
678
|
if (savedElision > 0) reductions.push({ phase: "elision", saved: savedElision });
|
|
@@ -553,8 +682,18 @@ var SelectiveCompactor = class {
|
|
|
553
682
|
const savedSelective = await this.runSelector(ctx, targetBudget);
|
|
554
683
|
if (savedSelective > 0) reductions.push({ phase: "selective", saved: savedSelective });
|
|
555
684
|
}
|
|
685
|
+
const repair = this.repairProtocolAdjacency(ctx);
|
|
556
686
|
const afterTokens = this.estimateTokens(ctx.messages);
|
|
557
|
-
return { before: beforeTokens, after: afterTokens, reductions };
|
|
687
|
+
return { before: beforeTokens, after: afterTokens, reductions, repaired: repair };
|
|
688
|
+
}
|
|
689
|
+
repairProtocolAdjacency(ctx) {
|
|
690
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
691
|
+
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
692
|
+
return repaired.report.changed ? {
|
|
693
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
694
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
695
|
+
removedMessages: repaired.report.removedMessages
|
|
696
|
+
} : void 0;
|
|
558
697
|
}
|
|
559
698
|
/**
|
|
560
699
|
* Run the LLM selector to decide what to keep vs collapse.
|
|
@@ -795,6 +934,7 @@ var AutoCompactionMiddleware = class {
|
|
|
795
934
|
aggressiveOn;
|
|
796
935
|
events;
|
|
797
936
|
failureMode;
|
|
937
|
+
policyProvider;
|
|
798
938
|
/**
|
|
799
939
|
* @param compactor Compactor to use for compaction.
|
|
800
940
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -817,17 +957,25 @@ var AutoCompactionMiddleware = class {
|
|
|
817
957
|
this.aggressiveOn = opts.aggressiveOn ?? "soft";
|
|
818
958
|
this.events = opts.events;
|
|
819
959
|
this.failureMode = opts.failureMode ?? "throw_on_hard";
|
|
960
|
+
this.policyProvider = opts.policyProvider;
|
|
820
961
|
}
|
|
821
962
|
handler() {
|
|
822
963
|
return async (ctx, next) => {
|
|
823
964
|
const tokens = this.estimator(ctx);
|
|
824
965
|
const load = tokens / this.maxContext;
|
|
825
|
-
|
|
966
|
+
const policy = this.policyProvider?.(ctx);
|
|
967
|
+
const thresholds = policy?.thresholds ?? {
|
|
968
|
+
warn: this.warnThreshold,
|
|
969
|
+
soft: this.softThreshold,
|
|
970
|
+
hard: this.hardThreshold
|
|
971
|
+
};
|
|
972
|
+
const aggressiveOn = policy?.aggressiveOn ?? this.aggressiveOn;
|
|
973
|
+
if (load >= thresholds.hard) {
|
|
826
974
|
await this.compact(ctx, true, { level: "hard", tokens, load });
|
|
827
|
-
} else if (load >=
|
|
828
|
-
await this.compact(ctx,
|
|
829
|
-
} else if (load >=
|
|
830
|
-
await this.compact(ctx,
|
|
975
|
+
} else if (load >= thresholds.soft) {
|
|
976
|
+
await this.compact(ctx, aggressiveOn !== "hard", { level: "soft", tokens, load });
|
|
977
|
+
} else if (load >= thresholds.warn) {
|
|
978
|
+
await this.compact(ctx, aggressiveOn === "warn", { level: "warn", tokens, load });
|
|
831
979
|
}
|
|
832
980
|
return next(ctx);
|
|
833
981
|
};
|