@wrongstack/core 0.256.1 → 0.257.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.
@@ -3,10 +3,10 @@ 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
- 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';
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-CznHTZqP.js';
10
10
  import { P as ProviderRunner, R as RunProviderOptions } from '../provider-runner-hM7EXlLI.js';
11
11
  import { b as Response } from '../context-CGdgA0q6.js';
12
12
  export { a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, n as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, q as DEFAULT_SUBAGENT_BASELINE, r as DelegateHost, s as Director, w as DirectorPromptParts, x as DirectorSessionFactory, y as DirectorSessionFactoryOptions, F as FLEET_ROSTER, z as FLEET_ROSTER_BUDGETS, J as FleetRosterBudget, K as FleetSpawnBudgetError, L as ICoordinator, M as IFleetManager, O as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, V as SubagentPromptParts, W as applyRosterBudget, X as attachAutoExtend, Y as composeDirectorPrompt, Z as composeSubagentPrompt, _ as createDelegateTool, $ as getAgentDefinition, a1 as makeAskTool, a2 as makeAssignTool, a3 as makeAwaitTasksTool, a4 as makeCollabDebugTool, a5 as makeDirectorSessionFactory, a6 as makeFleetEmitTool, a7 as makeFleetHealthTool, a8 as makeFleetSessionTool, a9 as makeFleetStatusTool, aa as makeFleetUsageTool, ab as makeRollUpTool, ac as makeSpawnTool, ad as makeTerminateTool, af as rosterSummaryFromConfigs } from '../null-fleet-bus-B5mfTJXT.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) => {
