@wrongstack/core 0.141.0 → 0.148.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.
@@ -10,8 +10,8 @@ export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOp
10
10
  export { D as DefaultLogger, a as DefaultLoggerOptions } from '../logger-B9J5puGM.js';
11
11
  export { D as DefaultPathResolver, a as DefaultTokenCounter } from '../path-resolver-DRjQBkoO.js';
12
12
  export { p as MEMORY_TYPE_LABELS, q as MemoryClearedPayload, r as MemoryConsolidatedPayload, k as MemoryEntry, s as MemoryForgottenPayload, t as MemoryPriority, m as MemoryRelevanceContext, u as MemoryRememberedPayload, M as MemoryScope, l as MemoryStore, v as MemoryType, S as ScoredEntry } from '../brain-Cp_3GIS2.js';
13
- import { I as IterationStage, f as ParallelIterationStage } from '../parallel-eternal-engine-Dj2SYzha.js';
14
- export { C as CompactorOptions, g as DEFAULT_RECOVERY_STRATEGIES, D as DefaultErrorHandler, a as DefaultRetryPolicy, H as HybridCompactor, R as RecoveryStrategy, T as ToolExecutor, h as buildRecoveryStrategies } from '../parallel-eternal-engine-Dj2SYzha.js';
13
+ import { I as IterationStage, f as ParallelIterationStage } from '../parallel-eternal-engine-C75QuhAI.js';
14
+ export { C as CompactorOptions, g as DEFAULT_RECOVERY_STRATEGIES, D as DefaultErrorHandler, a as DefaultRetryPolicy, H as HybridCompactor, R as RecoveryStrategy, T as ToolExecutor, h as buildRecoveryStrategies } from '../parallel-eternal-engine-C75QuhAI.js';
15
15
  export { b as SkillEntry, S as SkillLoader, a as SkillManifest } from '../skill-Bj6Ezqb8.js';
16
16
  export { B as BuildContext, b as ModelCapabilities, a as Renderer, S as SystemPromptBuilder } from '../pipeline-BG7UgbDc.js';
17
17
  export { I as InputReader, P as PromptOption } from '../input-reader-E-ffP2ee.js';
