@wrongstack/tools 0.5.6 → 0.6.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.
package/dist/index.js CHANGED
@@ -281,12 +281,17 @@ function findSimilarity(haystack, needle) {
281
281
  }
282
282
 
283
283
  // src/_regex.ts
284
- var MAX_PATTERN_LEN = 512;
284
+ var MAX_PATTERN_LEN = 256;
285
285
  var DANGEROUS_PATTERNS = [
286
- /(\([^)]*[+*][^)]*\))[+*]/,
287
286
  // (a+)+, (.*)+, etc — nested quantifier on a group with internal quantifier
288
- /(\(\?:[^)]*[+*][^)]*\))[+*]/
289
- // same, with non-capturing group
287
+ /(\([^)]*[+*][^)]*\))[+*]/,
288
+ /(\(\?:[^)]*[+*][^)]*\))[+*]/,
289
+ // Adjacent quantifiers: a++ a*+
290
+ /[+*]{2,}/,
291
+ // Quantifier on alternation with length 2+
292
+ /\([^|)]+\|[^)]+\)[+*][+*]/,
293
+ // Greedy quantifier inside lookahead/lookbehind — (?!.*a+)
294
+ /[\(\[][^)\]]*[+*][^)\]]*[\)\]][^)]*\?\??/
290
295
  ];
