@wrongstack/core 0.155.0 → 0.236.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.
Files changed (81) hide show
  1. package/dist/{agent-bridge-BbZU5TPN.d.ts → agent-bridge-Cimv7bK7.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-Bsueu0J2.d.ts → agent-subagent-runner-C658wj_c.d.ts} +9 -8
  3. package/dist/{brain-CS_B0vIE.d.ts → brain-sCZ3lCjq.d.ts} +26 -2
  4. package/dist/{compactor-BueGt7LG.d.ts → compactor-BRfg3QPd.d.ts} +1 -1
  5. package/dist/{config-BaVThgnT.d.ts → config-Koq6f3fs.d.ts} +2 -2
  6. package/dist/{context-C7G_MtLV.d.ts → context-CLz3z_E8.d.ts} +126 -2
  7. package/dist/coordination/index.d.ts +70 -13
  8. package/dist/coordination/index.js +1983 -145
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +26 -26
  11. package/dist/defaults/index.js +1105 -289
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +45 -16
  14. package/dist/execution/index.js +224 -53
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +86 -0
  17. package/dist/execution/prompt-enhancer.js +125 -0
  18. package/dist/execution/prompt-enhancer.js.map +1 -0
  19. package/dist/extension/index.d.ts +6 -6
  20. package/dist/extension/index.js +3 -1
  21. package/dist/extension/index.js.map +1 -1
  22. package/dist/{goal-preamble-CbV8pXLD.d.ts → goal-preamble-CnbzyVvl.d.ts} +19 -10
  23. package/dist/{index-CI1hRfPt.d.ts → index-BlMqh5GO.d.ts} +8 -8
  24. package/dist/{index-B5wz-GXm.d.ts → index-C2eSNPsB.d.ts} +7 -5
  25. package/dist/index.d.ts +438 -128
  26. package/dist/index.js +4974 -836
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +7 -7
  29. package/dist/infrastructure/index.js +61 -13
  30. package/dist/infrastructure/index.js.map +1 -1
  31. package/dist/kernel/index.d.ts +9 -9
  32. package/dist/kernel/index.js +7 -1
  33. package/dist/kernel/index.js.map +1 -1
  34. package/dist/{llm-selector-CP72f1lC.d.ts → llm-selector-D22R4AFz.d.ts} +2 -2
  35. package/dist/logger-DmmQhf4P.d.ts +65 -0
  36. package/dist/{mcp-servers-CPERR2De.d.ts → mcp-servers-DFbirBv6.d.ts} +3 -3
  37. package/dist/models/index.d.ts +5 -5
  38. package/dist/models/index.js +89 -9
  39. package/dist/models/index.js.map +1 -1
  40. package/dist/{models-registry-D90K9UnM.d.ts → models-registry-CnJRjTXc.d.ts} +1 -1
  41. package/dist/{multi-agent-coordinator-BSKSFNhv.d.ts → multi-agent-coordinator-60weDZoA.d.ts} +8 -8
  42. package/dist/{null-fleet-bus-CGOez8Le.d.ts → null-fleet-bus-1068dEnr.d.ts} +7 -7
  43. package/dist/observability/index.d.ts +2 -2
  44. package/dist/package-outdated-watcher-pzJ5w7y8.d.ts +560 -0
  45. package/dist/{parallel-eternal-engine-CYoTKjsz.d.ts → parallel-eternal-engine-DtG1fjc9.d.ts} +13 -9
  46. package/dist/{path-resolver-DuhlmPil.d.ts → path-resolver-CA1ULU0J.d.ts} +3 -3
  47. package/dist/{permission-B7nKnEvQ.d.ts → permission-DbWPbuoA.d.ts} +1 -1
  48. package/dist/{permission-policy-8-6zBmfA.d.ts → permission-policy-AOk0LVsV.d.ts} +2 -2
  49. package/dist/pipeline-DsmlwTXu.d.ts +493 -0
  50. package/dist/{plan-templates-DbH7lg-t.d.ts → plan-templates-DPABrDvy.d.ts} +18 -7
  51. package/dist/{provider-runner-Cocq0O9E.d.ts → provider-runner-D0HgUqwV.d.ts} +3 -3
  52. package/dist/{retry-policy-rutAfVeR.d.ts → retry-policy-BVnkbMET.d.ts} +1 -1
  53. package/dist/sdd/index.d.ts +8 -8
  54. package/dist/sdd/index.js +215 -79
  55. package/dist/sdd/index.js.map +1 -1
  56. package/dist/{secret-vault-w8MbUe2Q.d.ts → secret-vault-CeVNiy_f.d.ts} +3 -2
  57. package/dist/security/index.d.ts +5 -4
  58. package/dist/security/index.js +155 -13
  59. package/dist/security/index.js.map +1 -1
  60. package/dist/{selector-4vDFZKt3.d.ts → selector-Cb4_9-hf.d.ts} +1 -1
  61. package/dist/{session-event-bridge-DWlvglC2.d.ts → session-event-bridge-BhtkkFFy.d.ts} +4 -2
  62. package/dist/{session-reader-BAtCxdaw.d.ts → session-reader-CCOssnBS.d.ts} +1 -1
  63. package/dist/skills/index.js +171 -21
  64. package/dist/skills/index.js.map +1 -1
  65. package/dist/storage/index.d.ts +150 -12
  66. package/dist/storage/index.js +1041 -214
  67. package/dist/storage/index.js.map +1 -1
  68. package/dist/types/index.d.ts +67 -20
  69. package/dist/types/index.js +557 -52
  70. package/dist/types/index.js.map +1 -1
  71. package/dist/utils/expect-defined.js +3 -1
  72. package/dist/utils/expect-defined.js.map +1 -1
  73. package/dist/utils/index.d.ts +16 -4
  74. package/dist/utils/index.js +40 -14
  75. package/dist/utils/index.js.map +1 -1
  76. package/dist/{wstack-paths-DD50Omgn.d.ts → wstack-paths-CJjEwPXn.d.ts} +14 -1
  77. package/package.json +7 -3
  78. package/skills/chimera/SKILL.md +105 -0
  79. package/skills/research-web/SKILL.md +342 -0
  80. package/dist/logger-B9J5puGM.d.ts +0 -32
  81. package/dist/pipeline-BG7UgbDc.d.ts +0 -239
