@wrongstack/core 0.8.0 → 0.8.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.
@@ -1,22 +1,22 @@
1
- export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-Cx2ndr0L.js';
1
+ export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-QwfWnQZ8.js';
2
2
  import { m as Provider, d as Context } from '../context-z2x5gv_V.js';
3
3
  import { a as Compactor, C as CompactReport } from '../compactor-Mw7-rNyb.js';
4
4
  import { M as MessageSelector } from '../selector-DkvgYVS4.js';
5
5
  import { E as EventBus } from '../events-DyhxkstG.js';
6
6
  import { b as MiddlewareHandler } from '../system-prompt-CWA6ml-d.js';
7
7
  import { e as ContextWindowAggressiveOn, i as ContextWindowPolicy } from '../config-Bi4Q0fnz.js';
8
- import { c as Agent, R as RunResult, w as SystemPromptContributor } from '../index-BciJeH8g.js';
8
+ import { c as Agent, R as RunResult, w as SystemPromptContributor } from '../index-oYZeWsuJ.js';
9
9
  import { D as DoneCondition } from '../multi-agent-CRMznZmf.js';
10
10
  import { J as JournalEntry } from '../goal-store-C7jcumEh.js';
11
- import { A as AgentFactory } from '../agent-subagent-runner-Bzeueq2J.js';
12
- import { f as DispatchClassifier, d as DefaultMultiAgentCoordinator } from '../multi-agent-coordinator-tlSWD4cE.js';
11
+ import { A as AgentFactory } from '../agent-subagent-runner-Cav3yEJM.js';
12
+ import { f as DispatchClassifier, d as DefaultMultiAgentCoordinator } from '../multi-agent-coordinator-IQKrMfXz.js';
13
13
  import { a as SkillLoader, b as SkillManifest, S as SkillEntry } from '../skill-CxuWrsKK.js';
14
14
  import { a as WstackPaths } from '../wstack-paths-gCrJ631C.js';
15
15
  import '../retry-policy-OwtKNxo8.js';
16
16
  import '../models-registry-BcYJDKLm.js';
17
17
  import '../logger-DDd5C--Z.js';
18
18
  import '../observability-BhnVLBLS.js';
19
- import '../secret-scrubber-nI8qjaqW.js';
19
+ import '../secret-scrubber-CyE1-EMG.js';
20
20
  import 'node:events';
21
21
 
