@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.
@@ -3,7 +3,7 @@ export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOp
3
3
  export { D as DefaultSessionReader } from '../session-reader-CqRvaL5v.js';
4
4
  export { A as AuditLevel, S as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as createSessionEventBridge, r as resolveAuditLevel, e as resolveSessionLoggingConfig } from '../session-event-bridge-BAFWdgQ3.js';
5
5
  export { a as DirectorStateCheckpoint, D as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BfeCUbmk.js';
6
- export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-vault-BkYkJWQs.js';
6
+ export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-vault-gxtFZYBt.js';
7
7
  export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-B8rSu908.js';
8
8
  export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, E as EternalAutonomyEngine, c as EternalAutonomyOptions, d as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, e as ParallelEternalEngine, f as ParallelEternalOptions, g as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-C0juOszP.js';
9
9
  export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-UiEkbNmW.js';
@@ -12,8 +12,13 @@ import { EventEmitter } from 'events';
12
12
 
13
13
  var __defProp = Object.defineProperty;
14
14
  var __getOwnPropNames = Object.getOwnPropertyNames;
15
- var __esm = (fn, res) => function __init() {
16
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
+ var __esm = (fn, res, err) => function __init() {
16
+ if (err) throw err[0];
17
+ try {
18
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
19
+ } catch (e) {
20
+ throw err = [e], e;
21
+ }
17
22
  };
18
23
  var __export = (target, all) => {
19
24
  for (var name in all)
@@ -3328,7 +3333,7 @@ var DefaultSessionReader = class {
3328
3333
  this.store = opts.store;
3329
3334
  }
3330
3335
  async query(q = {}) {
3331
- const raw = await this.store.list(q.limit ? Math.max(q.limit * 4, 100) : 1e3);
3336
+ const raw = await this.store.list(q.limit ? Math.max(q.limit, 100) : 1e3);
3332
3337
  const titleNeedle = q.titleContains?.toLowerCase();
3333
3338
  const filtered = raw.filter((s) => {
3334
3339
  if (q.since && s.startedAt < q.since) return false;
@@ -4365,6 +4370,10 @@ var PATTERNS = [
4365
4370
  regex: /(?:^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?:\s|$)/g
4366
4371
  }
4367
4372
  ];
4373
+ var SIMPLE_PATTERNS = PATTERNS.filter((p) => p.type !== "high_entropy_env");
4374
+ var COMBINED_REGEX = new RegExp(SIMPLE_PATTERNS.map((p) => `(${p.regex.source})`).join("|"), "g");
4375
+ var HIGH_ENTROPY_REGEX = PATTERNS.find((p) => p.type === "high_entropy_env").regex;
4376
+ var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
4368
4377
  var SCRUB_CHUNK_BYTES = 64 * 1024;
4369
4378
  function hasCredentialAnchors(text) {
4370
4379
  return text.includes("-----BEGIN") || // Private keys (most unique → cheap reject)
@@ -4406,17 +4415,27 @@ var DefaultSecretScrubber = class {
4406
4415
  }
4407
4416
  scrubOne(text) {
4408
4417
  if (!hasCredentialAnchors(text)) return text;
4409
- let out = text;
4410
- for (const p of PATTERNS) {
4411
- out = out.replace(p.regex, (_match, group1, group2) => {
4412
- if (p.type === "high_entropy_env" && group1 && group2) {
4413
- return `${group1}=[REDACTED:${p.type}]`;
4414
- }
4415
- return `[REDACTED:${p.type}]`;
4416
- });
4417
- }
4418
+ let out = text.replace(
4419
+ COMBINED_REGEX,
4420
+ (match, ...groups) => {
4421
+ const idx = groups.findIndex((g) => g !== void 0);
4422
+ if (idx < 0) return match;
4423
+ const replacement = COMBINED_REPLACEMENTS[idx];
4424
+ return replacement !== void 0 ? replacement : match;
4425
+ }
4426
+ );
4427
+ out = out.replace(HIGH_ENTROPY_REGEX, (_match, group1, _group2) => {
4428
+ return `${group1}=[REDACTED:high_entropy_env]`;
4429
+ });
4418
4430
  return out;
4419
4431
  }
4432
+ /**
4433
+ * Recursively scrub every string value in an object/array graph. Secrets can
4434
+ * appear under any key — a URL query param, an `authorization` header, an
4435
+ * arbitrarily-named nested field — so we don't gate recursion on key names.
4436
+ * The per-string `scrub()` fast-path (anchor pre-scan) keeps this cheap: any
4437
+ * value without a credential anchor returns immediately without regex work.
4438
+ */
4420
4439
  scrubObject(obj) {
4421
4440
  const seen = /* @__PURE__ */ new WeakSet();
4422
4441
  const visit = (v) => {
@@ -5854,12 +5873,15 @@ function getCachedEstimate(key, compute) {
5854
5873
  const existing = ESTIMATE_CACHE.get(key);
5855
5874
  if (existing !== void 0) return existing;
5856
5875
  if (ESTIMATE_CACHE.size >= ESTIMATE_CACHE_MAX_SIZE) {
5857
- const keys = [...ESTIMATE_CACHE.keys()];
5858
- for (let i = 0; i < Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4); i++) {
5859
- ESTIMATE_CACHE.delete(expectDefined(keys[i]));
5876
+ let evicted = 0;
5877
+ const maxEvict = Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4);
5878
+ for (const k of ESTIMATE_CACHE.keys()) {
5879
+ if (evicted >= maxEvict) break;
5880
+ ESTIMATE_CACHE.delete(k);
5881
+ evicted++;
5860
5882
  }
5861
5883
  }
5862
- const estimate = compute();
5884
+ const estimate = compute(key);
5863
5885
  ESTIMATE_CACHE.set(key, estimate);
5864
5886
  return estimate;
5865
5887
  }
@@ -5868,13 +5890,11 @@ function estimateToolInputTokens(input) {
5868
5890
  if (input === null || typeof input !== "object") {
5869
5891
  return RoughTokenEstimate(String(input));
5870
5892
  }
5871
- const key = JSON.stringify(input);
5872
- return getCachedEstimate(key, () => RoughTokenEstimate(key));
5893
+ return getCachedEstimate(JSON.stringify(input), (key) => RoughTokenEstimate(key));
5873
5894
  }
5874
5895
  function estimateToolResultTokens(content) {
5875
5896
  if (typeof content === "string") return RoughTokenEstimate(content);
5876
- const key = JSON.stringify(content);
5877
- return getCachedEstimate(key, () => RoughTokenEstimate(key));
5897
+ return getCachedEstimate(JSON.stringify(content), (key) => RoughTokenEstimate(key));
5878
5898
  }
5879
5899
  function estimateTextTokens(text) {
5880
5900
  return RoughTokenEstimate(text);
@@ -5987,6 +6007,25 @@ function isTextBlock(b) {
5987
6007
  }
5988
6008
 
5989
6009
  // src/execution/compaction-core.ts
6010
+ function emitCompactionMetrics(event, metrics) {
6011
+ console.log(
6012
+ JSON.stringify({
6013
+ level: "debug",
6014
+ event,
6015
+ messageCount: metrics.messageCount,
6016
+ preserveStart: metrics.preserveStart,
6017
+ fastPathIterations: metrics.fastPathIterations,
6018
+ fastPathInnerIterations: metrics.fastPathInnerIterations,
6019
+ // Ratios — anything > 2.0 indicates the inner loop is running more than expected
6020
+ fastPathInnerPerOuter: metrics.fastPathIterations > 0 ? metrics.fastPathInnerIterations / metrics.fastPathIterations : 0,
6021
+ fullPassIterations: metrics.fullPassIterations,
6022
+ fullPassInnerIterations: metrics.fullPassInnerIterations,
6023
+ fullPassInnerPerOuter: metrics.fullPassIterations > 0 ? metrics.fullPassInnerIterations / metrics.fullPassIterations : 0,
6024
+ tokensSaved: metrics.tokensSaved,
6025
+ changed: metrics.changed
6026
+ })
6027
+ );
6028
+ }
5990
6029
  var estimateMessages = estimateMessageTokens;
5991
6030
  function hasTextContent(m) {
5992
6031
  if (typeof m.content === "string") return m.content.trim().length > 0;
@@ -6003,37 +6042,78 @@ function findPreserveStart(messages, preserveK) {
6003
6042
  preserveStart = i;
6004
6043
  }
6005
6044
  }
6045
+ let forwardWalkIterations = 0;
6046
+ let forwardWalkInnerIterations = 0;
6006
6047
  for (let i = preserveStart; i < messages.length; i++) {
6048
+ forwardWalkIterations++;
6007
6049
  const m = messages[i];
6008
6050
  if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
6009
- const hasToolUse3 = m.content.some((b) => b.type === "tool_use");
6051
+ const hasToolUse3 = m.content.some((b) => {
6052
+ forwardWalkInnerIterations++;
6053
+ return b.type === "tool_use";
6054
+ });
6010
6055
  if (hasToolUse3 && i + 1 < messages.length) {
6011
6056
  const next = messages[i + 1];
6012
- if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
6057
+ if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => {
6058
+ forwardWalkInnerIterations++;
6059
+ return b.type === "tool_result";
6060
+ })) {
6013
6061
  preserveStart = i + 1;
6014
6062
  }
6015
6063
  }
6016
6064
  }
6065
+ console.log(
6066
+ JSON.stringify({
6067
+ level: "debug",
6068
+ event: "compaction.find_preserve_start.ended",
6069
+ messageCount: messages.length,
6070
+ preserveK,
6071
+ preserveStart,
6072
+ forwardWalkIterations,
6073
+ forwardWalkInnerIterations,
6074
+ forwardWalkInnerPerOuter: forwardWalkIterations > 0 ? forwardWalkInnerIterations / forwardWalkIterations : 0
6075
+ })
6076
+ );
6017
6077
  return preserveStart;
6018
6078
  }
6019
6079
  function eliseOldToolResults(messages, opts) {
6020
6080
  const preserveStart = findPreserveStart(messages, opts.preserveK);
6021
6081
  let hasOversized = false;
6082
+ let fastPathIterations = 0;
6083
+ let fastPathInnerIterations = 0;
6022
6084
  for (let i = 0; i < preserveStart && !hasOversized; i++) {
6085
+ fastPathIterations++;
6023
6086
  const msg = messages[i];
6024
6087
  if (!msg || !Array.isArray(msg.content)) continue;
6025
6088
  for (const b of msg.content) {
6089
+ fastPathInnerIterations++;
6026
6090
  if (b.type === "tool_result" && estimateToolResultTokens(b.content) >= opts.eliseThreshold) {
6027
6091
  hasOversized = true;
6028
6092
  break;
6029
6093
  }
6030
6094
  }
6031
6095
  }
6096
+ emitCompactionMetrics(
6097
+ hasOversized ? "compaction.elision.fast_path.oversized_found" : "compaction.elision.fast_path.no_oversized",
6098
+ {
6099
+ messageCount: messages.length,
6100
+ preserveStart,
6101
+ fastPathIterations,
6102
+ fastPathInnerIterations,
6103
+ fullPassIterations: 0,
6104
+ fullPassInnerIterations: 0,
6105
+ tokensSaved: 0,
6106
+ changed: false
6107
+ }
6108
+ );
6032
6109
  if (!hasOversized) return { messages, saved: 0, changed: false };
6033
6110
  let saved = 0;
6034
6111
  let changed = false;
6112
+ let fullPassIterations = 0;
6113
+ let fullPassInnerIterations = 0;
6035
6114
  const next = new Array(messages.length);
6036
6115
  for (let i = 0; i < messages.length; i++) {
6116
+ fullPassIterations++;
6037
6117
  const msg = messages[i];
6038
6118
  if (i >= preserveStart || !msg || !Array.isArray(msg.content)) {
6039
6119
  next[i] = msg;
@@ -6059,7 +6139,33 @@ function eliseOldToolResults(messages, opts) {
6059
6139
  next[i] = { ...msg, content: newContent };
6060
6140
  changed = true;
6061
6141
  }
6142
+ fullPassInnerIterations += original.length;
6143
+ if (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1") {
6144
+ const ratio = fullPassInnerIterations / fullPassIterations;
6145
+ if (ratio > 10) {
6146
+ console.error(
6147
+ JSON.stringify({
6148
+ level: "error",
6149
+ event: "compaction.elision.regression",
6150
+ message: `fullPassInnerPerOuter=${ratio.toFixed(2)} exceeds threshold 10 \u2014 possible O(n\xB7m) regression`,
6151
+ messageCount: messages.length,
6152
+ fullPassIterations,
6153
+ fullPassInnerIterations
6154
+ })
6155
+ );
6156
+ }
6157
+ }
6062
6158
  }
6159
+ emitCompactionMetrics("compaction.elision.full_pass.ended", {
6160
+ messageCount: messages.length,
6161
+ preserveStart,
6162
+ fastPathIterations,
6163
+ fastPathInnerIterations,
6164
+ fullPassIterations,
6165
+ fullPassInnerIterations,
6166
+ tokensSaved: saved,
6167
+ changed
6168
+ });
6063
6169
  return { messages: changed ? next : messages, saved, changed };
6064
6170
  }
6065
6171
  function buildLosslessDigest(messages) {