@wrongstack/core 0.256.1 → 0.257.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.
- package/dist/defaults/index.d.ts +1 -1
- package/dist/defaults/index.js +128 -22
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.js +107 -20
- package/dist/execution/index.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +144 -38
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.js +9 -8
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/models/index.js +9 -8
- package/dist/models/index.js.map +1 -1
- package/dist/sdd/index.js +7 -2
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-BkYkJWQs.d.ts → secret-vault-gxtFZYBt.d.ts} +7 -0
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +23 -9
- package/dist/security/index.js.map +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +137 -36
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.js +9 -8
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,8 +16,8 @@ export { C as CheckpointInfo, R as RewindResult, a as RewindResultExtended, S as
|
|
|
16
16
|
import { A as AttachmentStore, b as AttachmentRef, a as AddAttachmentInput } from './session-reader-CqRvaL5v.js';
|
|
17
17
|
export { c as Attachment, d as AttachmentKind, e as AttachmentMeta, D as DefaultSessionReader, f as DefaultSessionReaderOptions, S as SessionReader } from './session-reader-CqRvaL5v.js';
|
|
18
18
|
export { D as DEFAULT_AUTONOMY_CONFIG, a as DEFAULT_CONTEXT_CONFIG, b as DEFAULT_SESSION_LOGGING_CONFIG, c as DEFAULT_SESSION_PRUNE_DAYS, d as DEFAULT_TOOLS_CONFIG } from './default-config-CXsDvOmP.js';
|
|
19
|
-
import { a as DefaultSecretVault } from './secret-vault-
|
|
20
|
-
export { D as DefaultSecretScrubber, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from './secret-vault-
|
|
19
|
+
import { a as DefaultSecretVault } from './secret-vault-gxtFZYBt.js';
|
|
20
|
+
export { D as DefaultSecretScrubber, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from './secret-vault-gxtFZYBt.js';
|
|
21
21
|
import { D as DefaultLogger } from './logger-DmmQhf4P.js';
|
|
22
22
|
export { a as DefaultLoggerOptions, L as LogFormat, n as noOpLogger } from './logger-DmmQhf4P.js';
|
|
23
23
|
import { D as DefaultPathResolver } from './path-resolver-CbkT-RMU.js';
|
|
@@ -504,6 +504,10 @@ declare function hasTextContent(m: Message): boolean;
|
|
|
504
504
|
* user/assistant messages until `preserveK` are covered, then walks forward to
|
|
505
505
|
* keep any tool_use/tool_result protocol pair intact — so a tool_result whose
|
|
506
506
|
* tool_use is preserved is never elided.
|
|
507
|
+
*
|
|
508
|
+
* Instrumentation: emits `compaction.find_preserve_start.ended` with the
|
|
509
|
+
* forward-walk inner-loop count so we can track whether the `.some()` calls
|
|
510
|
+
* over content blocks are causing measurable O(n·m) overhead.
|
|
507
511
|
*/
|
|
508
512
|
declare function findPreserveStart(messages: readonly Message[], preserveK: number): number;
|
|
509
513
|
interface EliseResult {
|
package/dist/index.js
CHANGED
|
@@ -16,8 +16,13 @@ import { pipeline } from 'stream/promises';
|
|
|
16
16
|
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
18
18
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
19
|
-
var __esm = (fn, res) => function __init() {
|
|
20
|
-
|
|
19
|
+
var __esm = (fn, res, err) => function __init() {
|
|
20
|
+
if (err) throw err[0];
|
|
21
|
+
try {
|
|
22
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
23
|
+
} catch (e) {
|
|
24
|
+
throw err = [e], e;
|
|
25
|
+
}
|
|
21
26
|
};
|
|
22
27
|
var __export = (target, all) => {
|
|
23
28
|
for (var name in all)
|
|
@@ -2169,16 +2174,6 @@ var MEMORY_TYPE_LABELS = {
|
|
|
2169
2174
|
anti_pattern: "Anti-pattern"
|
|
2170
2175
|
};
|
|
2171
2176
|
|
|
2172
|
-
// src/utils/expect-defined.ts
|
|
2173
|
-
function expectDefined(value, label) {
|
|
2174
|
-
if (value === null || value === void 0) {
|
|
2175
|
-
const err = new Error(label ? `Expected ${label} to be defined` : "Expected value to be defined");
|
|
2176
|
-
err.name = "ExpectDefinedError";
|
|
2177
|
-
throw err;
|
|
2178
|
-
}
|
|
2179
|
-
return value;
|
|
2180
|
-
}
|
|
2181
|
-
|
|
2182
2177
|
// src/utils/token-estimate.ts
|
|
2183
2178
|
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
2184
2179
|
var CAL_ALPHA = 0.3;
|
|
@@ -2199,12 +2194,15 @@ function getCachedEstimate(key, compute) {
|
|
|
2199
2194
|
const existing = ESTIMATE_CACHE.get(key);
|
|
2200
2195
|
if (existing !== void 0) return existing;
|
|
2201
2196
|
if (ESTIMATE_CACHE.size >= ESTIMATE_CACHE_MAX_SIZE) {
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2197
|
+
let evicted = 0;
|
|
2198
|
+
const maxEvict = Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4);
|
|
2199
|
+
for (const k of ESTIMATE_CACHE.keys()) {
|
|
2200
|
+
if (evicted >= maxEvict) break;
|
|
2201
|
+
ESTIMATE_CACHE.delete(k);
|
|
2202
|
+
evicted++;
|
|
2205
2203
|
}
|
|
2206
2204
|
}
|
|
2207
|
-
const estimate = compute();
|
|
2205
|
+
const estimate = compute(key);
|
|
2208
2206
|
ESTIMATE_CACHE.set(key, estimate);
|
|
2209
2207
|
return estimate;
|
|
2210
2208
|
}
|
|
@@ -2213,13 +2211,11 @@ function estimateToolInputTokens(input) {
|
|
|
2213
2211
|
if (input === null || typeof input !== "object") {
|
|
2214
2212
|
return RoughTokenEstimate(String(input));
|
|
2215
2213
|
}
|
|
2216
|
-
|
|
2217
|
-
return getCachedEstimate(key, () => RoughTokenEstimate(key));
|
|
2214
|
+
return getCachedEstimate(JSON.stringify(input), (key) => RoughTokenEstimate(key));
|
|
2218
2215
|
}
|
|
2219
2216
|
function estimateToolResultTokens(content) {
|
|
2220
2217
|
if (typeof content === "string") return RoughTokenEstimate(content);
|
|
2221
|
-
|
|
2222
|
-
return getCachedEstimate(key, () => RoughTokenEstimate(key));
|
|
2218
|
+
return getCachedEstimate(JSON.stringify(content), (key) => RoughTokenEstimate(key));
|
|
2223
2219
|
}
|
|
2224
2220
|
function estimateTextTokens(text) {
|
|
2225
2221
|
return RoughTokenEstimate(text);
|
|
@@ -2347,6 +2343,16 @@ function resetCalibration(calibrationKey) {
|
|
|
2347
2343
|
_cals.delete(calibrationKey);
|
|
2348
2344
|
}
|
|
2349
2345
|
|
|
2346
|
+
// src/utils/expect-defined.ts
|
|
2347
|
+
function expectDefined(value, label) {
|
|
2348
|
+
if (value === null || value === void 0) {
|
|
2349
|
+
const err = new Error(label ? `Expected ${label} to be defined` : "Expected value to be defined");
|
|
2350
|
+
err.name = "ExpectDefinedError";
|
|
2351
|
+
throw err;
|
|
2352
|
+
}
|
|
2353
|
+
return value;
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2350
2356
|
// src/utils/message-invariants.ts
|
|
2351
2357
|
function repairToolUseAdjacency(messages) {
|
|
2352
2358
|
const removedToolUses = [];
|
|
@@ -2440,6 +2446,25 @@ function isEmptyMessage(msg) {
|
|
|
2440
2446
|
}
|
|
2441
2447
|
|
|
2442
2448
|
// src/execution/compaction-core.ts
|
|
2449
|
+
function emitCompactionMetrics(event, metrics) {
|
|
2450
|
+
console.log(
|
|
2451
|
+
JSON.stringify({
|
|
2452
|
+
level: "debug",
|
|
2453
|
+
event,
|
|
2454
|
+
messageCount: metrics.messageCount,
|
|
2455
|
+
preserveStart: metrics.preserveStart,
|
|
2456
|
+
fastPathIterations: metrics.fastPathIterations,
|
|
2457
|
+
fastPathInnerIterations: metrics.fastPathInnerIterations,
|
|
2458
|
+
// Ratios — anything > 2.0 indicates the inner loop is running more than expected
|
|
2459
|
+
fastPathInnerPerOuter: metrics.fastPathIterations > 0 ? metrics.fastPathInnerIterations / metrics.fastPathIterations : 0,
|
|
2460
|
+
fullPassIterations: metrics.fullPassIterations,
|
|
2461
|
+
fullPassInnerIterations: metrics.fullPassInnerIterations,
|
|
2462
|
+
fullPassInnerPerOuter: metrics.fullPassIterations > 0 ? metrics.fullPassInnerIterations / metrics.fullPassIterations : 0,
|
|
2463
|
+
tokensSaved: metrics.tokensSaved,
|
|
2464
|
+
changed: metrics.changed
|
|
2465
|
+
})
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2443
2468
|
var estimateMessages = estimateMessageTokens;
|
|
2444
2469
|
function hasTextContent(m) {
|
|
2445
2470
|
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
@@ -2456,37 +2481,78 @@ function findPreserveStart(messages, preserveK) {
|
|
|
2456
2481
|
preserveStart = i;
|
|
2457
2482
|
}
|
|
2458
2483
|
}
|
|
2484
|
+
let forwardWalkIterations = 0;
|
|
2485
|
+
let forwardWalkInnerIterations = 0;
|
|
2459
2486
|
for (let i = preserveStart; i < messages.length; i++) {
|
|
2487
|
+
forwardWalkIterations++;
|
|
2460
2488
|
const m = messages[i];
|
|
2461
2489
|
if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
|
|
2462
|
-
const hasToolUse3 = m.content.some((b) =>
|
|
2490
|
+
const hasToolUse3 = m.content.some((b) => {
|
|
2491
|
+
forwardWalkInnerIterations++;
|
|
2492
|
+
return b.type === "tool_use";
|
|
2493
|
+
});
|
|
2463
2494
|
if (hasToolUse3 && i + 1 < messages.length) {
|
|
2464
2495
|
const next = messages[i + 1];
|
|
2465
|
-
if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) =>
|
|
2496
|
+
if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => {
|
|
2497
|
+
forwardWalkInnerIterations++;
|
|
2498
|
+
return b.type === "tool_result";
|
|
2499
|
+
})) {
|
|
2466
2500
|
preserveStart = i + 1;
|
|
2467
2501
|
}
|
|
2468
2502
|
}
|
|
2469
2503
|
}
|
|
2504
|
+
console.log(
|
|
2505
|
+
JSON.stringify({
|
|
2506
|
+
level: "debug",
|
|
2507
|
+
event: "compaction.find_preserve_start.ended",
|
|
2508
|
+
messageCount: messages.length,
|
|
2509
|
+
preserveK,
|
|
2510
|
+
preserveStart,
|
|
2511
|
+
forwardWalkIterations,
|
|
2512
|
+
forwardWalkInnerIterations,
|
|
2513
|
+
forwardWalkInnerPerOuter: forwardWalkIterations > 0 ? forwardWalkInnerIterations / forwardWalkIterations : 0
|
|
2514
|
+
})
|
|
2515
|
+
);
|
|
2470
2516
|
return preserveStart;
|
|
2471
2517
|
}
|
|
2472
2518
|
function eliseOldToolResults(messages, opts) {
|
|
2473
2519
|
const preserveStart = findPreserveStart(messages, opts.preserveK);
|
|
2474
2520
|
let hasOversized = false;
|
|
2521
|
+
let fastPathIterations = 0;
|
|
2522
|
+
let fastPathInnerIterations = 0;
|
|
2475
2523
|
for (let i = 0; i < preserveStart && !hasOversized; i++) {
|
|
2524
|
+
fastPathIterations++;
|
|
2476
2525
|
const msg = messages[i];
|
|
2477
2526
|
if (!msg || !Array.isArray(msg.content)) continue;
|
|
2478
2527
|
for (const b of msg.content) {
|
|
2528
|
+
fastPathInnerIterations++;
|
|
2479
2529
|
if (b.type === "tool_result" && estimateToolResultTokens(b.content) >= opts.eliseThreshold) {
|
|
2480
2530
|
hasOversized = true;
|
|
2481
2531
|
break;
|
|
2482
2532
|
}
|
|
2483
2533
|
}
|
|
2484
2534
|
}
|
|
2535
|
+
emitCompactionMetrics(
|
|
2536
|
+
hasOversized ? "compaction.elision.fast_path.oversized_found" : "compaction.elision.fast_path.no_oversized",
|
|
2537
|
+
{
|
|
2538
|
+
messageCount: messages.length,
|
|
2539
|
+
preserveStart,
|
|
2540
|
+
fastPathIterations,
|
|
2541
|
+
fastPathInnerIterations,
|
|
2542
|
+
fullPassIterations: 0,
|
|
2543
|
+
fullPassInnerIterations: 0,
|
|
2544
|
+
tokensSaved: 0,
|
|
2545
|
+
changed: false
|
|
2546
|
+
}
|
|
2547
|
+
);
|
|
2485
2548
|
if (!hasOversized) return { messages, saved: 0, changed: false };
|
|
2486
2549
|
let saved = 0;
|
|
2487
2550
|
let changed = false;
|
|
2551
|
+
let fullPassIterations = 0;
|
|
2552
|
+
let fullPassInnerIterations = 0;
|
|
2488
2553
|
const next = new Array(messages.length);
|
|
2489
2554
|
for (let i = 0; i < messages.length; i++) {
|
|
2555
|
+
fullPassIterations++;
|
|
2490
2556
|
const msg = messages[i];
|
|
2491
2557
|
if (i >= preserveStart || !msg || !Array.isArray(msg.content)) {
|
|
2492
2558
|
next[i] = msg;
|
|
@@ -2512,7 +2578,33 @@ function eliseOldToolResults(messages, opts) {
|
|
|
2512
2578
|
next[i] = { ...msg, content: newContent };
|
|
2513
2579
|
changed = true;
|
|
2514
2580
|
}
|
|
2581
|
+
fullPassInnerIterations += original.length;
|
|
2582
|
+
if (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1") {
|
|
2583
|
+
const ratio = fullPassInnerIterations / fullPassIterations;
|
|
2584
|
+
if (ratio > 10) {
|
|
2585
|
+
console.error(
|
|
2586
|
+
JSON.stringify({
|
|
2587
|
+
level: "error",
|
|
2588
|
+
event: "compaction.elision.regression",
|
|
2589
|
+
message: `fullPassInnerPerOuter=${ratio.toFixed(2)} exceeds threshold 10 \u2014 possible O(n\xB7m) regression`,
|
|
2590
|
+
messageCount: messages.length,
|
|
2591
|
+
fullPassIterations,
|
|
2592
|
+
fullPassInnerIterations
|
|
2593
|
+
})
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2515
2597
|
}
|
|
2598
|
+
emitCompactionMetrics("compaction.elision.full_pass.ended", {
|
|
2599
|
+
messageCount: messages.length,
|
|
2600
|
+
preserveStart,
|
|
2601
|
+
fastPathIterations,
|
|
2602
|
+
fastPathInnerIterations,
|
|
2603
|
+
fullPassIterations,
|
|
2604
|
+
fullPassInnerIterations,
|
|
2605
|
+
tokensSaved: saved,
|
|
2606
|
+
changed
|
|
2607
|
+
});
|
|
2516
2608
|
return { messages: changed ? next : messages, saved, changed };
|
|
2517
2609
|
}
|
|
2518
2610
|
function buildLosslessDigest(messages) {
|
|
@@ -3060,6 +3152,10 @@ var PATTERNS = [
|
|
|
3060
3152
|
regex: /(?:^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?:\s|$)/g
|
|
3061
3153
|
}
|
|
3062
3154
|
];
|
|
3155
|
+
var SIMPLE_PATTERNS = PATTERNS.filter((p) => p.type !== "high_entropy_env");
|
|
3156
|
+
var COMBINED_REGEX = new RegExp(SIMPLE_PATTERNS.map((p) => `(${p.regex.source})`).join("|"), "g");
|
|
3157
|
+
var HIGH_ENTROPY_REGEX = PATTERNS.find((p) => p.type === "high_entropy_env").regex;
|
|
3158
|
+
var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
|
|
3063
3159
|
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
3064
3160
|
function hasCredentialAnchors(text) {
|
|
3065
3161
|
return text.includes("-----BEGIN") || // Private keys (most unique → cheap reject)
|
|
@@ -3101,17 +3197,27 @@ var DefaultSecretScrubber = class {
|
|
|
3101
3197
|
}
|
|
3102
3198
|
scrubOne(text) {
|
|
3103
3199
|
if (!hasCredentialAnchors(text)) return text;
|
|
3104
|
-
let out = text
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
return
|
|
3111
|
-
}
|
|
3112
|
-
|
|
3200
|
+
let out = text.replace(
|
|
3201
|
+
COMBINED_REGEX,
|
|
3202
|
+
(match, ...groups) => {
|
|
3203
|
+
const idx = groups.findIndex((g) => g !== void 0);
|
|
3204
|
+
if (idx < 0) return match;
|
|
3205
|
+
const replacement = COMBINED_REPLACEMENTS[idx];
|
|
3206
|
+
return replacement !== void 0 ? replacement : match;
|
|
3207
|
+
}
|
|
3208
|
+
);
|
|
3209
|
+
out = out.replace(HIGH_ENTROPY_REGEX, (_match, group1, _group2) => {
|
|
3210
|
+
return `${group1}=[REDACTED:high_entropy_env]`;
|
|
3211
|
+
});
|
|
3113
3212
|
return out;
|
|
3114
3213
|
}
|
|
3214
|
+
/**
|
|
3215
|
+
* Recursively scrub every string value in an object/array graph. Secrets can
|
|
3216
|
+
* appear under any key — a URL query param, an `authorization` header, an
|
|
3217
|
+
* arbitrarily-named nested field — so we don't gate recursion on key names.
|
|
3218
|
+
* The per-string `scrub()` fast-path (anchor pre-scan) keeps this cheap: any
|
|
3219
|
+
* value without a credential anchor returns immediately without regex work.
|
|
3220
|
+
*/
|
|
3115
3221
|
scrubObject(obj) {
|
|
3116
3222
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
3117
3223
|
const visit = (v) => {
|
|
@@ -4857,12 +4963,12 @@ var ConversationState = class {
|
|
|
4857
4963
|
for (const m of messages) {
|
|
4858
4964
|
if (m._estTokens === void 0) {
|
|
4859
4965
|
m._estTokens = computeMessageTokens(m);
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4966
|
+
if (Array.isArray(m.content)) {
|
|
4967
|
+
for (const b of m.content) {
|
|
4968
|
+
if (b.type === "tool_use" || b.type === "tool_result") {
|
|
4969
|
+
hasToolBlock = true;
|
|
4970
|
+
break;
|
|
4971
|
+
}
|
|
4866
4972
|
}
|
|
4867
4973
|
}
|
|
4868
4974
|
}
|
|
@@ -5121,7 +5227,7 @@ var DefaultSessionReader = class {
|
|
|
5121
5227
|
this.store = opts.store;
|
|
5122
5228
|
}
|
|
5123
5229
|
async query(q = {}) {
|
|
5124
|
-
const raw = await this.store.list(q.limit ? Math.max(q.limit
|
|
5230
|
+
const raw = await this.store.list(q.limit ? Math.max(q.limit, 100) : 1e3);
|
|
5125
5231
|
const titleNeedle = q.titleContains?.toLowerCase();
|
|
5126
5232
|
const filtered = raw.filter((s) => {
|
|
5127
5233
|
if (q.since && s.startedAt < q.since) return false;
|