291
296
  function compileUserRegex(pattern, flags) {
292
297
  if (typeof pattern !== "string") {
@@ -854,6 +859,326 @@ async function runNative(input, base, mode, limit, signal) {
854
859
  };
855
860
  }
856
861
 
862
+ // src/circuit-breaker.ts
863
+ var DEFAULT_MAX_CONSECUTIVE_FAILURES = 5;
864
+ var DEFAULT_SLOW_CALL_THRESHOLD_MS = 6e4;
865
+ var DEFAULT_MAX_SLOW_CALLS = 3;
866
+ var DEFAULT_WINDOW_MS = 6e4;
867
+ var DEFAULT_MAX_CALLS_PER_WINDOW = 30;
868
+ var DEFAULT_COOLDOWN_MS = 3e4;
869
+ var CircuitBreaker = class {
870
+ maxConsecutiveFailures;
871
+ slowCallThresholdMs;
872
+ maxSlowCalls;
873
+ windowMs;
874
+ maxCallsPerWindow;
875
+ cooldownMs;
876
+ state = "closed";
877
+ consecutiveFailures = 0;
878
+ window = [];
879
+ lastFailureAt = null;
880
+ lastSlowAt = null;
881
+ /** Timestamp when the breaker was opened (for cooldown calculation). */
882
+ openedAt = null;
883
+ /** Timestamp when the last call ran (for half-open gate). */
884
+ lastCallAt = null;
885
+ constructor(config = {}) {
886
+ this.maxConsecutiveFailures = config.maxConsecutiveFailures ?? DEFAULT_MAX_CONSECUTIVE_FAILURES;
887
+ this.slowCallThresholdMs = config.slowCallThresholdMs ?? DEFAULT_SLOW_CALL_THRESHOLD_MS;
888
+ this.maxSlowCalls = config.maxSlowCalls ?? DEFAULT_MAX_SLOW_CALLS;
889
+ this.windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;
890
+ this.maxCallsPerWindow = config.maxCallsPerWindow ?? DEFAULT_MAX_CALLS_PER_WINDOW;
891
+ this.cooldownMs = config.cooldownMs ?? DEFAULT_COOLDOWN_MS;
892
+ }
893
+ /**
894
+ * Returns true if the circuit allows a new call to proceed.
895
+ * When false, callers should abort the tool call and return a
896
+ * circuit-breaker error instead of spawning a process.
897
+ */
898
+ get canProceed() {
899
+ this._checkStateTransition();
900
+ return this.state !== "open";
901
+ }
902
+ /**
903
+ * Snapshot of the current breaker state for observability (`/kill`).
904
+ */
905
+ snapshot() {
906
+ this._checkStateTransition();
907
+ const now = Date.now();
908
+ let cooldownRemaining = null;
909
+ if (this.openedAt !== null && this.state === "open") {
910
+ const elapsed = now - this.openedAt;
911
+ cooldownRemaining = Math.max(0, this.cooldownMs - elapsed);
912
+ }
913
+ return {
914
+ state: this.state,
915
+ consecutiveFailures: this.consecutiveFailures,
916
+ slowCallsInWindow: this.window.filter((c) => c.slow).length,
917
+ callsInWindow: this.window.length,
918
+ windowMs: this.windowMs,
919
+ cooldownRemainingMs: cooldownRemaining,
920
+ lastFailureAt: this.lastFailureAt,
921
+ lastSlowAt: this.lastSlowAt
922
+ };
923
+ }
924
+ /**
925
+ * Call this BEFORE spawning a bash/exec process.
926
+ * Returns true if the call is allowed; false if the breaker is open.
927
+ * When false, callers MUST NOT spawn a process.
928
+ */
929
+ beforeCall() {
930
+ this._checkStateTransition();
931
+ if (this.state === "open") return false;
932
+ return true;
933
+ }
934
+ /**
935
+ * Call this AFTER a bash/exec process finishes (success or failure).
936
+ * `durationMs` is the wall-clock time the process ran.
937
+ * `failed` is true when the process returned a non-zero exit code or
938
+ * threw an exception before spawning.
939
+ */
940
+ afterCall(durationMs, failed) {
941
+ const now = Date.now();
942
+ this.lastCallAt = now;
943
+ if (this.state === "half-open") {
944
+ if (failed) {
945
+ this._trip();
946
+ return;
947
+ }
948
+ this._reset();
949
+ return;
950
+ }
951
+ this._pruneWindow(now);
952
+ const slow = durationMs >= this.slowCallThresholdMs;
953
+ this.window.push({ at: now, failed, slow });
954
+ if (failed) {
955
+ this.consecutiveFailures++;
956
+ this.lastFailureAt = now;
957
+ if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
958
+ this._trip();
959
+ }
960
+ return;
961
+ }
962
+ this.consecutiveFailures = 0;
963
+ if (slow) {
964
+ this.lastSlowAt = now;
965
+ const slowCount = this.window.filter((c) => c.slow).length;
966
+ if (slowCount >= this.maxSlowCalls) {
967
+ this._trip();
968
+ }
969
+ }
970
+ const callCount = this.window.length;
971
+ if (callCount >= this.maxCallsPerWindow) {
972
+ this._trip();
973
+ }
974
+ }
975
+ /** Force the breaker open. Used by /kill force and Ctrl+C. */
976
+ forceOpen() {
977
+ this._trip();
978
+ }
979
+ /** Force a reset to closed. Used by tests and /kill reset. */
980
+ forceReset() {
981
+ this._reset();
982
+ }
983
+ _trip() {
984
+ if (this.state === "open") return;
985
+ this.state = "open";
986
+ this.openedAt = Date.now();
987
+ }
988
+ _reset() {
989
+ this.state = "closed";
990
+ this.consecutiveFailures = 0;
991
+ this.window = [];
992
+ this.openedAt = null;
993
+ }
994
+ /** Transition from open → half-open when cooldown elapses. */
995
+ _checkStateTransition() {
996
+ if (this.state !== "open" || this.openedAt === null) return;
997
+ const elapsed = Date.now() - this.openedAt;
998
+ if (elapsed >= this.cooldownMs) {
999
+ this.state = "half-open";
1000
+ this.openedAt = null;
1001
+ }
1002
+ }
1003
+ _pruneWindow(now) {
1004
+ const cutoff = now - this.windowMs;
1005
+ this.window = this.window.filter((c) => c.at >= cutoff);
1006
+ }
1007
+ };
1008
+
1009
+ // src/process-registry.ts
1010
+ var DEFAULT_GRACE_MS = 2e3;
1011
+ var ProcessRegistryImpl = class {
1012
+ processes = /* @__PURE__ */ new Map();
1013
+ breaker;
1014
+ constructor(breakerConfig) {
1015
+ this.breaker = new CircuitBreaker(breakerConfig);
1016
+ }
1017
+ register(info) {
1018
+ this.processes.set(info.pid, { ...info, killed: false });
1019
+ }
1020
+ /** Unregister a process by PID. Called on 'close' / 'exit' events. */
1021
+ unregister(pid) {
1022
+ this.processes.delete(pid);
1023
+ }
1024
+ /** Get a single process by PID. */
1025
+ get(pid) {
1026
+ return this.processes.get(pid);
1027
+ }
1028
+ /** Get all tracked processes. */
1029
+ list() {
1030
+ return Array.from(this.processes.values());
1031
+ }
1032
+ /** Get processes filtered by name (e.g. 'bash', 'exec'). */
1033
+ byName(name) {
1034
+ return this.list().filter((p) => p.name === name);
1035
+ }
1036
+ /** Get processes filtered by session. */
1037
+ bySession(sessionId) {
1038
+ return this.list().filter((p) => p.sessionId === sessionId);
1039
+ }
1040
+ /** Count of active (non-killed) processes. */
1041
+ get activeCount() {
1042
+ let n = 0;
1043
+ for (const p of this.processes.values()) {
1044
+ if (!p.killed) n++;
1045
+ }
1046
+ return n;
1047
+ }
1048
+ /**
1049
+ * Combined stats for observability — used by /ps and the TUI status bar.
1050
+ */
1051
+ stats() {
1052
+ return {
1053
+ activeCount: this.activeCount,
1054
+ totalCount: this.processes.size,
1055
+ breaker: this.breaker.snapshot()
1056
+ };
1057
+ }
1058
+ /**
1059
+ * Returns true if the circuit allows a new bash/exec call to proceed.
1060
+ * When false, callers MUST NOT spawn a process.
1061
+ */
1062
+ get canProceed() {
1063
+ return this.breaker.canProceed;
1064
+ }
1065
+ /**
1066
+ * Called before spawning a process. Returns true if allowed; false if
1067
+ * the circuit breaker is open.
1068
+ */
1069
+ beforeCall() {
1070
+ return this.breaker.beforeCall();
1071
+ }
1072
+ /**
1073
+ * Called after a process finishes. `durationMs` is wall-clock time;
1074
+ * `failed` is true for non-zero exit codes.
1075
+ */
1076
+ afterCall(durationMs, failed) {
1077
+ this.breaker.afterCall(durationMs, failed);
1078
+ }
1079
+ /** Force-open the circuit breaker (Ctrl+C, /kill force). */
1080
+ forceBreakerOpen() {
1081
+ this.breaker.forceOpen();
1082
+ }
1083
+ /** Force-reset the circuit breaker to closed (/kill reset). */
1084
+ forceBreakerReset() {
1085
+ this.breaker.forceReset();
1086
+ }
1087
+ /** Kill a single process by PID.
1088
+ *
1089
+ * On POSIX: sends SIGTERM to the *process group* (-pid) so that
1090
+ * runaway grandchild processes (`sleep 9999 & disown`) are also killed.
1091
+ * After `graceMs` a SIGKILL is sent if the process hasn't exited.
1092
+ *
1093
+ * On Windows: `child.kill()` maps to TerminateProcess — process groups
1094
+ * are not meaningfully supported. A second `force=true` call sends
1095
+ * SIGKILL (which maps to TerminateProcess again — the distinction is
1096
+ * in the exit code, not the signal).
1097
+ *
1098
+ * Returns true if the process was found and kill was attempted.
1099
+ */
1100
+ kill(pid, opts = {}) {
1101
+ const p = this.processes.get(pid);
1102
+ if (!p) return false;
1103
+ if (p.killed) return true;
1104
+ const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;
1105
+ const isWin = os.platform() === "win32";
1106
+ if (isWin) {
1107
+ try {
1108
+ p.child.kill(force ? "SIGKILL" : "SIGTERM");
1109
+ } catch {
1110
+ }
1111
+ p.killed = true;
1112
+ return true;
1113
+ }
1114
+ try {
1115
+ if (force) {
1116
+ try {
1117
+ process.kill(-pid, "SIGKILL");
1118
+ } catch {
1119
+ p.child.kill("SIGKILL");
1120
+ }
1121
+ } else {
1122
+ try {
1123
+ process.kill(-pid, "SIGTERM");
1124
+ } catch {
1125
+ p.child.kill("SIGTERM");
1126
+ }
1127
+ const timer = setTimeout(() => {
1128
+ if (this.processes.has(pid) && !p.child.killed) {
1129
+ try {
1130
+ process.kill(-pid, "SIGKILL");
1131
+ } catch {
1132
+ try {
1133
+ p.child.kill("SIGKILL");
1134
+ } catch {
1135
+ }
1136
+ }
1137
+ }
1138
+ }, graceMs);
1139
+ timer.unref?.();
1140
+ }
1141
+ } catch {
1142
+ }
1143
+ p.killed = true;
1144
+ return true;
1145
+ }
1146
+ /**
1147
+ * Kill all tracked processes.
1148
+ * Returns the PIDs that were kill()ed.
1149
+ */
1150
+ killAll(opts = {}) {
1151
+ const pids = Array.from(this.processes.keys());
1152
+ const killed = [];
1153
+ for (const pid of pids) {
1154
+ if (this.kill(pid, opts)) killed.push(pid);
1155
+ }
1156
+ return killed;
1157
+ }
1158
+ /**
1159
+ * Kill all processes for a specific session.
1160
+ * Returns the PIDs that were kill()ed.
1161
+ */
1162
+ killSession(sessionId, opts = {}) {
1163
+ const pids = this.bySession(sessionId).map((p) => p.pid);
1164
+ const killed = [];
1165
+ for (const pid of pids) {
1166
+ if (this.kill(pid, opts)) killed.push(pid);
1167
+ }
1168
+ return killed;
1169
+ }
1170
+ };
1171
+ var _registry;
1172
+ function getProcessRegistry() {
1173
+ if (!_registry) {
1174
+ _registry = new ProcessRegistryImpl();
1175
+ }
1176
+ return _registry;
1177
+ }
1178
+ function _resetProcessRegistry() {
1179
+ _registry = void 0;
1180
+ }
1181
+
857
1182
  // src/bash.ts