@@ -77,7 +77,13 @@ var ERROR_CODES = {
77
77
  FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
78
78
  FS_DELETE_FAILED: "FS_DELETE_FAILED",
79
79
  FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
80
+ // SDD (Spec-Driven Development)
81
+ SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
82
+ SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
83
+ SDD_INVALID_STATE: "SDD_INVALID_STATE",
84
+ SDD_NOT_READY: "SDD_NOT_READY",
80
85
  // General
86
+ VALIDATION_ERROR: "VALIDATION_ERROR",
81
87
  UNKNOWN: "UNKNOWN"
82
88
  };
83
89
  var WrongStackError = class extends Error {
@@ -192,6 +198,20 @@ var SessionError = class extends WrongStackError {
192
198
  this.sessionId = opts.sessionId;
193
199
  }
194
200
  };
201
+ var SddError = class extends WrongStackError {
202
+ constructor(opts) {
203
+ super({
204
+ message: opts.message,
205
+ code: opts.code,
206
+ subsystem: "sdd",
207
+ severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? "warning" : "error",
208
+ recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,
209
+ context: opts.context,
210
+ cause: opts.cause
211
+ });
212
+ this.name = "SddError";
213
+ }
214
+ };
195
215
  var FsError = class extends WrongStackError {
196
216
  path;
197
217
  constructor(opts) {
@@ -229,6 +249,9 @@ function isAgentError(err) {
229
249
  function isFsError(err) {
230
250
  return err instanceof FsError;
231
251
  }
252
+ function isSddError(err) {
253
+ return err instanceof SddError;
254
+ }
232
255
 
233
256
  // src/types/provider.ts
234
257
  var ProviderError = class extends WrongStackError {
@@ -419,7 +442,7 @@ async function renameWithRetry(from, to) {
419
442
  if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
420
443
  throw err;
421
444
  }
422
- await new Promise((resolve3) => setTimeout(resolve3, delays[i]));
445
+ await new Promise((resolve4) => setTimeout(resolve4, delays[i]));
423
446
  }
424
447
  }
425
448
  throw lastErr;
@@ -489,6 +512,26 @@ var KEY_BYTES = 32;
489
512
  var IV_BYTES = 12;
490
513
  var TAG_BYTES = 16;
491
514
  var ALGO = "aes-256-gcm";
515
+ var KEY_FILE_MODE = 384;
516
+ function checkKeyFilePermissions(keyFile) {
517
+ if (process.platform === "win32") return;
518
+ try {
519
+ const stat2 = fs2.statSync(keyFile);
520
+ const actualMode = stat2.mode & 511;
521
+ if (actualMode !== KEY_FILE_MODE) {
522
+ console.warn(JSON.stringify({
523
+ level: "warn",
524
+ event: "vault.key_file_wrong_permissions",
525
+ message: `Key file ${keyFile} has mode ${actualMode.toString(8)} \u2014 expected ${KEY_FILE_MODE.toString(8)}. Run: chmod ${KEY_FILE_MODE.toString(8)} ${keyFile}`,
526
+ keyFile,
527
+ expectedMode: KEY_FILE_MODE,
528
+ actualMode,
529
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530
+ }));
531
+ }
532
+ } catch {
533
+ }
534
+ }
492
535
  var DefaultSecretVault = class {
493
536
  keyFile;
494
537
  key;
@@ -512,14 +555,26 @@ var DefaultSecretVault = class {
512
555
  const rest = value.slice(ENCRYPTED_PREFIX.length);
513
556
  const parts = rest.split(":");
514
557
  if (parts.length !== 3) {
515
- throw new Error("SecretVault: malformed encrypted value");
558
+ throw new ConfigError({
559
+ message: "SecretVault: malformed encrypted value",
560
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
561
+ context: { field: "encrypted_value" }
562
+ });
516
563
  }
517
564
  const [ivB64, tagB64, ctB64] = parts;
518
565
  const iv = Buffer.from(ivB64, "base64");
519
566
  const tag = Buffer.from(tagB64, "base64");
520
567
  const ct = Buffer.from(ctB64, "base64");
521
- if (iv.length !== IV_BYTES) throw new Error("SecretVault: bad IV length");
522
- if (tag.length !== TAG_BYTES) throw new Error("SecretVault: bad tag length");
568
+ if (iv.length !== IV_BYTES) throw new ConfigError({
569
+ message: "SecretVault: bad IV length",
570
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
571
+ context: { expected: IV_BYTES, actual: iv.length }
572
+ });
573
+ if (tag.length !== TAG_BYTES) throw new ConfigError({
574
+ message: "SecretVault: bad tag length",
575
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
576
+ context: { expected: TAG_BYTES, actual: tag.length }
577
+ });
523
578
  const key = this.loadOrCreateKey();
524
579
  const decipher = createDecipheriv(ALGO, key, iv);
525
580
  decipher.setAuthTag(tag);
@@ -531,11 +586,14 @@ var DefaultSecretVault = class {
531
586
  try {
532
587
  const buf = fs2.readFileSync(this.keyFile);
533
588
  if (buf.length !== KEY_BYTES) {
534
- throw new Error(
535
- `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`
536
- );
589
+ throw new ConfigError({
590
+ message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`,
591
+ code: ERROR_CODES.CONFIG_INVALID,
592
+ context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
593
+ });
537
594
  }
538
595
  this.key = buf;
596
+ checkKeyFilePermissions(this.keyFile);
539
597
  return this.key;
540
598
  } catch (err) {
541
599
  if (err.code !== "ENOENT") throw err;
@@ -548,11 +606,14 @@ var DefaultSecretVault = class {
548
606
  if (err.code !== "EEXIST") throw err;
549
607
  const buf = fs2.readFileSync(this.keyFile);
550
608
  if (buf.length !== KEY_BYTES) {
551
- throw new Error(
552
- `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`
553
- );
609
+ throw new ConfigError({
610
+ message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`,
611
+ code: ERROR_CODES.CONFIG_INVALID,
612
+ context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
613
+ });
554
614
  }
555
615
  this.key = buf;
616
+ checkKeyFilePermissions(this.keyFile);
556
617
  return this.key;
557
618
  }
558
619
  this.key = key;
@@ -613,7 +674,7 @@ async function rewriteConfigEncrypted(configPath, vault, patch) {
613
674
  await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
614
675
  await restrictFilePermissions(configPath);
615
676
  }
616
- async function migratePlaintextSecrets(configPath, vault) {
677
+ async function migratePlaintextSecrets(configPath, vault, logger) {
617
678
  let raw;
618
679
  try {
619
680
  raw = await fs.readFile(configPath, "utf8");
@@ -630,11 +691,14 @@ async function migratePlaintextSecrets(configPath, vault) {
630
691
  const migrated = walkCount(parsed, vault, counter);
631
692
  if (counter.n === 0) return { migrated: 0, file: configPath };
632
693
  await atomicWrite(configPath, JSON.stringify(migrated, null, 2), { mode: 384 });
633
- await restrictFilePermissions(configPath);
694
+ await restrictFilePermissions(
695
+ configPath,
696
+ logger ? { warn: (msg) => logger.warn(msg) } : void 0
697
+ );
634
698
  return { migrated: counter.n, file: configPath };
635
699
  }
636
700
  async function restrictFilePermissions(filePath, opts) {
637
- const warn = ((msg) => console.warn(msg));
701
+ const warn = opts?.warn ?? ((msg) => console.warn(msg));
638
702
  if (process.platform === "win32") {
639
703
  try {
640
704
  const { execFile } = await import('child_process');
@@ -751,18 +815,24 @@ var COLORS = {
751
815
  trace: color.dim
752
816
  };
753
817
  var LOG_LEVELS = /* @__PURE__ */ new Set(["error", "warn", "info", "debug", "trace"]);
818
+ var LOG_FORMATS = /* @__PURE__ */ new Set(["pretty", "json"]);
754
819
  var DefaultLogger = class _DefaultLogger {
820
+ /** How many file writes between rotation size checks (statSync is not free). */
821
+ static ROTATE_CHECK_EVERY = 100;
755
822
  level;
756
823
  file;
757
824
  bindings;
758
- pretty;
825
+ format;
759
826
  stderr;
827
+ maxFileBytes;
828
+ writesSinceRotateCheck = 0;
760
829
  constructor(opts = {}) {
761
830
  this.level = opts.level ?? parseLogLevel(process.env.WRONGSTACK_LOG_LEVEL);
762
831
  this.file = opts.file;
763
832
  this.bindings = opts.bindings ?? {};
764
- this.pretty = opts.pretty ?? true;
833
+ this.format = opts.format ?? parseLogFormat(process.env.WRONGSTACK_LOG_FORMAT);
765
834
  this.stderr = opts.stderr !== false;
835
+ this.maxFileBytes = opts.maxFileBytes ?? 10 * 1024 * 1024;
766
836
  if (this.file) {
767
837
  try {
768
838
  fs2.mkdirSync(path4.dirname(this.file), { recursive: true });
@@ -789,11 +859,30 @@ var DefaultLogger = class _DefaultLogger {
789
859
  return new _DefaultLogger({
790
860
  level: this.level,
791
861
  file: this.file,
792
- pretty: this.pretty,
862
+ format: this.format,
793
863
  stderr: this.stderr,
864
+ maxFileBytes: this.maxFileBytes,
794
865
  bindings: { ...this.bindings, ...bindings }
795
866
  });
796
867
  }
868
+ /**
869
+ * Size-based rotation: when the file outgrows `maxFileBytes`, rename it to
870
+ * `<file>.1` (dropping the previous `.1`) so the live file restarts empty.
871
+ * Checked on the first write and every ROTATE_CHECK_EVERY writes after.
872
+ * Best-effort: a rename can fail on Windows while another process holds
873
+ * the file — the next check retries. Multiple processes appending to the
874
+ * same log all run this check; whoever crosses the threshold first wins.
875
+ */
876
+ maybeRotate(file) {
877
+ if (this.writesSinceRotateCheck++ % _DefaultLogger.ROTATE_CHECK_EVERY !== 0) return;
878
+ try {
879
+ const st = fs2.statSync(file);
880
+ if (st.size < this.maxFileBytes) return;
881
+ fs2.rmSync(`${file}.1`, { force: true });
882
+ fs2.renameSync(file, `${file}.1`);
883
+ } catch {
884
+ }
885
+ }
797
886
  log(level, msg, ctx) {
798
887
  const r = LEVEL_RANK[level];
799
888
  const allowed = LEVEL_RANK[this.level];
@@ -805,13 +894,17 @@ var DefaultLogger = class _DefaultLogger {
805
894
  }
806
895
  if (this.file) {
807
896
  try {
897
+ this.maybeRotate(this.file);
808
898
  fs2.appendFileSync(this.file, `${JSON.stringify(entry)}
809
899
  `);
810
900
  } catch {
811
901
  }
812
902
  }
813
903
  if (!this.stderr) return;
814
- if (r <= LEVEL_RANK.warn || this.level === "debug" || this.level === "trace") {
904
+ if (this.format === "json") {
905
+ writeErr(`${JSON.stringify(entry)}
906
+ `);
907
+ } else {
815
908
  const head = `${color.dim(ts)} ${COLORS[level](level.toUpperCase().padEnd(5))} ${msg}`;
816
909
  if (ctx !== void 0) {
817
910
  writeErr(`${head} ${formatCtx(ctx)}
@@ -826,6 +919,9 @@ var DefaultLogger = class _DefaultLogger {
826
919
  function parseLogLevel(raw) {
827
920
  return raw && LOG_LEVELS.has(raw) ? raw : "info";
828
921
  }
922
+ function parseLogFormat(raw) {
923
+ return raw && LOG_FORMATS.has(raw) ? raw : "pretty";
924
+ }
829
925
  function formatCtx(ctx) {
830
926
  if (ctx instanceof Error) return color.dim(ctx.message);
831
927
  if (typeof ctx === "string") return color.dim(ctx);
@@ -835,6 +931,22 @@ function formatCtx(ctx) {
835
931
  return color.dim(String(ctx));
836
932
  }
837
933
  }
934
+ var noOpLogger = {
935
+ // 'error' is the quietest level the Logger contract offers; the methods
936
+ // discard everything regardless, this only matters to level checks.
937
+ level: "error",
938
+ error: () => {
939
+ },
940
+ warn: () => {
941
+ },
942
+ info: () => {
943
+ },
944
+ debug: () => {
945
+ },
946
+ trace: () => {
947
+ },
948
+ child: () => noOpLogger
949
+ };
838
950
 
839
951
  // src/infrastructure/token-counter.ts
840
952
  var PRICE_CACHE_MAX_SIZE = 100;
@@ -975,7 +1087,9 @@ var MEMORY_TYPE_LABELS = {
975
1087
  // src/utils/expect-defined.ts
976
1088
  function expectDefined(value, label) {
977
1089
  if (value === null || value === void 0) {
978
- throw new Error("Expected value to be defined");
1090
+ const err = new Error("Expected value to be defined");
1091
+ err.name = "ExpectDefinedError";
1092
+ throw err;
979
1093
  }
980
1094
  return value;
981
1095
  }
@@ -1023,22 +1137,31 @@ function estimateToolResultTokens(content) {
1023
1137
  function estimateTextTokens(text) {
1024
1138
  return RoughTokenEstimate(text);
1025
1139
  }
1140
+ function computeMessageTokens(msg) {
1141
+ if (typeof msg.content === "string") return estimateTextTokens(msg.content);
1142
+ let total = 0;
1143
+ for (const b of msg.content) {
1144
+ if (b.type === "text") total += estimateTextTokens(b.text);
1145
+ else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
1146
+ else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
1147
+ else total += RoughTokenEstimate(JSON.stringify(b));
1148
+ }
1149
+ return total;
1150
+ }
1026
1151
  function estimateMessageTokens(messages) {
1027
1152
  let total = 0;
1028
1153
  for (const m of messages) {
1029
- if (typeof m.content === "string") {
1030
- total += estimateTextTokens(m.content);
1031
- } else {
1032
- for (const b of m.content) {
1033
- if (b.type === "text") total += estimateTextTokens(b.text);
1034
- else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
1035
- else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
1036
- }
1154
+ if (typeof m._estTokens === "number" && m._estTokens > 0) {
1155
+ total += m._estTokens;
1156
+ continue;
1037
1157
  }
1158
+ total += computeMessageTokens(m);
1038
1159
  }
1039
1160
  return total;
1040
1161
  }
1041
1162
  function estimateToolDefTokens(tool) {
1163
+ const cached = tool._estDefTokens;
1164
+ if (typeof cached === "number" && cached > 0) return cached;
1042
1165
  return RoughTokenEstimate(tool.name) + RoughTokenEstimate(tool.description ?? "") + RoughTokenEstimate(JSON.stringify(tool.inputSchema));
1043
1166
  }
1044
1167
  function estimateRequestTokens(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
@@ -1048,6 +1171,11 @@ function estimateRequestTokens(messages, systemPrompt, tools, calibrationKey = C
1048
1171
  } else if (Array.isArray(messages)) {
1049
1172
  for (const m of messages) {
1050
1173
  if (typeof m === "object" && m !== null && "content" in m) {
1174
+ const cached = m._estTokens;
1175
+ if (typeof cached === "number" && cached > 0) {
1176
+ messagesTokens += cached;
1177
+ continue;
1178
+ }
1051
1179
  const content = m.content;
1052
1180
  if (typeof content === "string") {
1053
1181
  messagesTokens += RoughTokenEstimate(content);
@@ -1213,6 +1341,18 @@ function findPreserveStart(messages, preserveK) {
1213
1341
  }
1214
1342
  function eliseOldToolResults(messages, opts) {
1215
1343
  const preserveStart = findPreserveStart(messages, opts.preserveK);
1344
+ let hasOversized = false;
1345
+ for (let i = 0; i < preserveStart && !hasOversized; i++) {
1346
+ const msg = messages[i];
1347
+ if (!msg || !Array.isArray(msg.content)) continue;
1348
+ for (const b of msg.content) {
1349
+ if (b.type === "tool_result" && estimateToolResultTokens(b.content) >= opts.eliseThreshold) {
1350
+ hasOversized = true;
1351
+ break;
1352
+ }
1353
+ }
1354
+ }
1355
+ if (!hasOversized) return { messages, saved: 0, changed: false };
1216
1356
  let saved = 0;
1217
1357
  let changed = false;
1218
1358
  const next = new Array(messages.length);
@@ -2393,6 +2533,77 @@ Remember: your job is to make the user a better developer, not just to complete
2393
2533
  tags: ["teaching", "mentor", "learning"],
2394
2534
  toolPreferences: ["read", "edit", "explain"],
2395
2535
  suggestedSkills: ["prompt-engineering", "skill-creator", "node-modern", "typescript-strict"]
2536
+ },
2537
+ {
2538
+ id: "research-web",
2539
+ name: "Research Web",
2540
+ description: "Current-data research \u2014 search web, verify, inject findings into context",
2541
+ prompt: `## Research Web Mode
2542
+
2543
+ You are in research mode. Your role: find, verify, and incorporate
2544
+ current web data. Your training data is stale \u2014 every factual claim
2545
+ about version numbers, API surfaces, package status, or ecosystem
2546
+ changes must be verified against live sources.
2547
+
2548
+ ### When to research
2549
+ - The user asks "is this still the case?", "what's current?", "latest version?"
2550
+ - You're about to claim a version number, deprecation, or API change
2551
+ - You're comparing tools, packages, or approaches released in the last 12 months
2552
+ - You realize your knowledge may be >6 months old on a fast-moving topic
2553
+
2554
+ ### Research methodology
2555
+ 1. **Search first, fetch selectively.** Use web_search with 5-8 results for
2556
+ broad queries. Then web_fetch the 1-2 most authoritative results for detail.
2557
+ Don't fetch every result \u2014 you'll burn tokens on noise.
2558
+ 2. **Cross-reference.** One source is a data point. Two sources that agree
2559
+ is a signal. Three is confirmation. Flag single-source claims as tentative.
2560
+ 3. **Cite sources.** Every factual claim from web data must include where it
2561
+ came from: domain name, and date if visible on the page.
2562
+ 4. **Know when to stop.** 2-3 searches + 1-2 fetches is usually sufficient.
2563
+ If you're on your 5th search without a clear answer, pause and tell the user
2564
+ what you've found and what's still unclear \u2014 let them decide to dig deeper.
2565
+ 5. **Inject findings for reuse.** After gathering current data, use
2566
+ context_manager with add_note to inject a structured "Research Findings"
2567
+ block into the conversation. Future turns see this and don't re-search.
2568
+
2569
+ ### Self-injection pattern
2570
+ When you discover current data mid-research, inject it so subsequent turns
2571
+ benefit without re-searching:
2572
+
2573
+ web_search("Next.js middleware breaking changes 2025")
2574
+ \u2192 Surfaced: Next.js 15.2 changed middleware runtime from edge to node
2575
+ web_fetch("https://nextjs.org/docs/messages/middleware-upgrade-guide")
2576
+ \u2192 Confirmed: middleware now runs on Node.js runtime by default
2577
+ context_manager: add_note(
2578
+ "## Research: Next.js middleware
2579
+ - Next.js 15.2: middleware defaults to Node.js runtime (was edge)
2580
+ - Breaking: edge-only APIs (crypto.subtle, WebSocket) no longer available
2581
+ - Migration: use node:* equivalents or set runtime: 'edge' explicitly
2582
+ - Source: nextjs.org/docs/messages/middleware-upgrade-guide"
2583
+ )
2584
+
2585
+ The add_note persists in conversation \u2014 you won't re-search on the next turn.
2586
+
2587
+ ### Anti-patterns
2588
+ - Don't research things already in the conversation context (including
2589
+ earlier add_note blocks you injected)
2590
+ - Don't treat a single web search result as ground truth \u2014 cross-reference
2591
+ - Don't inject raw JSON or search result dumps via add_note \u2014 summarize
2592
+ - Don't research while the user is waiting for a quick code edit \u2014 toggle
2593
+ research-web mode only during analysis/discussion phases
2594
+ - Don't research-loop: 5+ searches on one topic \u2192 stop and ask the user
2595
+
2596
+ ### Exiting research mode
2597
+ When the user no longer needs current-data research, suggest switching back
2598
+ to the previous mode. You stay in research mode until explicitly told to
2599
+ switch \u2014 but don't force web searches on every turn. The methodology rules
2600
+ above already gate when to actually search.
2601
+
2602
+ When you're done with research: suggest the user run \`/mode default\` or
2603
+ their previous mode.`,
2604
+ tags: ["research", "web", "current-data", "up-to-date"],
2605
+ toolPreferences: ["web_search", "web_fetch", "search", "fetch", "context_manager"],
2606
+ suggestedSkills: ["research-web", "tech-stack", "node-modern", "security-scanner", "react-modern"]
2396
2607
  }
2397
2608
  ];
2398
2609
 
@@ -2563,28 +2774,40 @@ var InMemoryAgentBridge = class {
2563
2774
  return () => this.subscriptions.delete(handler);
2564
2775
  }
2565
2776
  async request(msg, timeoutMs) {
2566
- if (this.stopped) throw new Error("Bridge is stopped");
2777
+ if (this.stopped) throw new AgentError({
2778
+ message: "Bridge is stopped",
2779
+ code: ERROR_CODES.AGENT_ABORTED
2780
+ });
2567
2781
  const timeout = timeoutMs ?? this.timeoutMs;
2568
2782
  const correlationId = msg.id;
2569
2783
  if (this.inflightGuards.has(correlationId)) {
2570
- throw new Error(
2571
- `Bridge request id "${correlationId}" collides with an in-flight request \u2014 caller is reusing message ids`
2572
- );
2784
+ throw new AgentError({
2785
+ message: `Bridge request id "${correlationId}" collides with an in-flight request \u2014 caller is reusing message ids`,
2786
+ code: ERROR_CODES.AGENT_RUN_FAILED,
2787
+ context: { correlationId }
2788
+ });
2573
2789
  }
2574
2790
  this.inflightGuards.add(correlationId);
2575
- return new Promise((resolve3, reject) => {
2791
+ return new Promise((resolve4, reject) => {
2576
2792
  const timer = setTimeout(() => {
2577
2793
  this.inflightGuards.delete(correlationId);
2578
2794
  this.pendingRequests.delete(correlationId);
2579
- reject(new Error(`Request ${correlationId} timed out after ${timeout}ms`));
2795
+ reject(new AgentError({
2796
+ message: `Request ${correlationId} timed out after ${timeout}ms`,
2797
+ code: ERROR_CODES.AGENT_RUN_FAILED,
2798
+ context: { correlationId, timeoutMs: timeout }
2799
+ }));
2580
2800
  }, timeout);
2581
2801
  if (!this.inflightGuards.has(correlationId)) {
2582
2802
  clearTimeout(timer);
2583
- reject(new Error("Bridge stopped"));
2803
+ reject(new AgentError({
2804
+ message: "Bridge stopped",
2805
+ code: ERROR_CODES.AGENT_ABORTED
2806
+ }));
2584
2807
  return;
2585
2808
  }
2586
2809
  this.pendingRequests.set(correlationId, {
2587
- resolve: resolve3,
2810
+ resolve: resolve4,
2588
2811
  reject,
2589
2812
  timer
2590
2813
  });
@@ -2601,7 +2824,10 @@ var InMemoryAgentBridge = class {
2601
2824
  this.stopped = true;
2602
2825
  for (const [, p] of this.pendingRequests) {
2603
2826
  clearTimeout(p.timer);
2604
- p.reject(new Error("Bridge stopped"));
2827
+ p.reject(new AgentError({
2828
+ message: "Bridge stopped",
2829
+ code: ERROR_CODES.AGENT_ABORTED
2830
+ }));
2605
2831
  }
2606
2832
  this.pendingRequests.clear();
2607
2833
  this.inflightGuards.clear();
@@ -2780,11 +3006,11 @@ function validateAgainstSchema(value, schema) {
2780
3006
  walk2(value, schema, "", errors);
2781
3007
  return { ok: errors.length === 0, errors };
2782
3008
  }
2783
- function walk2(value, schema, path6, errors) {
3009
+ function walk2(value, schema, path7, errors) {
2784
3010
  if (schema.enum !== void 0) {
2785
3011
  if (!schema.enum.some((e) => deepEqual(e, value))) {
2786
3012
  errors.push({
2787
- path: path6 || "<root>",
3013
+ path: path7 || "<root>",
2788
3014
  message: `expected one of ${JSON.stringify(schema.enum)}, got ${JSON.stringify(value)}`
2789
3015
  });
2790
3016
  return;
@@ -2793,7 +3019,7 @@ function walk2(value, schema, path6, errors) {
2793
3019
  if (typeof schema.type === "string") {
2794
3020
  if (!checkType(value, schema.type)) {
2795
3021
  errors.push({
2796
- path: path6 || "<root>",
3022
+ path: path7 || "<root>",
2797
3023
  message: `expected ${schema.type}, got ${describeType(value)}`
2798
3024
  });
2799
3025
  return;
@@ -2803,19 +3029,19 @@ function walk2(value, schema, path6, errors) {
2803
3029
  const obj = value;
2804
3030
  for (const req of schema.required ?? []) {
2805
3031
  if (!(req in obj)) {
2806
- errors.push({ path: joinPath(path6, req), message: "required property missing" });
3032
+ errors.push({ path: joinPath(path7, req), message: "required property missing" });
2807
3033
  }
2808
3034
  }
2809
3035
  if (schema.properties) {
2810
3036
  for (const [key, subSchema] of Object.entries(schema.properties)) {
2811
3037
  if (key in obj) {
2812
- walk2(obj[key], subSchema, joinPath(path6, key), errors);
3038
+ walk2(obj[key], subSchema, joinPath(path7, key), errors);
2813
3039
  }
2814
3040
  }
2815
3041
  }
2816
3042
  }
2817
3043
  if (schema.type === "array" && Array.isArray(value) && schema.items) {
2818
- value.forEach((item, i) => walk2(item, schema.items, `${path6}[${i}]`, errors));
3044
+ value.forEach((item, i) => walk2(item, schema.items, `${path7}[${i}]`, errors));
2819
3045
  }
2820
3046
  }
2821
3047
  function checkType(value, type) {
@@ -2913,7 +3139,7 @@ function createToolOutputSerializer(opts = {}) {
2913
3139
  }
2914
3140
 
2915
3141
  // src/execution/tool-executor.ts
2916
- var ToolExecutor = class {
3142
+ var ToolExecutor = class _ToolExecutor {
2917
3143
  constructor(registry, opts) {
2918
3144
  this.registry = registry;
2919
3145
  this.opts = opts;
@@ -2925,6 +3151,10 @@ var ToolExecutor = class {
2925
3151
  }
2926
3152
  registry;
2927
3153
  opts;
3154
+ /** Minimum gap between coalesced `partial_output` tool.progress emits. */
3155
+ static PROGRESS_EMIT_INTERVAL_MS = 100;
3156
+ /** Max chars of accumulated stream text carried per coalesced emit. */
3157
+ static PROGRESS_TAIL_CHARS = 16384;
2928
3158
  serializer;
2929
3159
  iterationTimeoutMs;
2930
3160
  maxToolTimeoutMs;
@@ -2970,9 +3200,6 @@ Please call the tool again with arguments that match its inputSchema. You can us
2970
3200
  return { result, tool, durationMs: Date.now() - start };
2971
3201
  }
2972
3202
  const toolDangerousCaps = getDangerousCapabilities(tool);
2973
- if (toolDangerousCaps.length > 0) {
2974
- if (this.opts.events) ;
2975
- }
2976
3203
  if (hasMalformedArguments(use.input)) {
2977
3204
  const result = this.malformedInputResult(use, extractMalformedRaw(use.input));
2978
3205
  budget = this.decrementBudget(result, budget);
@@ -3210,17 +3437,48 @@ ${post.additionalContext}` };
3210
3437
  throw new Error(`Tool "${tool.name}" does not support streaming execution`);
3211
3438
  }
3212
3439
  const stream = tool.executeStream(input, ctx, { signal });
3213
- for await (const ev of stream) {
3214
- if (ev.type === "final") {
3215
- finalOutput = ev.output;
3216
- sawFinal = true;
3217
- break;
3218
- }
3440
+ const iter = stream[Symbol.asyncIterator]();
3441
+ let progressTail = "";
3442
+ let lastProgressEmitAt = 0;
3443
+ const emitProgress = (ev) => {
3219
3444
  this.opts.events?.emit("tool.progress", {
3220
3445
  name: tool.name,
3221
3446
  id: toolUseId ?? "<unknown>",
3222
3447
  event: ev
3223
3448
  });
3449
+ };
3450
+ const flushProgressTail = (force) => {
3451
+ if (progressTail.length === 0) return;
3452
+ const now = Date.now();
3453
+ if (!force && now - lastProgressEmitAt < _ToolExecutor.PROGRESS_EMIT_INTERVAL_MS) return;
3454
+ const text = progressTail;
3455
+ progressTail = "";
3456
+ lastProgressEmitAt = now;
3457
+ emitProgress({ type: "partial_output", text });
3458
+ };
3459
+ try {
3460
+ while (true) {
3461
+ const { done, value: ev } = await iter.next();
3462
+ if (done) break;
3463
+ if (ev.type === "final") {
3464
+ finalOutput = ev.output;
3465
+ sawFinal = true;
3466
+ break;
3467
+ }
3468
+ if (ev.type === "partial_output" && typeof ev.text === "string") {
3469
+ progressTail += ev.text;
3470
+ if (progressTail.length > _ToolExecutor.PROGRESS_TAIL_CHARS) {
3471
+ progressTail = progressTail.slice(-_ToolExecutor.PROGRESS_TAIL_CHARS);
3472
+ }
3473
+ flushProgressTail(false);
3474
+ continue;
3475
+ }
3476
+ flushProgressTail(true);
3477
+ emitProgress(ev);
3478
+ }
3479
+ flushProgressTail(true);
3480
+ } finally {
3481
+ await iter.return?.(void 0);
3224
3482
  }
3225
3483
  if (!sawFinal) {
3226
3484
  throw new Error(`tool "${tool.name}" executeStream completed without a 'final' event`);
@@ -3329,6 +3587,253 @@ function extractMalformedRaw(input) {
3329
3587
  }
3330
3588
  }
3331
3589
 
3590
+ // src/core/conversation-state.ts
3591
+ var ConversationState = class {
3592
+ ctx;
3593
+ listeners = /* @__PURE__ */ new Set();
3594
+ constructor(ctx) {
3595
+ this.ctx = ctx;
3596
+ }
3597
+ get messages() {
3598
+ return this.ctx.messages;
3599
+ }
3600
+ get todos() {
3601
+ return this.ctx.todos;
3602
+ }
3603
+ get meta() {
3604
+ return this.ctx.meta;
3605
+ }
3606
+ /**
3607
+ * Cheap immutable snapshot. Useful for tests and for compaction passes
3608
+ * that need a stable view across an async boundary.
3609
+ *
3610
+ * Uses shallow-freeze instead of deep-freeze: only the wrapper object
3611
+ * and the three content arrays are frozen. Individual message/todo
3612
+ * objects are NOT recursively frozen — they are reconstructed via
3613
+ * spread copies and are immutable by convention. This cuts the freeze
3614
+ * count from O(n·m·d) (n=messages, m=content blocks, d=depth) to O(1).
3615
+ */
3616
+ snapshot() {
3617
+ const snap = {
3618
+ messages: [...this.ctx.messages],
3619
+ todos: [...this.ctx.todos],
3620
+ meta: { ...this.ctx.meta }
3621
+ };
3622
+ Object.freeze(snap.messages);
3623
+ Object.freeze(snap.todos);
3624
+ Object.freeze(snap.meta);
3625
+ return Object.freeze(snap);
3626
+ }
3627
+ appendMessage(message) {
3628
+ if (message._estTokens === void 0) {
3629
+ message._estTokens = computeMessageTokens(message);
3630
+ }
3631
+ this.ctx.messages.splice(this.ctx.messages.length, 0, message);
3632
+ this.emit({ kind: "message_appended", message });
3633
+ }
3634
+ replaceMessages(messages) {
3635
+ for (const m of messages) {
3636
+ if (m._estTokens === void 0) {
3637
+ m._estTokens = computeMessageTokens(m);
3638
+ }
3639
+ }
3640
+ const arr = this.ctx.messages;
3641
+ if (messages.length < arr.length) {
3642
+ arr.length = messages.length;
3643
+ }
3644
+ for (let i = 0; i < messages.length; i++) {
3645
+ arr[i] = messages[i];
3646
+ }
3647
+ if (messages.some(
3648
+ (m) => Array.isArray(m.content) && m.content.some((b) => b.type === "tool_use" || b.type === "tool_result")
3649
+ )) {
3650
+ this.ctx.toolAdjacencyDirty = true;
3651
+ }
3652
+ this.emit({ kind: "messages_replaced", messages: [...messages] });
3653
+ }
3654
+ replaceTodos(todos) {
3655
+ const allDone = todos.length > 0 && todos.every((t) => t.status === "completed");
3656
+ const effective = allDone ? [] : todos;
3657
+ this.ctx.todos.length = 0;
3658
+ this.ctx.todos.splice(0, 0, ...effective);
3659
+ this.emit({ kind: "todos_replaced", todos: [...effective] });
3660
+ }
3661
+ setMeta(key, value) {
3662
+ this.ctx.meta[key] = value;
3663
+ this.emit({ kind: "meta_set", key, value });
3664
+ }
3665
+ deleteMeta(key) {
3666
+ if (!(key in this.ctx.meta)) return;
3667
+ delete this.ctx.meta[key];
3668
+ this.emit({ kind: "meta_deleted", key });
3669
+ }
3670
+ clearMeta() {
3671
+ const keys = Object.keys(this.ctx.meta);
3672
+ if (keys.length === 0) return;
3673
+ for (const key of keys) delete this.ctx.meta[key];
3674
+ this.emit({ kind: "meta_cleared" });
3675
+ }
3676
+ /**
3677
+ * Subscribe to mutations that go through this wrapper. Direct mutations of
3678
+ * the compatibility arrays are intentionally not observed.
3679
+ */
3680
+ onChange(listener) {
3681
+ this.listeners.add(listener);
3682
+ return () => this.listeners.delete(listener);
3683
+ }
3684
+ emit(change) {
3685
+ for (const h of this.listeners) {
3686
+ try {
3687
+ h(change, this);
3688
+ } catch {
3689
+ }
3690
+ }
3691
+ }
3692
+ };
3693
+
3694
+ // src/core/context.ts
3695
+ var Context = class {
3696
+ messages = [];
3697
+ todos = [];
3698
+ readFiles = /* @__PURE__ */ new Set();
3699
+ fileMtimes = /* @__PURE__ */ new Map();
3700
+ systemPrompt;
3701
+ provider;
3702
+ session;
3703
+ signal;
3704
+ tokenCounter;
3705
+ cwd;
3706
+ projectRoot;
3707
+ /** Mutable working directory — starts as `cwd`. Change via `setWorkingDir()`. */
3708
+ workingDir;
3709
+ model;
3710
+ tools = [];
3711
+ meta = {};
3712
+ /** Agent id performing this run (e.g. 'leader', 'executor'). */
3713
+ agentId;
3714
+ /** Human-readable agent name. */
3715
+ agentName;
3716
+ /** Callbacks fired when `setWorkingDir()` changes the working directory. */
3717
+ _onWorkingDirChanged = [];
3718
+ /**
3719
+ * Set to true when the conversation gains new tool_use or tool_result
3720
+ * blocks — the only time repairToolUseAdjacency() can find new issues.
3721
+ * buildAndRunRequestPipeline() checks this flag to skip an O(n) scan
3722
+ * on iterations where no tool content was added (pure text responses).
3723
+ */
3724
+ toolAdjacencyDirty = false;
3725
+ constructor(init) {
3726
+ this.systemPrompt = init.systemPrompt;
3727
+ this.provider = init.provider;
3728
+ this.session = init.session;
3729
+ this.signal = init.signal;
3730
+ this.tokenCounter = init.tokenCounter;
3731
+ this.cwd = init.cwd;
3732
+ this.projectRoot = init.projectRoot;
3733
+ this.workingDir = init.workingDir ?? init.cwd;
3734
+ this.model = init.model;
3735
+ this.tools = init.tools ?? [];
3736
+ this.agentId = init.agentId ?? "unknown";
3737
+ this.agentName = init.agentName ?? "Unknown Agent";
3738
+ }
3739
+ /**
3740
+ * Observable wrapper over the mutable conversation state. Lazy so
3741
+ * subsystems that don't subscribe pay nothing. Mutations made directly
3742
+ * on `ctx.messages` / `ctx.todos` are still visible through this
3743
+ * wrapper's read API (it holds a reference, not a copy) but only
3744
+ * mutations that go through `state.appendMessage()` etc. fire
3745
+ * `onChange`. New code should prefer the wrapper API.
3746
+ */
3747
+ _state = null;
3748
+ get state() {
3749
+ if (!this._state) this._state = new ConversationState(this);
3750
+ return this._state;
3751
+ }
3752
+ /**
3753
+ * Register a teardown hook tied to the current run's abort signal.
3754
+ * Hooks registered before a run starts are stored and fired when the
3755
+ * next run ends; there is no immediate fire when no run is active.
3756
+ *
3757
+ * **Scope:** these hooks fire on the **whole agent run's** abort, not on
3758
+ * an individual tool call. For per-tool teardown of resources owned by
3759
+ * the tool author (child processes, handles), prefer `Tool.cleanup` —
3760
+ * see its JSDoc for the full rule.
3761
+ */
3762
+ abortHooks = /* @__PURE__ */ new Set();
3763
+ registerAbortHook(fn) {
3764
+ this.abortHooks.add(fn);
3765
+ return () => this.abortHooks.delete(fn);
3766
+ }
3767
+ async drainAbortHooks() {
3768
+ const snapshot = [...this.abortHooks].reverse();
3769
+ this.abortHooks.clear();
3770
+ for (const fn of snapshot) {
3771
+ try {
3772
+ await fn();
3773
+ } catch {
3774
+ }
3775
+ }
3776
+ }
3777
+ recordRead(absPath, mtimeMs) {
3778
+ this.readFiles.add(absPath);
3779
+ this.fileMtimes.set(absPath, mtimeMs);
3780
+ }
3781
+ /** Clear accumulated file-read metadata after compaction or at boundaries
3782
+ * where stale read history could cause tools to skip legitimate re-reads.
3783
+ * The agent re-populates this naturally on the next file access. */
3784
+ clearFileTracking() {
3785
+ this.readFiles.clear();
3786
+ this.fileMtimes.clear();
3787
+ }
3788
+ hasRead(absPath) {
3789
+ return this.readFiles.has(absPath);
3790
+ }
3791
+ lastReadMtime(absPath) {
3792
+ return this.fileMtimes.get(absPath);
3793
+ }
3794
+ /**
3795
+ * Change the working directory for path resolution. Resolves relative paths
3796
+ * against `projectRoot` and validates the result is within the project root.
3797
+ * Fires all registered `onWorkingDirChanged` callbacks.
3798
+ * Returns the resolved absolute path.
3799
+ */
3800
+ setWorkingDir(dir) {
3801
+ const resolved = path4.isAbsolute(dir) ? path4.resolve(dir) : path4.resolve(this.projectRoot, dir);
3802
+ const root = path4.resolve(this.projectRoot);
3803
+ const rel = path4.relative(root, resolved);
3804
+ if (rel.startsWith("..") || path4.isAbsolute(rel)) {
3805
+ throw new Error(
3806
+ `Working directory "${resolved}" is outside project root "${root}"`
3807
+ );
3808
+ }
3809
+ const old = this.workingDir;
3810
+ this.workingDir = resolved;
3811
+ for (const cb of this._onWorkingDirChanged) {
3812
+ try {
3813
+ cb(resolved, old);
3814
+ } catch {
3815
+ }
3816
+ }
3817
+ return resolved;
3818
+ }
3819
+ /**
3820
+ * Register a callback that fires when the working directory changes.
3821
+ * Returns an unsubscribe function. Callbacks are fired synchronously
3822
+ * inside `setWorkingDir()` — errors in callbacks are swallowed so one
3823
+ * bad listener doesn't prevent others from executing.
3824
+ */
3825
+ onWorkingDirChanged(cb) {
3826
+ this._onWorkingDirChanged.push(cb);
3827
+ return () => {
3828
+ const idx = this._onWorkingDirChanged.indexOf(cb);
3829
+ if (idx >= 0) this._onWorkingDirChanged.splice(idx, 1);
3830
+ };
3831
+ }
3832
+ usage() {
3833
+ return this.tokenCounter.total();
3834
+ }
3835
+ };
3836
+
3332
3837
  // src/utils/regex-guard.ts
3333
3838
  var MAX_PATTERN_LEN = 512;
3334
3839
  var DANGEROUS_PATTERNS = [
@@ -3641,6 +4146,6 @@ function renderPlainText(meta, events) {
3641
4146
  return lines.join("\n");
3642
4147
  }
3643
4148
 
3644
- export { AgentError, CONTEXT_WINDOW_MODES, ConfigError, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_TOOLS_CONFIG, DefaultErrorHandler, DefaultLogger, DefaultModelsRegistry, DefaultPathResolver, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultTokenCounter, ERROR_CODES, FsError, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, MEMORY_TYPE_LABELS, PluginError, ProviderError, SessionError, StreamHangError, ToolError, ToolExecutor, WrongStackError, asBlocks, asText, buildRecoveryStrategies, classifyFamily, computeTaskProgress, createMessage, decryptConfigSecrets, encryptConfigSecrets, findCriticalPath, formatContextWindowModeList, getContextWindowMode, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isPluginError, isSecretField, isSessionError, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isWrongStackError, listContextWindowModes, migratePlaintextSecrets, resolveContextWindowPolicy, rewriteConfigEncrypted, toWrongStackError, topologicalSort };
4149
+ export { AgentError, CONTEXT_WINDOW_MODES, ConfigError, Context, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_TOOLS_CONFIG, DefaultErrorHandler, DefaultLogger, DefaultModelsRegistry, DefaultPathResolver, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultTokenCounter, ERROR_CODES, FsError, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, MEMORY_TYPE_LABELS, PluginError, ProviderError, SddError, SessionError, StreamHangError, ToolError, ToolExecutor, WrongStackError, asBlocks, asText, buildRecoveryStrategies, classifyFamily, computeTaskProgress, createMessage, decryptConfigSecrets, encryptConfigSecrets, findCriticalPath, formatContextWindowModeList, getContextWindowMode, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isPluginError, isSddError, isSecretField, isSessionError, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isWrongStackError, listContextWindowModes, migratePlaintextSecrets, noOpLogger, resolveContextWindowPolicy, rewriteConfigEncrypted, toWrongStackError, topologicalSort };
3645
4150
  //# sourceMappingURL=index.js.map
3646
4151
  //# sourceMappingURL=index.js.map