22
22
  interface SkillLoaderOptions {
@@ -210,6 +210,16 @@ declare class AutoCompactionMiddleware {
210
210
  * short conversations, causing premature compaction triggers.
211
211
  */
212
212
  private static readonly OVERHEAD_FACTOR;
213
+ /**
214
+ * Once a compaction attempt reduces nothing (preserveK protects everything,
215
+ * no oversized tool_results remain to elide), retrying on every iteration
216
+ * just spams `compaction.fired` events without making progress. We remember
217
+ * the no-op and skip until either the pressure level escalates or context
218
+ * has grown by at least this many tokens since the failed attempt.
219
+ */
220
+ private static readonly NOOP_RETRY_DELTA_TOKENS;
221
+ /** Tracks the most recent no-op attempt so we can avoid re-firing per turn. */
222
+ private lastNoopAttempt;
213
223
  /**
214
224
  * @param compactor Compactor to use for compaction.
215
225
  * @param maxContext Provider's max context window in tokens.
@@ -230,6 +240,13 @@ declare class AutoCompactionMiddleware {
230
240
  * denominator when the active model changes. */
231
241
  setMaxContext(maxContext: number): void;
232
242
  handler(): MiddlewareHandler<Context>;
243
+ /**
244
+ * Returns true when the previous compaction at the same or higher pressure
245
+ * level reduced nothing and context has not grown materially since. Prevents
246
+ * a stuck preserveK window from spamming compaction events every iteration.
247
+ */
248
+ private shouldSkipNoopRetry;
249
+ private recordAttempt;
233
250
  private compact;
234
251
  }
235
252
 
@@ -1004,6 +1004,7 @@ var FsError = class extends WrongStackError {
1004
1004
  };
1005
1005
 
1006
1006
  // src/execution/auto-compaction-middleware.ts
1007
+ var LEVEL_RANK = { warn: 0, soft: 1, hard: 2 };
1007
1008
  var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
1008
1009
  name = "AutoCompaction";
1009
1010
  compactor;
@@ -1024,6 +1025,16 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
1024
1025
  * short conversations, causing premature compaction triggers.
1025
1026
  */
1026
1027
  static OVERHEAD_FACTOR = 1.3;
1028
+ /**
1029
+ * Once a compaction attempt reduces nothing (preserveK protects everything,
1030
+ * no oversized tool_results remain to elide), retrying on every iteration
1031
+ * just spams `compaction.fired` events without making progress. We remember
1032
+ * the no-op and skip until either the pressure level escalates or context
1033
+ * has grown by at least this many tokens since the failed attempt.
1034
+ */
1035
+ static NOOP_RETRY_DELTA_TOKENS = 2e3;
1036
+ /** Tracks the most recent no-op attempt so we can avoid re-firing per turn. */
1037
+ lastNoopAttempt = null;
1027
1038
  /**
1028
1039
  * @param compactor Compactor to use for compaction.
1029
1040
  * @param maxContext Provider's max context window in tokens.
@@ -1065,19 +1076,44 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
1065
1076
  hard: this.hardThreshold
1066
1077
  };
1067
1078
  const aggressiveOn = policy?.aggressiveOn ?? this.aggressiveOn;
1068
- if (load >= thresholds.hard) {
1069
- await this.compact(ctx, true, { level: "hard", tokens, load });
1070
- } else if (load >= thresholds.soft) {
1071
- await this.compact(ctx, aggressiveOn !== "hard", { level: "soft", tokens, load });
1072
- } else if (load >= thresholds.warn) {
1073
- await this.compact(ctx, aggressiveOn === "warn", { level: "warn", tokens, load });
1079
+ const level = load >= thresholds.hard ? "hard" : load >= thresholds.soft ? "soft" : load >= thresholds.warn ? "warn" : null;
1080
+ if (!level) {
1081
+ this.lastNoopAttempt = null;
1082
+ return next(ctx);
1074
1083
  }
1084
+ if (this.shouldSkipNoopRetry(level, tokens)) {
1085
+ return next(ctx);
1086
+ }
1087
+ const aggressive = level === "hard" ? true : level === "soft" ? aggressiveOn !== "hard" : aggressiveOn === "warn";
1088
+ await this.compact(ctx, aggressive, { level, tokens, load });
1075
1089
  return next(ctx);
1076
1090
  };
1077
1091
  }
1092
+ /**
1093
+ * Returns true when the previous compaction at the same or higher pressure
1094
+ * level reduced nothing and context has not grown materially since. Prevents
1095
+ * a stuck preserveK window from spamming compaction events every iteration.
1096
+ */
1097
+ shouldSkipNoopRetry(level, tokens) {
1098
+ const stuck = this.lastNoopAttempt;
1099
+ if (!stuck) return false;
1100
+ if (LEVEL_RANK[level] > LEVEL_RANK[stuck.level]) return false;
1101
+ const delta = tokens - stuck.tokens;
1102
+ return delta < _AutoCompactionMiddleware.NOOP_RETRY_DELTA_TOKENS;
1103
+ }
1104
+ recordAttempt(level, tokens, report) {
1105
+ const reduced = report.before > report.after;
1106
+ const repaired = !!report.repaired;
1107
+ if (reduced || repaired) {
1108
+ this.lastNoopAttempt = null;
1109
+ } else {
1110
+ this.lastNoopAttempt = { level, tokens };
1111
+ }
1112
+ }
1078
1113
  async compact(ctx, aggressive, pressure) {
1079
1114
  try {
1080
1115
  const report = await this.compactor.compact(ctx, { aggressive });
1116
+ this.recordAttempt(pressure.level, pressure.tokens, report);
1081
1117
  this.events?.emit("compaction.fired", {
1082
1118
  level: pressure.level,
1083
1119
  tokens: pressure.tokens,