@@ -1164,8 +1164,8 @@ function findPreserveStart(messages, preserveK) {
1164
1164
  for (let i = preserveStart; i < messages.length; i++) {
1165
1165
  const m = messages[i];
1166
1166
  if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
1167
- const hasToolUse2 = m.content.some((b) => b.type === "tool_use");
1168
- if (hasToolUse2 && i + 1 < messages.length) {
1167
+ const hasToolUse3 = m.content.some((b) => b.type === "tool_use");
1168
+ if (hasToolUse3 && i + 1 < messages.length) {
1169
1169
  const next = messages[i + 1];
1170
1170
  if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
1171
1171
  preserveStart = i + 1;
@@ -1229,14 +1229,137 @@ function buildLosslessDigest(messages) {
1229
1229
  }
1230
1230
  return lines.join("\n");
1231
1231
  }
1232
+ function extractText(m) {
1233
+ if (typeof m.content === "string") return m.content;
1234
+ return m.content.filter(isTextBlock).map((b) => b.text).join(" ");
1235
+ }
1236
+ function hasToolUse2(m) {
1237
+ if (typeof m.content === "string") return false;
1238
+ return m.content.some((b) => b.type === "tool_use");
1239
+ }
1240
+ function hasLargeToolResult(m, threshold = 3e3) {
1241
+ if (typeof m.content === "string") return false;
1242
+ return m.content.some(
1243
+ (b) => b.type === "tool_result" && b.content && (typeof b.content === "string" ? b.content.length : JSON.stringify(b.content).length) > threshold
1244
+ );
1245
+ }
1246
+ function scoreMessage(m, context) {
1247
+ const text = extractText(m).toLowerCase();
1248
+ if (text.trim().length === 0 && (hasToolUse2(m) || typeof m.content !== "string")) {
1249
+ const hasResult = typeof m.content !== "string" && m.content.some((b) => b.type === "tool_result");
1250
+ if (hasToolUse2(m) || hasResult) return 0;
1251
+ }
1252
+ if (context?.failureCounts && m.role === "user" && hasToolUse2(m) === false) {
1253
+ const isFailure = /error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort/i.test(text);
1254
+ if (isFailure) {
1255
+ const errKey = /(error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort)/i.exec(text)?.[0]?.toLowerCase() ?? "error";
1256
+ const count = (context.failureCounts.get(errKey) ?? 0) + 1;
1257
+ context.failureCounts.set(errKey, count);
1258
+ if (count >= 5) return 0;
1259
+ if (count >= 3) return 1;
1260
+ }
1261
+ }
1262
+ if (m.role === "user") {
1263
+ if (/\b(wrong|no\b|stop\b|don'?t\b|actually|fix that|undo|revert|forget|ignore|skip)\b/i.test(
1264
+ text
1265
+ )) {
1266
+ return 5;
1267
+ }
1268
+ }
1269
+ if (/\b(error|exception|fatal|critical|crash|panic|abort|segfault|core dump|undefined is not|null pointer|typeerror|referenceerror|syntaxerror)\b/i.test(
1270
+ text
1271
+ )) {
1272
+ return 5;
1273
+ }
1274
+ if (/\b(security|vulnerability|injection|xss|csrf|secret|apikey|api.key|hardcoded|leak|exploit|cve)\b/i.test(
1275
+ text
1276
+ )) {
1277
+ return 5;
1278
+ }
1279
+ if (m.role === "assistant" && /\b(architecture|design|approach|strategy|pattern|refactor|migrate|restructure|decision|trade.?off)\b/i.test(
1280
+ text
1281
+ )) {
1282
+ return 5;
1283
+ }
1284
+ if (hasLargeToolResult(m)) return 1;
1285
+ if (m.role === "user" && !hasToolUse2(m) && /\b(files_with_matches|count|found \d+ match|directory tree|\.\.\. and \d+ more)\b/i.test(text)) {
1286
+ return 1;
1287
+ }
1288
+ return 3;
1289
+ }
1290
+ function buildSmartDigest(messages) {
1291
+ const lines = [];
1292
+ const failureCounts = /* @__PURE__ */ new Map();
1293
+ let noiseCount = 0;
1294
+ for (const m of messages) {
1295
+ const score = scoreMessage(m, { failureCounts });
1296
+ const text = extractText(m);
1297
+ const toolCount = countToolBlocks(m);
1298
+ if (score === 0) {
1299
+ noiseCount++;
1300
+ continue;
1301
+ }
1302
+ const marker = toolCount > 0 ? ` [${toolCount} tool call(s)]` : "";
1303
+ let display;
1304
+ switch (score) {
1305
+ case 5:
1306
+ display = text.trim();
1307
+ break;
1308
+ case 3:
1309
+ display = firstSentence(text);
1310
+ break;
1311
+ case 1:
1312
+ display = oneLineSummary(m, text);
1313
+ break;
1314
+ default:
1315
+ display = firstSentence(text);
1316
+ }
1317
+ if (display.length === 0 && toolCount === 0) continue;
1318
+ lines.push(`[${m.role}]: ${display}${marker}`);
1319
+ }
1320
+ if (noiseCount > 0) {
1321
+ lines.push(`[system]: ${noiseCount} low-importance turn(s) collapsed (repeated failures / pure tool I/O)`);
1322
+ }
1323
+ return lines.join("\n");
1324
+ }
1325
+ function countToolBlocks(m) {
1326
+ if (typeof m.content === "string") return 0;
1327
+ return m.content.filter(
1328
+ (b) => b.type === "tool_use" || b.type === "tool_result"
1329
+ ).length;
1330
+ }
1331
+ function firstSentence(text) {
1332
+ const trimmed = text.trim();
1333
+ if (trimmed.length === 0) return "";
1334
+ const dot = trimmed.indexOf(". ");
1335
+ if (dot === -1) return trimmed.length > 150 ? `${trimmed.slice(0, 147)}\u2026` : trimmed;
1336
+ const sentence = trimmed.slice(0, dot + 1);
1337
+ return sentence.length > 150 ? `${sentence.slice(0, 147)}\u2026` : sentence;
1338
+ }
1339
+ function oneLineSummary(m, text) {
1340
+ const trimmed = text.trim();
1341
+ if (trimmed.length === 0) {
1342
+ if (typeof m.content !== "string") {
1343
+ const results = m.content.filter((b) => b.type === "tool_result");
1344
+ if (results.length > 0) {
1345
+ return `[${results.length} tool result(s) \u2014 see session log]`;
1346
+ }
1347
+ }
1348
+ return "[no text content]";
1349
+ }
1350
+ const firstLine = trimmed.split("\n")[0] ?? "";
1351
+ return firstLine.length > 100 ? `${firstLine.slice(0, 97)}\u2026` : firstLine;
1352
+ }
1232
1353
 
1233
1354
  // src/execution/compactor.ts
1234
1355
  var HybridCompactor = class {
1235
1356
  preserveK;
1236
1357
  eliseThreshold;
1358
+ smart;
1237
1359
  constructor(opts = {}) {
1238
1360
  this.preserveK = opts.preserveK ?? 5;
1239
1361
  this.eliseThreshold = opts.eliseThreshold ?? 2e3;
1362
+ this.smart = opts.smart ?? false;
1240
1363
  }
1241
1364
  async compact(ctx, opts = {}) {
1242
1365
  const beforeTokens = estimateMessages(ctx.messages);
@@ -1308,7 +1431,7 @@ var HybridCompactor = class {
1308
1431
  if (boundary <= 0) return { saved: 0 };
1309
1432
  const removed = messages.slice(0, boundary);
1310
1433
  const removedTokens = estimateMessages(removed);
1311
- const digest = buildLosslessDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)`;
1434
+ const digest = this.smart ? buildSmartDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)` : buildLosslessDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)`;
1312
1435
  const summaryMsg = {
1313
1436
  role: "system",
1314
1437
  content: `[prior_turns_digest: ${digest}]`
@@ -3118,7 +3241,7 @@ ${excerpt}`;
3118
3241
  subjectFor(toolName, input, subjectKey) {
3119
3242
  if (!input || typeof input !== "object") return void 0;
3120
3243
  const obj = input;
3121
- const globChars = /[*?\[\]]/g;
3244
+ const globChars = /[*?[\]]/g;
3122
3245
  const escapeGlob = (s) => s.replace(globChars, (c) => `\\${c}`);
3123
3246
  const normalizePath = (s) => escapeGlob(s.replace(/\\/g, "/"));
3124
3247
  if (subjectKey) {