@wrongstack/core 0.24.0 → 0.31.1
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/coordination/index.d.ts +3 -3
- package/dist/coordination/index.js +414 -71
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +2 -2
- package/dist/defaults/index.js +388 -57
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.js +47 -5
- package/dist/execution/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +635 -242
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.js +2 -1
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/{multi-agent-coordinator-Dcsc5t4-.d.ts → multi-agent-coordinator-DOXSgtom.d.ts} +4 -0
- package/dist/{null-fleet-bus-Cq4YKOiW.d.ts → null-fleet-bus-CAQDGsKc.d.ts} +58 -2
- package/dist/sdd/index.js +40 -3
- package/dist/sdd/index.js.map +1 -1
- package/dist/types/index.js +2 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +76 -1
- package/dist/utils/index.js +171 -5
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/utils/index.d.ts
CHANGED
|
@@ -142,6 +142,21 @@ declare function createToolOutputSerializer(opts?: ToolOutputSerializerOptions):
|
|
|
142
142
|
/**
|
|
143
143
|
* Shared token estimation with JSON.stringify caching.
|
|
144
144
|
* Avoids repeated stringification of tool input objects.
|
|
145
|
+
*
|
|
146
|
+
* ## Calibration
|
|
147
|
+
*
|
|
148
|
+
* `estimateRequestTokens` uses a fixed 3.5 chars/token heuristic — a
|
|
149
|
+
* conservative overestimate that prevents underestimation but reduces
|
|
150
|
+
* accuracy. After each API call, call `recordActualUsage()` with the
|
|
151
|
+
* real `usage.input` from the provider response. The module maintains a
|
|
152
|
+
* rolling average of `actual / estimated` ratio (EWM, α=0.3) and
|
|
153
|
+
* applies it to subsequent calls via `estimateRequestTokensCalibrated`.
|
|
154
|
+
*
|
|
155
|
+
* Calibration is per-module (shared across all callers), which is
|
|
156
|
+
* sufficient: the chars/token ratio is a property of the tokenizer,
|
|
157
|
+
* not the model. Uncalibrated calls (before any samples, or when
|
|
158
|
+
* `recordActualUsage` is not called) fall back to the uncalibrated
|
|
159
|
+
* estimate so nothing breaks.
|
|
145
160
|
*/
|
|
146
161
|
/**
|
|
147
162
|
* Estimate tokens for a tool_use block input.
|
|
@@ -190,6 +205,47 @@ declare function estimateRequestTokens(messages: unknown, systemPrompt: unknown,
|
|
|
190
205
|
description?: string;
|
|
191
206
|
inputSchema: unknown;
|
|
192
207
|
}[]): RequestTokenBreakdown;
|
|
208
|
+
/**
|
|
209
|
+
* Record the actual API input token count after a provider call so
|
|
210
|
+
* `estimateRequestTokensCalibrated` can self-correct on subsequent calls.
|
|
211
|
+
*
|
|
212
|
+
* Prefer passing `estimatedInputTokens` explicitly (the calibrated pre-flight
|
|
213
|
+
* estimate from the middleware) — this avoids race conditions when other code
|
|
214
|
+
* also calls `estimateRequestTokens` between the pre-flight and this call
|
|
215
|
+
* (e.g. audit logging in agent.ts).
|
|
216
|
+
*
|
|
217
|
+
* When `estimatedInputTokens` is omitted, falls back to `_cal.prevEst`
|
|
218
|
+
* for backward compatibility with callers that don't have the pre-flight value.
|
|
219
|
+
*/
|
|
220
|
+
declare function recordActualUsage(actualInputTokens: number, estimatedInputTokens?: number): void;
|
|
221
|
+
/**
|
|
222
|
+
* Returns the current calibration state. Exposed for debugging and
|
|
223
|
+
* tests — not needed by normal callers.
|
|
224
|
+
*/
|
|
225
|
+
declare function getCalibrationState(): {
|
|
226
|
+
ratio: number;
|
|
227
|
+
count: number;
|
|
228
|
+
calibrated: boolean;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Like `estimateRequestTokens` but applies the rolling calibration factor
|
|
232
|
+
* so context pressure readings converge on reality within a few iterations.
|
|
233
|
+
*
|
|
234
|
+
* Before any `recordActualUsage` samples are collected, returns the same
|
|
235
|
+
* result as `estimateRequestTokens` (ratio = 1.0, no distortion).
|
|
236
|
+
* After `MIN_SAMPLES_FOR_CALIBRATION` samples, applies the calibrated
|
|
237
|
+
* multiplier capped to the range [0.5, 1.5] as a sanity bound.
|
|
238
|
+
*/
|
|
239
|
+
declare function estimateRequestTokensCalibrated(messages: unknown, systemPrompt: unknown, tools: {
|
|
240
|
+
name: string;
|
|
241
|
+
description?: string;
|
|
242
|
+
inputSchema: unknown;
|
|
243
|
+
}[]): RequestTokenBreakdown;
|
|
244
|
+
/**
|
|
245
|
+
* Resets calibration state. Primarily for tests that run in the same
|
|
246
|
+
* process and need a clean slate between suites.
|
|
247
|
+
*/
|
|
248
|
+
declare function resetCalibration(): void;
|
|
193
249
|
|
|
194
250
|
interface MessageRepairReport {
|
|
195
251
|
changed: boolean;
|
|
@@ -254,6 +310,25 @@ interface CompileFail {
|
|
|
254
310
|
}
|
|
255
311
|
declare function compileUserRegex(pattern: string, flags: string): CompileResult | CompileFail;
|
|
256
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Glob pattern → concrete file path expansion.
|
|
315
|
+
*
|
|
316
|
+
* Supports: *, **, ?, [...]
|
|
317
|
+
* Does NOT support brace expansion {a,b}.
|
|
318
|
+
*
|
|
319
|
+
* Returns the input as-is if it contains no glob metacharacters.
|
|
320
|
+
* On Windows, both / and \ are accepted as path separators.
|
|
321
|
+
*/
|
|
322
|
+
/**
|
|
323
|
+
* Resolve `pattern` to the set of concrete file paths it matches.
|
|
324
|
+
* Literal paths (no glob chars) are returned as-is.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* await expandGlob('src/**\/*.ts') // → ['src/a.ts', 'src/b/c.ts', ...]
|
|
328
|
+
* await expandGlob('foo.txt') // → ['foo.txt']
|
|
329
|
+
*/
|
|
330
|
+
declare function expandGlob(pattern: string): Promise<string[]>;
|
|
331
|
+
|
|
257
332
|
/**
|
|
258
333
|
* Attempt to close an incomplete JSON object string by auto-closing braces
|
|
259
334
|
* and completing any unclosed double-quoted string values.
|
|
@@ -296,4 +371,4 @@ declare function completePartialObject(s: string): string;
|
|
|
296
371
|
*/
|
|
297
372
|
declare function mergeModelsPayload(base: ModelsDevPayload, overlay: ModelsDevPayload): ModelsDevPayload;
|
|
298
373
|
|
|
299
|
-
export { type AtomicWriteOptions, type BuildChildEnvOptions, type CompileFail, type CompileResult, type MessageRepairReport, type MessageRepairResult, type NewlineStyle, type RequestTokenBreakdown, type SafeParseResult, type ToolOutputSerializerOptions, type UnifiedDiffOptions, type ValidationError, type ValidationResult, atomicWrite, buildChildEnv, color, compileGlob, compileUserRegex, completePartialObject, createToolOutputSerializer, detectNewlineStyle, ensureDir, estimateRequestTokens, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, formatTodosList, matchAny, matchGlob, mergeModelsPayload, normalizeToLf, repairToolUseAdjacency, safeParse, safeStringify, sanitizeJsonString, stripAnsi, toStyle, unifiedDiff, validateAgainstSchema };
|
|
374
|
+
export { type AtomicWriteOptions, type BuildChildEnvOptions, type CompileFail, type CompileResult, type MessageRepairReport, type MessageRepairResult, type NewlineStyle, type RequestTokenBreakdown, type SafeParseResult, type ToolOutputSerializerOptions, type UnifiedDiffOptions, type ValidationError, type ValidationResult, atomicWrite, buildChildEnv, color, compileGlob, compileUserRegex, completePartialObject, createToolOutputSerializer, detectNewlineStyle, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, expandGlob, formatTodosList, getCalibrationState, matchAny, matchGlob, mergeModelsPayload, normalizeToLf, recordActualUsage, repairToolUseAdjacency, resetCalibration, safeParse, safeStringify, sanitizeJsonString, stripAnsi, toStyle, unifiedDiff, validateAgainstSchema };
|
package/dist/utils/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomBytes, createHash } from 'crypto';
|
|
2
2
|
import * as fs from 'fs/promises';
|
|
3
3
|
import * as path2 from 'path';
|
|
4
|
+
import { isAbsolute, resolve } from 'path';
|
|
4
5
|
import * as os from 'os';
|
|
5
6
|
|
|
6
7
|
// src/utils/atomic-write.ts
|
|
@@ -25,8 +26,8 @@ async function atomicWrite(targetPath, content, opts = {}) {
|
|
|
25
26
|
}
|
|
26
27
|
let mode;
|
|
27
28
|
try {
|
|
28
|
-
const
|
|
29
|
-
mode =
|
|
29
|
+
const stat3 = await fs.stat(targetPath);
|
|
30
|
+
mode = stat3.mode & 511;
|
|
30
31
|
} catch {
|
|
31
32
|
mode = opts.mode;
|
|
32
33
|
}
|
|
@@ -63,7 +64,7 @@ async function renameWithRetry(from, to) {
|
|
|
63
64
|
if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
|
|
64
65
|
throw err;
|
|
65
66
|
}
|
|
66
|
-
await new Promise((
|
|
67
|
+
await new Promise((resolve3) => setTimeout(resolve3, delays[i]));
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
throw lastErr;
|
|
@@ -657,6 +658,17 @@ function createToolOutputSerializer(opts = {}) {
|
|
|
657
658
|
|
|
658
659
|
// src/utils/token-estimate.ts
|
|
659
660
|
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
661
|
+
var _cal = {
|
|
662
|
+
ratio: 1,
|
|
663
|
+
// current calibration multiplier (actual / estimated)
|
|
664
|
+
count: 0,
|
|
665
|
+
// number of samples recorded
|
|
666
|
+
prevEst: 0,
|
|
667
|
+
// estimated tokens from the most recent estimateRequestTokens call
|
|
668
|
+
/** EWM α — higher = faster adaptation, more volatile */
|
|
669
|
+
alpha: 0.3
|
|
670
|
+
};
|
|
671
|
+
var MIN_SAMPLES_FOR_CALIBRATION = 3;
|
|
660
672
|
var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
|
|
661
673
|
var ESTIMATE_CACHE_MAX_SIZE = 1e4;
|
|
662
674
|
function getCachedEstimate(key, compute) {
|
|
@@ -729,13 +741,53 @@ function estimateRequestTokens(messages, systemPrompt, tools) {
|
|
|
729
741
|
for (const t of tools) {
|
|
730
742
|
toolsTokens += estimateToolDefTokens(t);
|
|
731
743
|
}
|
|
744
|
+
const total = messagesTokens + systemTokens + toolsTokens;
|
|
745
|
+
_cal.prevEst = total;
|
|
732
746
|
return {
|
|
733
747
|
messages: messagesTokens,
|
|
734
748
|
systemPrompt: systemTokens,
|
|
735
749
|
tools: toolsTokens,
|
|
736
|
-
total
|
|
750
|
+
total
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
function recordActualUsage(actualInputTokens, estimatedInputTokens) {
|
|
754
|
+
if (actualInputTokens <= 0) return;
|
|
755
|
+
const est = estimatedInputTokens ?? _cal.prevEst;
|
|
756
|
+
if (est <= 0) return;
|
|
757
|
+
const sampleRatio = actualInputTokens / est;
|
|
758
|
+
if (_cal.count === 0) {
|
|
759
|
+
_cal.ratio = sampleRatio;
|
|
760
|
+
} else {
|
|
761
|
+
_cal.ratio = _cal.alpha * sampleRatio + (1 - _cal.alpha) * _cal.ratio;
|
|
762
|
+
}
|
|
763
|
+
_cal.ratio = Math.min(1.5, Math.max(0.5, _cal.ratio));
|
|
764
|
+
_cal.count++;
|
|
765
|
+
}
|
|
766
|
+
function getCalibrationState() {
|
|
767
|
+
return {
|
|
768
|
+
ratio: _cal.ratio,
|
|
769
|
+
count: _cal.count,
|
|
770
|
+
calibrated: _cal.count >= MIN_SAMPLES_FOR_CALIBRATION
|
|
737
771
|
};
|
|
738
772
|
}
|
|
773
|
+
function estimateRequestTokensCalibrated(messages, systemPrompt, tools) {
|
|
774
|
+
const result = estimateRequestTokens(messages, systemPrompt, tools);
|
|
775
|
+
if (_cal.count >= MIN_SAMPLES_FOR_CALIBRATION) {
|
|
776
|
+
const safeRatio = Math.min(1.5, Math.max(0.5, _cal.ratio));
|
|
777
|
+
return {
|
|
778
|
+
messages: Math.round(result.messages * safeRatio),
|
|
779
|
+
systemPrompt: Math.round(result.systemPrompt * safeRatio),
|
|
780
|
+
tools: Math.round(result.tools * safeRatio),
|
|
781
|
+
total: Math.round(result.total * safeRatio)
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
return result;
|
|
785
|
+
}
|
|
786
|
+
function resetCalibration() {
|
|
787
|
+
_cal.ratio = 1;
|
|
788
|
+
_cal.count = 0;
|
|
789
|
+
_cal.prevEst = 0;
|
|
790
|
+
}
|
|
739
791
|
|
|
740
792
|
// src/utils/message-invariants.ts
|
|
741
793
|
function repairToolUseAdjacency(messages) {
|
|
@@ -958,6 +1010,120 @@ function compileUserRegex(pattern, flags) {
|
|
|
958
1010
|
};
|
|
959
1011
|
}
|
|
960
1012
|
}
|
|
1013
|
+
var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
|
|
1014
|
+
var IS_WINDOWS = process.platform === "win32";
|
|
1015
|
+
var SEP = IS_WINDOWS ? "\\" : "/";
|
|
1016
|
+
function isGlob(p) {
|
|
1017
|
+
for (const c of p) {
|
|
1018
|
+
if (GLOB_CHARS.has(c)) return true;
|
|
1019
|
+
}
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
function globToRegex(pat) {
|
|
1023
|
+
let i = 0, re = "^";
|
|
1024
|
+
while (i < pat.length) {
|
|
1025
|
+
const c = pat[i];
|
|
1026
|
+
if (c === "*") {
|
|
1027
|
+
if (pat[i + 1] === "*") {
|
|
1028
|
+
re += ".*";
|
|
1029
|
+
i += 2;
|
|
1030
|
+
if (pat[i] === "/") i++;
|
|
1031
|
+
} else {
|
|
1032
|
+
re += "[^/\\\\]*";
|
|
1033
|
+
i++;
|
|
1034
|
+
}
|
|
1035
|
+
} else if (c === "?") {
|
|
1036
|
+
re += "[^/\\\\]";
|
|
1037
|
+
i++;
|
|
1038
|
+
} else if (c === "[") {
|
|
1039
|
+
let cls = "[";
|
|
1040
|
+
i++;
|
|
1041
|
+
if (pat[i] === "!" || pat[i] === "^") {
|
|
1042
|
+
cls += "^";
|
|
1043
|
+
i++;
|
|
1044
|
+
}
|
|
1045
|
+
while (i < pat.length && pat[i] !== "]") {
|
|
1046
|
+
const ch = pat[i] ?? "";
|
|
1047
|
+
if (ch === "\\") cls += "\\\\";
|
|
1048
|
+
else if (ch === "]" || ch === "^") cls += `\\${ch}`;
|
|
1049
|
+
else cls += ch;
|
|
1050
|
+
i++;
|
|
1051
|
+
}
|
|
1052
|
+
cls += "]";
|
|
1053
|
+
re += cls;
|
|
1054
|
+
i++;
|
|
1055
|
+
} else {
|
|
1056
|
+
re += c.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
1057
|
+
i++;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
return new RegExp(re + "$");
|
|
1061
|
+
}
|
|
1062
|
+
function baseDir(pat) {
|
|
1063
|
+
let i = pat.length - 1;
|
|
1064
|
+
while (i >= 0 && !GLOB_CHARS.has(pat[i]) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
1065
|
+
const cut = i >= 0 ? pat.lastIndexOf(SEP, i) : pat.lastIndexOf("/", i);
|
|
1066
|
+
return cut < 0 ? "." : pat.slice(0, cut);
|
|
1067
|
+
}
|
|
1068
|
+
async function expandGlob(pattern) {
|
|
1069
|
+
if (!isGlob(pattern)) return [pattern];
|
|
1070
|
+
const results = /* @__PURE__ */ new Set();
|
|
1071
|
+
const abs = isAbsolute(pattern);
|
|
1072
|
+
const base = abs ? baseDir(pattern) : baseDir(pattern);
|
|
1073
|
+
const relPat = base === "." ? pattern : pattern.slice(base.length + 1);
|
|
1074
|
+
async function walk2(dir, pat) {
|
|
1075
|
+
let entries;
|
|
1076
|
+
try {
|
|
1077
|
+
entries = await fs.readdir(dir);
|
|
1078
|
+
} catch {
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
const firstGlob = pat.search(/[*?[\[]/);
|
|
1082
|
+
if (firstGlob < 0) {
|
|
1083
|
+
const re = globToRegex(pat);
|
|
1084
|
+
for (const e of entries) {
|
|
1085
|
+
if (re.test(e)) {
|
|
1086
|
+
const full = `${dir}${SEP}${e}`;
|
|
1087
|
+
results.add(abs ? resolve(full) : full);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
const before = pat.slice(0, firstGlob);
|
|
1093
|
+
const rest = pat.slice(firstGlob);
|
|
1094
|
+
if (before.endsWith("**")) {
|
|
1095
|
+
await walk2(dir, rest);
|
|
1096
|
+
for (const e of entries) {
|
|
1097
|
+
const full = `${dir}${SEP}${e}`;
|
|
1098
|
+
try {
|
|
1099
|
+
const stat3 = await fs.stat(full);
|
|
1100
|
+
if (stat3.isDirectory()) await walk2(full, rest);
|
|
1101
|
+
} catch {
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
} else if (before === "") {
|
|
1105
|
+
const re = globToRegex(rest);
|
|
1106
|
+
for (const e of entries) {
|
|
1107
|
+
if (re.test(e)) {
|
|
1108
|
+
const full = `${dir}${SEP}${e}`;
|
|
1109
|
+
results.add(abs ? resolve(full) : full);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
} else {
|
|
1113
|
+
const seg = before.replace(/[*?[\]]/g, "").replace(/\/$/, "");
|
|
1114
|
+
if (entries.includes(seg)) {
|
|
1115
|
+
const full = `${dir}${SEP}${seg}`;
|
|
1116
|
+
try {
|
|
1117
|
+
const stat3 = await fs.stat(full);
|
|
1118
|
+
if (stat3.isDirectory()) await walk2(full, rest);
|
|
1119
|
+
} catch {
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
await walk2(base === "." ? "." : base, relPat);
|
|
1125
|
+
return [...results];
|
|
1126
|
+
}
|
|
961
1127
|
|
|
962
1128
|
// src/utils/json-repair.ts
|
|
963
1129
|
function completePartialObject(s) {
|
|
@@ -1111,6 +1277,6 @@ function stripUndefined(obj) {
|
|
|
1111
1277
|
return out;
|
|
1112
1278
|
}
|
|
1113
1279
|
|
|
1114
|
-
export { atomicWrite, buildChildEnv, color, compileGlob, compileUserRegex, completePartialObject, createToolOutputSerializer, detectNewlineStyle, ensureDir, estimateRequestTokens, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, formatTodosList, matchAny, matchGlob, mergeModelsPayload, normalizeToLf, projectHash, repairToolUseAdjacency, resolveWstackPaths, safeParse, safeStringify, sanitizeJsonString, stripAnsi, toStyle, unifiedDiff, validateAgainstSchema };
|
|
1280
|
+
export { atomicWrite, buildChildEnv, color, compileGlob, compileUserRegex, completePartialObject, createToolOutputSerializer, detectNewlineStyle, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, expandGlob, formatTodosList, getCalibrationState, matchAny, matchGlob, mergeModelsPayload, normalizeToLf, projectHash, recordActualUsage, repairToolUseAdjacency, resetCalibration, resolveWstackPaths, safeParse, safeStringify, sanitizeJsonString, stripAnsi, toStyle, unifiedDiff, validateAgainstSchema };
|
|
1115
1281
|
//# sourceMappingURL=index.js.map
|
|
1116
1282
|
//# sourceMappingURL=index.js.map
|