@wrongstack/core 0.8.2 → 0.8.5

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,5 +1,5 @@
1
1
  export { D as DefaultLogger, a as DefaultLoggerOptions } from '../logger-bOzkF5LL.js';
2
- export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-BnlpEkX8.js';
2
+ export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-D8zQgZzc.js';
3
3
  export { D as DefaultSessionReader } from '../session-reader-DsadjyF9.js';
4
4
  export { D as DirectorStateCheckpoint, a as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BmYi3DGA.js';
5
5
  export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-scrubber-C0n1EqrC.js';
@@ -22,7 +22,7 @@ export { D as DEFAULT_CONTEXT_CONFIG, a as DEFAULT_TOOLS_CONFIG } from '../defau
22
22
  import '../logger-DDd5C--Z.js';
23
23
  import '../events-DyhxkstG.js';
24
24
  import '../memory-CEXuo7sz.js';
25
- import '../wstack-paths-gCrJ631C.js';
25
+ import '../wstack-paths-Bxik3CsK.js';
26
26
  import '../config-Bi4Q0fnz.js';
27
27
  import '../models-registry-BcYJDKLm.js';
28
28
  import '../secret-vault-DoISxaKO.js';
@@ -1662,9 +1662,7 @@ var RecoveryLock = class {
1662
1662
  hostname: this.hostname,
1663
1663
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
1664
1664
  };
1665
- const tmp = `${this.file}.tmp`;
1666
- await fsp.writeFile(tmp, JSON.stringify(lock), { mode: 384 });
1667
- await fsp.rename(tmp, this.file);
1665
+ await atomicWrite(this.file, JSON.stringify(lock), { mode: 384 });
1668
1666
  }
1669
1667
  /**
1670
1668
  * Release the lock. Idempotent — silently succeeds if the file is
@@ -4842,12 +4840,18 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
4842
4840
  failureMode;
4843
4841
  policyProvider;
4844
4842
  /**
4845
- * Overhead factor applied to the rough message-token estimate to produce a
4846
- * figure comparable to the real API request size (system prompt + tool defs).
4847
- * Without this factor, raw message tokens undercount real load by 15-50% in
4848
- * short conversations, causing premature compaction triggers.
4843
+ * Calibration factor applied to the estimator output. The estimator is now
4844
+ * expected to already include messages + system prompt + tool definitions
4845
+ * (see `estimateRequestTokens.total`), so no overhead boost is needed. Kept
4846
+ * as a constant so a future calibration against real provider tokenization
4847
+ * (BPE vs the chars/3.5 rough estimator) can dial this without touching the
4848
+ * threshold-check math.
4849
+ *
4850
+ * Historical note: was 1.3 when the estimator only counted messages — that
4851
+ * double-counted system+tools once the estimator was upgraded, firing
4852
+ * compaction ~30% earlier than intended (e.g. real 56% load showed as 73%).
4849
4853
  */