@@ -5208,6 +5227,8 @@ function compactSkillBody(body) {
5208
5227
  var DefaultSkillLoader = class {
5209
5228
  dirs;
5210
5229
  cache;
5230
+ entriesCache;
5231
+ bodyCache = /* @__PURE__ */ new Map();
5211
5232
  constructor(opts) {
5212
5233
  this.dirs = [
5213
5234
  { dir: opts.paths.inProjectSkills, source: "project" },
@@ -5266,6 +5287,7 @@ var DefaultSkillLoader = class {
5266
5287
  return lines.join("\n");
5267
5288
  }
5268
5289
  async listEntries() {
5290
+ if (this.entriesCache) return this.entriesCache;
5269
5291
  const skills = await this.list();
5270
5292
  const entries = [];
5271
5293
  for (const s of skills) {
@@ -5276,33 +5298,47 @@ var DefaultSkillLoader = class {
5276
5298
  } catch {
5277
5299
  }
5278
5300
  }
5301
+ this.entriesCache = entries;
5279
5302
  return entries;
5280
5303
  }
5281
5304
  invalidateCache() {
5282
5305
  this.cache = void 0;
5306
+ this.entriesCache = void 0;
5307
+ this.bodyCache.clear();
5283
5308
  }
5284
5309
  async readBody(name) {
5310
+ const cached = this.bodyCache.get(name);
5311
+ if (cached !== void 0) return cached;
5285
5312
  const m = await this.find(name);
5286
5313
  if (!m) throw new Error(`Skill "${name}" not found`);
5287
- return fsp.readFile(m.path, "utf8");
5314
+ const body = await fsp.readFile(m.path, "utf8");
5315
+ this.bodyCache.set(name, body);
5316
+ return body;
5288
5317
  }
5289
5318
  async readSaveBody(name) {
5319
+ const key = `save:${name}`;
5320
+ const cached = this.bodyCache.get(key);
5321
+ if (cached !== void 0) return cached;
5290
5322
  const m = await this.find(name);
5291
5323
  if (!m) throw new Error(`Skill "${name}" not found`);
5292
5324
  const savePath = path11.join(path11.dirname(m.path), "SKILL.save.md");
5325
+ let result;
5293
5326
  try {
5294
- return await fsp.readFile(savePath, "utf8");
5327
+ result = await fsp.readFile(savePath, "utf8");
5295
5328
  } catch {
5296
5329
  const full = await fsp.readFile(m.path, "utf8");
5297
5330
  const body = stripFrontmatter(full);
5298
5331
  const compact = compactSkillBody(body);
5299
5332
  if (compact) {
5300
- return `## Overview
5333
+ result = `## Overview
5301
5334
 
5302
5335
  ${compact}`;
5336
+ } else {
5337
+ result = body.trim().slice(0, 300);
5303
5338
  }
5304
- return body.trim().slice(0, 300);
5305
5339
  }
5340
+ this.bodyCache.set(key, result);
5341
+ return result;
5306
5342
  }
5307
5343
  };
5308
5344
  function parseFrontmatter(raw) {
@@ -5854,12 +5890,15 @@ function getCachedEstimate(key, compute) {
5854
5890
  const existing = ESTIMATE_CACHE.get(key);
5855
5891
  if (existing !== void 0) return existing;
5856
5892
  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]));
5893
+ let evicted = 0;
5894
+ const maxEvict = Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4);
5895
+ for (const k of ESTIMATE_CACHE.keys()) {
5896
+ if (evicted >= maxEvict) break;
5897
+ ESTIMATE_CACHE.delete(k);
5898
+ evicted++;
5860
5899
  }
5861
5900
  }
5862
- const estimate = compute();
5901
+ const estimate = compute(key);
5863
5902
  ESTIMATE_CACHE.set(key, estimate);
5864
5903
  return estimate;
5865
5904
  }
@@ -5868,13 +5907,11 @@ function estimateToolInputTokens(input) {
5868
5907
  if (input === null || typeof input !== "object") {
5869
5908
  return RoughTokenEstimate(String(input));
5870
5909
  }
5871
- const key = JSON.stringify(input);
5872
- return getCachedEstimate(key, () => RoughTokenEstimate(key));
5910
+ return getCachedEstimate(JSON.stringify(input), (key) => RoughTokenEstimate(key));
5873
5911
  }
5874
5912
  function estimateToolResultTokens(content) {
5875
5913
  if (typeof content === "string") return RoughTokenEstimate(content);
5876
- const key = JSON.stringify(content);
5877
- return getCachedEstimate(key, () => RoughTokenEstimate(key));
5914
+ return getCachedEstimate(JSON.stringify(content), (key) => RoughTokenEstimate(key));
5878
5915
  }
5879
5916
  function estimateTextTokens(text) {
5880
5917
  return RoughTokenEstimate(text);
@@ -5987,6 +6024,25 @@ function isTextBlock(b) {
5987
6024
  }
5988
6025
 
5989
6026
  // src/execution/compaction-core.ts
6027
+ function emitCompactionMetrics(event, metrics) {
6028
+ console.log(
6029
+ JSON.stringify({
6030
+ level: "debug",
6031
+ event,
6032
+ messageCount: metrics.messageCount,
6033
+ preserveStart: metrics.preserveStart,
6034
+ fastPathIterations: metrics.fastPathIterations,
6035
+ fastPathInnerIterations: metrics.fastPathInnerIterations,
6036
+ // Ratios — anything > 2.0 indicates the inner loop is running more than expected
6037
+ fastPathInnerPerOuter: metrics.fastPathIterations > 0 ? metrics.fastPathInnerIterations / metrics.fastPathIterations : 0,
6038
+ fullPassIterations: metrics.fullPassIterations,
6039
+ fullPassInnerIterations: metrics.fullPassInnerIterations,
6040
+ fullPassInnerPerOuter: metrics.fullPassIterations > 0 ? metrics.fullPassInnerIterations / metrics.fullPassIterations : 0,
6041
+ tokensSaved: metrics.tokensSaved,
6042
+ changed: metrics.changed
6043
+ })
6044
+ );
6045
+ }
5990
6046
  var estimateMessages = estimateMessageTokens;
5991
6047
  function hasTextContent(m) {
5992
6048
  if (typeof m.content === "string") return m.content.trim().length > 0;
@@ -6003,37 +6059,78 @@ function findPreserveStart(messages, preserveK) {
6003
6059
  preserveStart = i;
6004
6060
  }
6005
6061
  }
6062
+ let forwardWalkIterations = 0;
6063
+ let forwardWalkInnerIterations = 0;
6006
6064
  for (let i = preserveStart; i < messages.length; i++) {
6065
+ forwardWalkIterations++;
6007
6066
  const m = messages[i];
6008
6067
  if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
6009
- const hasToolUse3 = m.content.some((b) => b.type === "tool_use");
6068
+ const hasToolUse3 = m.content.some((b) => {
6069
+ forwardWalkInnerIterations++;
6070
+ return b.type === "tool_use";
6071
+ });
6010
6072
  if (hasToolUse3 && i + 1 < messages.length) {
6011
6073
  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")) {
6074
+ if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => {
6075
+ forwardWalkInnerIterations++;
6076
+ return b.type === "tool_result";
6077
+ })) {
6013
6078
  preserveStart = i + 1;
6014
6079
  }
6015
6080
  }
6016
6081
  }
6082
+ console.log(
6083
+ JSON.stringify({
6084
+ level: "debug",
6085
+ event: "compaction.find_preserve_start.ended",
6086
+ messageCount: messages.length,
6087
+ preserveK,
6088
+ preserveStart,
6089
+ forwardWalkIterations,
6090
+ forwardWalkInnerIterations,
6091
+ forwardWalkInnerPerOuter: forwardWalkIterations > 0 ? forwardWalkInnerIterations / forwardWalkIterations : 0
6092
+ })
6093
+ );
6017
6094
  return preserveStart;
6018
6095
  }
6019
6096
  function eliseOldToolResults(messages, opts) {
6020
6097
  const preserveStart = findPreserveStart(messages, opts.preserveK);
6021
6098
  let hasOversized = false;
6099
+ let fastPathIterations = 0;
6100
+ let fastPathInnerIterations = 0;
6022
6101
  for (let i = 0; i < preserveStart && !hasOversized; i++) {
6102
+ fastPathIterations++;
6023
6103
  const msg = messages[i];
6024
6104
  if (!msg || !Array.isArray(msg.content)) continue;
6025
6105
  for (const b of msg.content) {
6106
+ fastPathInnerIterations++;
6026
6107
  if (b.type === "tool_result" && estimateToolResultTokens(b.content) >= opts.eliseThreshold) {
6027
6108
  hasOversized = true;
6028
6109
  break;
6029
6110
  }
6030
6111
  }
6031
6112
  }
6113
+ emitCompactionMetrics(
6114
+ hasOversized ? "compaction.elision.fast_path.oversized_found" : "compaction.elision.fast_path.no_oversized",
6115
+ {
6116
+ messageCount: messages.length,
6117
+ preserveStart,
6118
+ fastPathIterations,
6119
+ fastPathInnerIterations,
6120
+ fullPassIterations: 0,
6121
+ fullPassInnerIterations: 0,
6122
+ tokensSaved: 0,
6123
+ changed: false
6124
+ }
6125
+ );
6032
6126
  if (!hasOversized) return { messages, saved: 0, changed: false };
6033
6127
  let saved = 0;
6034
6128
  let changed = false;
6129
+ let fullPassIterations = 0;
6130
+ let fullPassInnerIterations = 0;
6035
6131
  const next = new Array(messages.length);
6036
6132
  for (let i = 0; i < messages.length; i++) {
6133
+ fullPassIterations++;
6037
6134
  const msg = messages[i];
6038
6135
  if (i >= preserveStart || !msg || !Array.isArray(msg.content)) {
6039
6136
  next[i] = msg;
@@ -6059,7 +6156,33 @@ function eliseOldToolResults(messages, opts) {
6059
6156
  next[i] = { ...msg, content: newContent };
6060
6157
  changed = true;
6061
6158
  }
6159
+ fullPassInnerIterations += original.length;
6160
+ if (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1") {
6161
+ const ratio = fullPassInnerIterations / fullPassIterations;
6162
+ if (ratio > 10) {
6163
+ console.error(
6164
+ JSON.stringify({
6165
+ level: "error",
6166
+ event: "compaction.elision.regression",
6167
+ message: `fullPassInnerPerOuter=${ratio.toFixed(2)} exceeds threshold 10 \u2014 possible O(n\xB7m) regression`,
6168
+ messageCount: messages.length,
6169
+ fullPassIterations,
6170
+ fullPassInnerIterations
6171
+ })
6172
+ );
6173
+ }
6174
+ }
6062
6175
  }
6176
+ emitCompactionMetrics("compaction.elision.full_pass.ended", {
6177
+ messageCount: messages.length,
6178
+ preserveStart,
6179
+ fastPathIterations,
6180
+ fastPathInnerIterations,
6181
+ fullPassIterations,
6182
+ fullPassInnerIterations,
6183
+ tokensSaved: saved,
6184
+ changed
6185
+ });
6063
6186
  return { messages: changed ? next : messages, saved, changed };
6064
6187
  }
6065
6188
  function buildLosslessDigest(messages) {
@@ -11900,17 +12023,17 @@ function normalize(text) {
11900
12023
  return ` ${text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim()} `;
11901
12024
  }
11902
12025
  function scoreAgents(task, catalog = AGENT_CATALOG) {
11903
- const hay = normalize(task);
12026
+ const haySet = new Set(normalize(task).split(/\s+/).filter(Boolean));
11904
12027
  const out = [];
11905
12028
  for (const def of Object.values(catalog)) {
11906
12029
  if (!def?.config?.role) continue;
11907
12030
  let score = 0;
11908
12031
  const matched = [];
11909
12032
  for (const kw of def.capability.keywords) {
11910
- const needle = normalize(kw);
11911
- if (hay.includes(needle.trimEnd() + " ") || hay.includes(" " + needle.trimStart())) {
11912
- const words = kw.trim().split(/\s+/).length;
11913
- score += words;
12033
+ const needleWords = normalize(kw).split(/\s+/).filter(Boolean);
12034
+ const allPresent = needleWords.every((w) => haySet.has(w));
12035
+ if (allPresent) {
12036
+ score += needleWords.length;
11914
12037
  matched.push(kw);
11915
12038
  }
11916
12039
  }
@@ -14601,6 +14724,7 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
14601
14724
  }
14602
14725
  for (const dispose of this.disposers) dispose();
14603
14726
  this.disposers.length = 0;
14727
+ this.snapshot.files.length = 0;
14604
14728
  }
14605
14729
  };
14606
14730