858
1183
  var MAX_OUTPUT = 32768;
859
1184
  var DEFAULT_TIMEOUT = 3e4;
@@ -892,12 +1217,27 @@ var bashTool = {
892
1217
  },
893
1218
  async *executeStream(input, ctx, opts) {
894
1219
  if (!input?.command) throw new Error("bash: command is required");
1220
+ const registry = getProcessRegistry();
1221
+ if (!registry.beforeCall()) {
1222
+ yield {
1223
+ type: "final",
1224
+ output: {
1225
+ output: "",
1226
+ exit_code: 1,
1227
+ timed_out: false,
1228
+ pid: null,
1229
+ error: "bash: circuit breaker open \u2014 too many consecutive failures or slow calls. Use /kill to inspect or /kill reset to recover."
1230
+ }
1231
+ };
1232
+ return;
1233
+ }
895
1234
  const timeoutMs = Math.max(1, Math.min(input.timeout_ms ?? DEFAULT_TIMEOUT, 6e5));
896
1235
  const isWin = os.platform() === "win32";
897
1236
  const shell = isWin ? process.env["COMSPEC"] ?? "cmd.exe" : process.env["SHELL"] ?? "/bin/bash";
898
1237
  const args = isWin ? ["/c", input.command] : ["-c", input.command];
899
1238
  const env = buildChildEnv(ctx.session?.id);
900
1239
  const detached = isWin ? !!input.background : true;
1240
+ const startedAt = Date.now();
901
1241
  if (input.background) {
902
1242
  let buf2 = "";
903
1243
  let truncated = false;
@@ -908,7 +1248,18 @@ var bashTool = {
908
1248
  detached: true,
909
1249
  signal: opts.signal
910
1250
  });
911
- const pid = child2.pid;
1251
+ const pid2 = child2.pid;
1252
+ if (typeof pid2 === "number") {
1253
+ registry.register({
1254
+ pid: pid2,
1255
+ name: "bash",
1256
+ command: input.command,
1257
+ startedAt: Date.now(),
1258
+ sessionId: ctx.session?.id,
1259
+ child: child2
1260
+ });
1261
+ child2.on("close", () => registry.unregister(pid2));
1262
+ }
912
1263
  child2.stdout?.on("data", (chunk) => {
913
1264
  if (!truncated) {
914
1265
  const remain = MAX_OUTPUT - buf2.length;
@@ -928,15 +1279,16 @@ var bashTool = {
928
1279
  }
929
1280
  });
930
1281
  child2.on("close", () => {
1282
+ registry.afterCall(Date.now() - startedAt, false);
931
1283
  });
932
- if (typeof pid === "number") child2.unref();
1284
+ if (typeof pid2 === "number") child2.unref();
933
1285
  yield {
934
1286
  type: "final",
935
1287
  output: {
936
1288
  output: truncated ? buf2.slice(0, MAX_OUTPUT) + "\u2026[truncated]" : buf2,
937
1289
  exit_code: null,
938
1290
  timed_out: false,
939
- pid
1291
+ pid: pid2
940
1292
  }
941
1293
  };
942
1294
  return;
@@ -948,6 +1300,17 @@ var bashTool = {
948
1300
  detached,
949
1301
  signal: opts.signal
950
1302
  });
1303
+ const pid = child.pid;
1304
+ if (typeof pid === "number") {
1305
+ registry.register({
1306
+ pid,
1307
+ name: "bash",
1308
+ command: input.command,
1309
+ startedAt: Date.now(),
1310
+ sessionId: ctx.session?.id,
1311
+ child
1312
+ });
1313
+ }
951
1314
  let buf = "";
952
1315
  let pending = "";
953
1316
  let timedOut = false;
@@ -1030,10 +1393,13 @@ var bashTool = {
1030
1393
  });