4850
- static OVERHEAD_FACTOR = 1.3;
4854
+ static OVERHEAD_FACTOR = 1;
4851
4855
  /**
4852
4856
  * Once a compaction attempt reduces nothing (preserveK protects everything,
4853
4857
  * no oversized tool_results remain to elide), retrying on every iteration
@@ -5057,7 +5061,7 @@ var ToolExecutor = class {
5057
5061
  return { result, tool, durationMs: Date.now() - start };
5058
5062
  }
5059
5063
  if (hasMalformedArguments(use.input)) {
5060
- const result = this.malformedInputResult(use);
5064
+ const result = this.malformedInputResult(use, extractMalformedRaw(use.input));
5061
5065
  budget = this.decrementBudget(result, budget);
5062
5066
  return { result, tool, durationMs: Date.now() - start };
5063
5067
  }
@@ -5264,11 +5268,18 @@ var ToolExecutor = class {
5264
5268
  is_error: true
5265
5269
  };
5266
5270
  }
5267
- malformedInputResult(use) {
5271
+ malformedInputResult(use, raw) {
5272
+ let content = `Tool "${use.name}" received arguments that were not a valid JSON object, so they could not be parsed. Re-issue the call with the arguments encoded as a single well-formed JSON object matching the tool's input schema.`;
5273
+ if (raw) {
5274
+ const max = 800;
5275
+ const excerpt = raw.length > max ? `${raw.slice(0, max)}\u2026 (truncated, ${raw.length} chars total)` : raw;
5276
+ content += ` Common cause: a string field (e.g. code in old_string/new_string) contains literal newlines, quotes, or backslashes that must be JSON-escaped, or the payload was cut off mid-stream. The raw arguments received were:
5277
+ ${excerpt}`;
5278
+ }
5268
5279
  return {
5269
5280
  type: "tool_result",
5270
5281
  tool_use_id: use.id,
5271
- content: `Tool "${use.name}" received arguments that were not a valid JSON object, so they could not be parsed. Re-issue the call with the arguments encoded as a single well-formed JSON object matching the tool's input schema.`,
5282
+ content,
5272
5283
  is_error: true
5273
5284
  };
5274
5285
  }
@@ -5324,6 +5335,18 @@ function hasMalformedArguments(input) {
5324
5335
  const keys = Object.keys(obj);
5325
5336
  return keys.length === 1 && MALFORMED_ARG_MARKERS.includes(keys[0]);
5326
5337
  }
5338
+ function extractMalformedRaw(input) {
5339
+ if (!hasMalformedArguments(input)) return void 0;
5340
+ const obj = input;
5341
+ const value = obj[Object.keys(obj)[0]];
5342
+ if (value === void 0 || value === null) return void 0;
5343
+ if (typeof value === "string") return value;
5344
+ try {
5345
+ return JSON.stringify(value);
5346
+ } catch {
5347
+ return String(value);
5348
+ }
5349
+ }
5327
5350
 
5328
5351
  // src/execution/autonomous-runner.ts
5329
5352
  var DoneConditionChecker = class {
@@ -10670,7 +10693,7 @@ function makeSpawnTool(director, roster) {
10670
10693
  catalog: roster
10671
10694
  });
10672
10695
  const dispatchRole = dispatchResult.role;
10673
- if (roster && roster[dispatchRole]) {
10696
+ if (roster?.[dispatchRole]) {
10674
10697
  cfg = instantiateRosterConfig(dispatchRole, roster[dispatchRole]);
10675
10698
  } else {
10676
10699
  const def = dispatchResult.definition;
@@ -11160,6 +11183,13 @@ var Director = class {
11160
11183
  extendCounts.delete(guardKey);
11161
11184
  return;
11162
11185
  }
11186
+ if (payload.kind === "cost" && this.maxFleetCostUsd < Number.POSITIVE_INFINITY) {
11187
+ const totalCost = this.usage.snapshot().total?.cost ?? 0;
11188
+ if (totalCost >= this.maxFleetCostUsd) {
11189
+ payload.deny();
11190
+ return;
11191
+ }
11192
+ }
11163
11193
  extendCounts.set(guardKey, prior + 1);
11164
11194
  setImmediate(() => {
11165
11195
  const extra = {};
@@ -13130,6 +13160,13 @@ var TaskTracker = class {
13130
13160
  opts;
13131
13161
  graph = null;
13132
13162
  transitions = [];
13163
+ /**
13164
+ * Attach an existing graph (used by PhaseOrchestrator to associate a tracker
13165
+ * with a phase's pre-built task graph without re-creating it).
13166
+ */
13167
+ setGraph(graph) {
13168
+ this.graph = graph;
13169
+ }
13133
13170
  async createGraph(specId, title) {
13134
13171
  this.graph = {
13135
13172
  id: crypto.randomUUID(),
@@ -13202,10 +13239,6 @@ var TaskTracker = class {
13202
13239
  this.graph.updatedAt = now;
13203
13240
  this.persist();
13204
13241
  }
13205
- /**
13206
- * Update node fields (title, description, priority, estimateHours, tags).
13207
- * Does NOT change status. Use updateNodeStatus for status changes.
13208
- */
13209
13242
  updateNode(id, patch) {
13210
13243
  if (!this.graph) throw new Error("No graph loaded");
13211
13244
  const node = this.graph.nodes.get(id);
@@ -13283,8 +13316,7 @@ var TaskTracker = class {
13283
13316
  }
13284
13317
  return computeTaskProgress(this.graph);
13285
13318
  }
13286
- getTransitions(taskId) {
13287
- if (!taskId) return [...this.transitions];
13319
+ getTransitions(_taskId) {
13288
13320
  return [...this.transitions];
13289
13321
  }
13290
13322
  unblockDependents(completedId) {
@@ -13324,18 +13356,12 @@ var TaskTracker = class {
13324
13356
  * Fire-and-forget persistence with attached error handler.
13325
13357
  * Synchronous mutators (addNode/addEdge/updateNodeStatus) use this to
13326
13358
  * avoid forcing an async cascade through every caller; if the store
13327
- * rejects, the configured `onPersistError` is invoked so failures are
13328
- * surfaced instead of swallowed by an unhandled promise rejection.
13359
+ * is missing or throwing, the error is surfaced via onPersistError.
13329
13360
  */
13330
13361
  persist() {
13331
13362
  if (!this.graph) return;
13332
13363
  this.opts.store.saveGraph(this.graph).catch((err) => {
13333
- if (this.opts.onPersistError) this.opts.onPersistError(err);
13334
- else
13335
- console.warn(
13336
- "[task-tracker] saveGraph failed:",
13337
- err instanceof Error ? err.message : String(err)
13338
- );
13364
+ this.opts.onPersistError ? this.opts.onPersistError(err) : console.warn("[task-tracker] saveGraph failed:", err instanceof Error ? err.message : String(err));
13339
13365
  });
13340
13366
  }
13341
13367
  };