1031
1394
  child.on("error", (err) => {
1032
1395
  for (const t of timers) clearTimeout(t);
1396
+ registry.afterCall(Date.now() - startedAt, true);
1033
1397
  push({ kind: "error", err });
1034
1398
  });
1035
1399
  child.on("close", (code) => {
1036
1400
  for (const t of timers) clearTimeout(t);
1401
+ if (typeof pid === "number") registry.unregister(pid);
1402
+ registry.afterCall(Date.now() - startedAt, code !== 0 && code !== null);
1037
1403
  push({ kind: "end", code });
1038
1404
  });
1039
1405
  try {
@@ -1124,14 +1490,21 @@ var BLOCKED_ARG_PATTERNS = {
1124
1490
  // go run could execute arbitrary .go files; -ldflags could inject build-time code
1125
1491
  go: [/^-ldflags$/],
1126
1492
  // bun --preload is similar to node --require
1127
- bun: [/^--preload$/],
1493
+ bun: [/^--preload$/, /^run$/, /^bunx$/, /^create$/, /^init$/],
1128
1494
  // docker build/run can create containers with host access;
1129
1495
  // only allow read-only commands (ps, images, version)
1130
1496
  docker: [/^build$/, /^run$/, /^exec$/, /^push$/, /^pull$/],
1131
1497
  // find -exec/-ok/-execdir execute arbitrary commands
1132
1498
  find: [/^-exec$/, /^-exec;$/, /^-ok$/, /^-ok;$/, /^-execdir$/, /^-execdir;$/, /^-exec=/, /^-ok=/, /^-execdir=/],
1133
1499
  // rm -rf / is catastrophic — block root and home targets
1134
- rm: [/^\/$/, /^\/\*$/, /^~$/]
1500
+ rm: [/^\/$/, /^\/\*$/, /^~$/],
1501
+ // npm run/exec/create/pack/publish can execute arbitrary scripts or publish malware
1502
+ npm: [/^run$/, /^exec$/, /^create$/, /^init$/, /^pack$/, /^publish$/, /^deploy$/],
1503
+ // pnpm run/dlx/exec/create can execute arbitrary scripts
1504
+ pnpm: [/^run$/, /^dlx$/, /^exec$/, /^create$/, /^init$/, /^pack$/, /^publish$/, /^deploy$/],
1505
+ // npx should only be used for --version; any package name is a vector for
1506
+ // malicious package execution (typosquatting, dependency confusion)
1507
+ npx: [/^[^\s]+$/]
1135
1508
  };
1136
1509
  function validateArgs(cmd, args) {
1137
1510
  const blocked = BLOCKED_ARG_PATTERNS[cmd];
@@ -1164,6 +1537,18 @@ var execTool = {
1164
1537
  required: ["command"]
1165
1538
  },
1166
1539
  async execute(input, ctx, opts) {
1540
+ const registry = getProcessRegistry();
1541
+ if (!registry.canProceed) {
1542
+ return {
1543
+ command: input.command,
1544
+ args: input.args ?? [],
1545
+ stdout: "",
1546
+ stderr: "Circuit breaker is open \u2014 too many consecutive failures. Use /kill reset to recover.",
1547
+ exitCode: 1,
1548
+ truncated: false,
1549
+ allowed: false
1550
+ };
1551
+ }
1167
1552
  const cmd = input.command.trim();
1168
1553
  if (!cmd)
1169
1554
  return {
@@ -1223,15 +1608,23 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
1223
1608
  let stdout = "";
1224
1609
  let stderr = "";
1225
1610
  let killed = false;
1611
+ const startedAt = Date.now();
1226
1612
  const child = spawn(cmd, args, {
1227
1613
  cwd,
1228
1614
  signal,
1229
1615
  env: buildChildEnv(sessionId),
1230
1616
  stdio: ["ignore", "pipe", "pipe"]
1231
1617
  });
1618
+ const registry = getProcessRegistry();
1619
+ const pid = child.pid;
1620
+ if (typeof pid === "number") {
1621
+ const fullCommand = `${cmd} ${args.join(" ")}`;
1622
+ registry.register({ pid, name: "exec", command: fullCommand, startedAt: Date.now(), sessionId, child });
1623
+ }
1232
1624
  const timer = setTimeout(() => {
1233
1625
  killed = true;
1234
- child.kill("SIGTERM");
1626
+ if (typeof pid === "number") registry.kill(pid);
1627
+ else child.kill("SIGTERM");
1235
1628
  }, timeout);
1236
1629
  child.stdout?.on("data", (chunk) => {
1237
1630
  if (stdout.length < MAX_OUTPUT2) stdout += chunk.toString();
@@ -1241,18 +1634,24 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
1241
1634
  });
1242
1635
  child.on("close", (code) => {
1243
1636
  clearTimeout(timer);
1637
+ if (typeof pid === "number") registry.unregister(pid);
1638
+ const durationMs = Date.now() - startedAt;
1639
+ const exitCode = killed ? 124 : code ?? 1;
1640
+ registry.afterCall(durationMs, exitCode !== 0);
1244
1641
  resolve5({
1245
1642
  command: cmd,
1246
1643
  args,
1247
1644
  stdout: stdout.slice(0, MAX_OUTPUT2),
1248
1645
  stderr: stderr.slice(0, MAX_OUTPUT2),
1249
- exitCode: killed ? 124 : code ?? 1,
1646
+ exitCode,
1250
1647
  truncated: stdout.length >= MAX_OUTPUT2 || stderr.length >= MAX_OUTPUT2,
1251
1648
  allowed: true
1252
1649
  });
1253
1650
  });
1254
1651
  child.on("error", (err) => {
1255
1652
  clearTimeout(timer);
1653
+ if (typeof pid === "number") registry.unregister(pid);
1654
+ registry.afterCall(Date.now() - startedAt, true);
1256
1655
  resolve5({
1257
1656
  command: cmd,
1258
1657
  args,
@@ -3958,7 +4357,7 @@ async function handleBuiltIn(name, templateFiles, cwd, ctx, dryRun, vars) {
3958
4357
  const fullPath = target;
3959
4358
  if (!dryRun) {
3960
4359
  await fs4.mkdir(path.dirname(fullPath), { recursive: true });
3961
- await fs4.writeFile(fullPath, substituteVars(content, name, vars), "utf8");
4360
+ await atomicWrite(fullPath, substituteVars(content, name, vars));
3962
4361
  }
3963
4362
  files.push(resolvedPath);
3964
4363
  filesCreated++;
@@ -4525,6 +4924,6 @@ var builtinToolsPack = {
4525
4924
  tools: builtinTools
4526
4925
  };
4527
4926
 
4528
- export { auditTool, bashTool, batchToolUseTool, builtinTools, builtinToolsPack, createModeTool, diffTool, documentTool, editTool, execTool, fetchTool, forgetTool, formatTool, gitTool, globTool, grepTool, installTool, jsonTool, lintTool, logsTool, outdatedTool, patchTool, planTool, readTool, rememberTool, replaceTool, scaffoldTool, searchTool, testTool, todoTool, toolHelpTool, toolSearchTool, toolUseTool, treeTool, typecheckTool, writeTool };
4927
+ export { CircuitBreaker, _resetProcessRegistry, auditTool, bashTool, batchToolUseTool, builtinTools, builtinToolsPack, createModeTool, diffTool, documentTool, editTool, execTool, fetchTool, forgetTool, formatTool, getProcessRegistry, gitTool, globTool, grepTool, installTool, jsonTool, lintTool, logsTool, outdatedTool, patchTool, planTool, readTool, rememberTool, replaceTool, scaffoldTool, searchTool, testTool, todoTool, toolHelpTool, toolSearchTool, toolUseTool, treeTool, typecheckTool, writeTool };
4529
4928
  //# sourceMappingURL=index.js.map
4530
4929
  //# sourceMappingURL=index.js.map