@proxysoul/soulforge 2.20.8 → 2.20.10

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 (2) hide show
  1. package/dist/index.js +214 -78
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -46983,6 +46983,8 @@ function supportsTemperature(modelId) {
46983
46983
  const base = extractBaseModel(modelId);
46984
46984
  if (!base.startsWith("claude"))
46985
46985
  return true;
46986
+ if (isClaude5Plus(base))
46987
+ return false;
46986
46988
  const v = parseOpusVersion(base);
46987
46989
  if (!v)
46988
46990
  return true;
@@ -46990,11 +46992,20 @@ function supportsTemperature(modelId) {
46990
46992
  }
46991
46993
  function isAdaptiveOnly(modelId) {
46992
46994
  const base = extractBaseModel(modelId);
46995
+ if (isClaude5Plus(base))
46996
+ return true;
46993
46997
  const v = parseOpusVersion(base);
46994
46998
  if (!v)
46995
46999
  return false;
46996
47000
  return v.major >= 5 || v.major === 4 && v.minor >= 7;
46997
47001
  }
47002
+ function isClaude5Plus(base) {
47003
+ if (/(?:fable|mythos)-(\d+)/.test(base)) {
47004
+ const m = base.match(/(?:fable|mythos)-(\d+)/);
47005
+ return m ? Number(m[1]) >= 5 : false;
47006
+ }
47007
+ return false;
47008
+ }
46998
47009
 
46999
47010
  // src/utils/errors.ts
47000
47011
  function toErrorMessage(err2) {
@@ -52021,6 +52032,8 @@ var init_anthropic = __esm(() => {
52021
52032
  return result;
52022
52033
  },
52023
52034
  fallbackModels: [
52035
+ { id: "claude-fable-5", name: "Claude Fable 5" },
52036
+ { id: "claude-mythos-5", name: "Claude Mythos 5" },
52024
52037
  { id: "claude-opus-4-8", name: "Claude Opus 4.8" },
52025
52038
  { id: "claude-opus-4-7", name: "Claude Opus 4.7" },
52026
52039
  { id: "claude-opus-4-6", name: "Claude Opus 4.6" },
@@ -52032,6 +52045,8 @@ var init_anthropic = __esm(() => {
52032
52045
  { id: "claude-haiku-4", name: "Claude Haiku 4" }
52033
52046
  ],
52034
52047
  contextWindows: [
52048
+ ["claude-fable-5", 1e6],
52049
+ ["claude-mythos-5", 1e6],
52035
52050
  ["claude-opus-4-8", 1e6],
52036
52051
  ["claude-opus-4-7", 1e6],
52037
52052
  ["claude-opus-4-6", 1e6],
@@ -71947,7 +71962,7 @@ var package_default;
71947
71962
  var init_package = __esm(() => {
71948
71963
  package_default = {
71949
71964
  name: "@proxysoul/soulforge",
71950
- version: "2.20.8",
71965
+ version: "2.20.10",
71951
71966
  description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
71952
71967
  repository: {
71953
71968
  type: "git",
@@ -100230,6 +100245,7 @@ import {
100230
100245
  mkdirSync as mkdirSync13,
100231
100246
  readdirSync as readdirSync4,
100232
100247
  readFileSync as readFileSync13,
100248
+ statSync as statSync3,
100233
100249
  unlinkSync as unlinkSync4,
100234
100250
  writeFileSync as writeFileSync11
100235
100251
  } from "fs";
@@ -100659,6 +100675,8 @@ function runProxyLogin(onOutput, providerFlag) {
100659
100675
  }
100660
100676
  ensureConfig();
100661
100677
  const flag = providerFlag ?? "-claude-login";
100678
+ const prefix = PROXY_PROVIDERS.find((p) => p.flag === flag)?.prefix ?? "";
100679
+ const credSnapshot = snapshotProviderCreds(prefix);
100662
100680
  const proc = spawn4(binary2, ["-config", PROXY_CONFIG_PATH, flag], {
100663
100681
  stdio: ["ignore", "pipe", "pipe"]
100664
100682
  });
@@ -100678,12 +100696,20 @@ function runProxyLogin(onOutput, providerFlag) {
100678
100696
  proc.stderr?.on("data", handleData);
100679
100697
  const promise2 = new Promise((resolve6) => {
100680
100698
  proc.on("close", async (code) => {
100681
- if (code === 0) {
100682
- const result = await ensureProxy();
100683
- resolve6({ ok: result.ok });
100684
- } else {
100699
+ const authed = code === 0 && credsChangedSince(prefix, credSnapshot);
100700
+ if (!authed) {
100685
100701
  resolve6({ ok: false });
100702
+ return;
100703
+ }
100704
+ try {
100705
+ const healthy = await bounceProxy();
100706
+ if (!healthy) {
100707
+ onOutput("Credentials saved, but the proxy did not come back up. Run /proxy restart.");
100708
+ }
100709
+ } catch {
100710
+ onOutput("Credentials saved, but restarting the proxy failed. Run /proxy restart.");
100686
100711
  }
100712
+ resolve6({ ok: true });
100687
100713
  });
100688
100714
  proc.on("error", (err2) => {
100689
100715
  onOutput(`Login failed: ${err2.message}`);
@@ -100825,6 +100851,35 @@ function parseNetstatPidsForPort(out2, port) {
100825
100851
  }
100826
100852
  return pids;
100827
100853
  }
100854
+ function snapshotProviderCreds(prefix) {
100855
+ const snap = new Map;
100856
+ if (!prefix || !existsSync16(AUTH_DIR))
100857
+ return snap;
100858
+ for (const f of readdirSync4(AUTH_DIR)) {
100859
+ if (!f.startsWith(prefix) || !f.endsWith(".json"))
100860
+ continue;
100861
+ try {
100862
+ snap.set(f, statSync3(join19(AUTH_DIR, f)).mtimeMs);
100863
+ } catch {}
100864
+ }
100865
+ return snap;
100866
+ }
100867
+ function credsChangedSince(prefix, before) {
100868
+ if (!prefix || !existsSync16(AUTH_DIR))
100869
+ return false;
100870
+ for (const f of readdirSync4(AUTH_DIR)) {
100871
+ if (!f.startsWith(prefix) || !f.endsWith(".json"))
100872
+ continue;
100873
+ const prev = before.get(f);
100874
+ if (prev === undefined)
100875
+ return true;
100876
+ try {
100877
+ if (statSync3(join19(AUTH_DIR, f)).mtimeMs > prev)
100878
+ return true;
100879
+ } catch {}
100880
+ }
100881
+ return false;
100882
+ }
100828
100883
  var proxyProcess = null, PROXY_URL, PROXY_CONFIG_DIR, PROXY_CONFIG_PATH, HEALTH_TIMEOUT_MS = 2000, STARTUP_POLL_MS = 500, STARTUP_POLL_ATTEMPTS = 10, currentState = "stopped", lastError = null, stateListeners, VERSION_FILE, LEGACY_PERF_MARKER_PREFIX = "# soulforge-perf-defaults", bounceInFlight = null, PROXY_PROVIDERS, AUTH_DIR, cachedLatest = null, VERSION_CACHE_TTL;
100829
100884
  var init_lifecycle = __esm(() => {
100830
100885
  init_errors();
@@ -115417,7 +115472,7 @@ var init_checkpoints = __esm(() => {
115417
115472
  });
115418
115473
 
115419
115474
  // src/core/commands/utils.ts
115420
- import { existsSync as existsSync17, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
115475
+ import { existsSync as existsSync17, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
115421
115476
  import { homedir as homedir4 } from "os";
115422
115477
  import { join as join20 } from "path";
115423
115478
  function sysMsg(ctx, content) {
@@ -115445,7 +115500,7 @@ function dirSize(dirPath) {
115445
115500
  for (const entry of readdirSync5(dirPath)) {
115446
115501
  const fp = join20(dirPath, entry);
115447
115502
  try {
115448
- const s = statSync3(fp);
115503
+ const s = statSync4(fp);
115449
115504
  total += s.isDirectory() ? dirSize(fp) : s.size;
115450
115505
  } catch {}
115451
115506
  }
@@ -115453,7 +115508,7 @@ function dirSize(dirPath) {
115453
115508
  }
115454
115509
  function fileSize(filePath) {
115455
115510
  try {
115456
- return statSync3(filePath).size;
115511
+ return statSync4(filePath).size;
115457
115512
  } catch {
115458
115513
  return 0;
115459
115514
  }
@@ -134682,7 +134737,7 @@ ${lanes.join(`
134682
134737
  return process.memoryUsage().heapUsed;
134683
134738
  },
134684
134739
  getFileSize(path) {
134685
- const stat2 = statSync4(path);
134740
+ const stat2 = statSync5(path);
134686
134741
  if (stat2 == null ? undefined : stat2.isFile()) {
134687
134742
  return stat2.size;
134688
134743
  }
@@ -134725,7 +134780,7 @@ ${lanes.join(`
134725
134780
  }
134726
134781
  };
134727
134782
  return nodeSystem;
134728
- function statSync4(path) {
134783
+ function statSync5(path) {
134729
134784
  try {
134730
134785
  return _fs.statSync(path, statSyncOptions);
134731
134786
  } catch {
@@ -134777,7 +134832,7 @@ ${lanes.join(`
134777
134832
  activeSession.post("Profiler.stop", (err2, { profile }) => {
134778
134833
  var _a31;
134779
134834
  if (!err2) {
134780
- if ((_a31 = statSync4(profilePath)) == null ? undefined : _a31.isDirectory()) {
134835
+ if ((_a31 = statSync5(profilePath)) == null ? undefined : _a31.isDirectory()) {
134781
134836
  profilePath = _path.join(profilePath, `${(/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-")}+P${process.pid}.cpuprofile`);
134782
134837
  }
134783
134838
  try {
@@ -134886,7 +134941,7 @@ ${lanes.join(`
134886
134941
  let stat2;
134887
134942
  if (typeof dirent === "string" || dirent.isSymbolicLink()) {
134888
134943
  const name38 = combinePaths(path, entry);
134889
- stat2 = statSync4(name38);
134944
+ stat2 = statSync5(name38);
134890
134945
  if (!stat2) {
134891
134946
  continue;
134892
134947
  }
@@ -134910,7 +134965,7 @@ ${lanes.join(`
134910
134965
  return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames2, process.cwd(), depth, getAccessibleFileSystemEntries, realpath);
134911
134966
  }
134912
134967
  function fileSystemEntryExists(path, entryKind) {
134913
- const stat2 = statSync4(path);
134968
+ const stat2 = statSync5(path);
134914
134969
  if (!stat2) {
134915
134970
  return false;
134916
134971
  }
@@ -134944,7 +134999,7 @@ ${lanes.join(`
134944
134999
  }
134945
135000
  function getModifiedTime3(path) {
134946
135001
  var _a31;
134947
- return (_a31 = statSync4(path)) == null ? undefined : _a31.mtime;
135002
+ return (_a31 = statSync5(path)) == null ? undefined : _a31.mtime;
134948
135003
  }
134949
135004
  function setModifiedTime(path, time3) {
134950
135005
  try {
@@ -378118,7 +378173,7 @@ var init_trigram = __esm(() => {
378118
378173
 
378119
378174
  // src/core/intelligence/repo-map.ts
378120
378175
  import { Database } from "bun:sqlite";
378121
- import { chmodSync as chmodSync3, existsSync as existsSync25, readdirSync as readdirSync9, readFileSync as readFileSync17, statSync as statSync4 } from "fs";
378176
+ import { chmodSync as chmodSync3, existsSync as existsSync25, readdirSync as readdirSync9, readFileSync as readFileSync17, statSync as statSync5 } from "fs";
378122
378177
  import { stat as statAsync } from "fs/promises";
378123
378178
  import { dirname as dirname8, extname as extname2, join as join30, relative as relative4, resolve as resolve13 } from "path";
378124
378179
 
@@ -380193,7 +380248,7 @@ class RepoMap {
380193
380248
  for (const f of files) {
380194
380249
  const absPath = join30(this.cwd, f.path);
380195
380250
  try {
380196
- const st2 = statSync4(absPath);
380251
+ const st2 = statSync5(absPath);
380197
380252
  if (st2.mtimeMs !== f.mtime_ms || st2.size !== f.size_bytes) {
380198
380253
  this.onFileChanged(absPath);
380199
380254
  }
@@ -380698,7 +380753,7 @@ class RepoMap {
380698
380753
  continue;
380699
380754
  seenPaths.add(absPath);
380700
380755
  try {
380701
- const stat3 = statSync4(absPath);
380756
+ const stat3 = statSync5(absPath);
380702
380757
  if (Math.abs(stat3.mtimeMs - row.mtime_ms) > 1000)
380703
380758
  continue;
380704
380759
  } catch {
@@ -380788,7 +380843,7 @@ class RepoMap {
380788
380843
  seen.add(key);
380789
380844
  const absPath = join30(this.cwd, row.path);
380790
380845
  try {
380791
- const stat3 = statSync4(absPath);
380846
+ const stat3 = statSync5(absPath);
380792
380847
  if (Math.abs(stat3.mtimeMs - row.mtime_ms) > 1000)
380793
380848
  continue;
380794
380849
  } catch {
@@ -380842,7 +380897,7 @@ class RepoMap {
380842
380897
  for (const row of rows) {
380843
380898
  const absPath = join30(this.cwd, row.path);
380844
380899
  try {
380845
- const stat3 = statSync4(absPath);
380900
+ const stat3 = statSync5(absPath);
380846
380901
  if (Math.abs(stat3.mtimeMs - row.mtime_ms) > 1000)
380847
380902
  continue;
380848
380903
  } catch {
@@ -396346,7 +396401,7 @@ var init_clipboard2 = __esm(() => {
396346
396401
  import { MouseButton } from "@opentui/core";
396347
396402
  function useCopySelection() {
396348
396403
  const renderer = useRenderer();
396349
- const copySelection = import_react19.useCallback(() => {
396404
+ const copySelectionInner = import_react19.useCallback((clear) => {
396350
396405
  const sel = renderer.getSelection();
396351
396406
  if (!sel)
396352
396407
  return false;
@@ -396357,9 +396412,12 @@ function useCopySelection() {
396357
396412
  const clipboardText = focus?.getClipboardText && sel.selectedRenderables.includes(focus) ? focus.getClipboardText(text2) : text2;
396358
396413
  renderer.copyToClipboardOSC52(clipboardText);
396359
396414
  copyToClipboard2(clipboardText);
396360
- renderer.clearSelection();
396415
+ if (clear)
396416
+ renderer.clearSelection();
396361
396417
  return true;
396362
396418
  }, [renderer]);
396419
+ const copySelection = import_react19.useCallback(() => copySelectionInner(true), [copySelectionInner]);
396420
+ const copyOnSelect = import_react19.useCallback(() => copySelectionInner(false), [copySelectionInner]);
396363
396421
  const onMouseDown = import_react19.useCallback((evt) => {
396364
396422
  if (IS_WIN)
396365
396423
  return;
@@ -396370,7 +396428,7 @@ function useCopySelection() {
396370
396428
  evt.preventDefault();
396371
396429
  evt.stopPropagation();
396372
396430
  }, [copySelection]);
396373
- const onMouseUp = IS_WIN ? undefined : copySelection;
396431
+ const onMouseUp = IS_WIN ? undefined : copyOnSelect;
396374
396432
  return { copySelection, onMouseDown, onMouseUp };
396375
396433
  }
396376
396434
  var import_react19;
@@ -403002,6 +403060,8 @@ function matchPricing(modelId) {
403002
403060
  if (id.includes(key))
403003
403061
  return pricing;
403004
403062
  }
403063
+ if (id.includes("fable") || id.includes("mythos"))
403064
+ return MODEL_PRICING["claude-fable-5"] ?? DEFAULT_PRICING;
403005
403065
  if (id.includes("opus"))
403006
403066
  return MODEL_PRICING["claude-opus-4-8"] ?? DEFAULT_PRICING;
403007
403067
  if (id.includes("sonnet"))
@@ -403010,6 +403070,8 @@ function matchPricing(modelId) {
403010
403070
  return MODEL_PRICING["claude-haiku-4-5"] ?? DEFAULT_PRICING;
403011
403071
  if (id.includes("gemini"))
403012
403072
  return MODEL_PRICING["gemini-2.5-flash"] ?? DEFAULT_PRICING;
403073
+ if (id.includes("grok"))
403074
+ return MODEL_PRICING["grok-4.3"] ?? DEFAULT_PRICING;
403013
403075
  if (id.includes("gpt"))
403014
403076
  return MODEL_PRICING["gpt-5.4"] ?? DEFAULT_PRICING;
403015
403077
  if (id.includes("deepseek"))
@@ -403049,6 +403111,9 @@ function resetStatusBarStore() {
403049
403111
  memPollTimer = null;
403050
403112
  memPollStarted = false;
403051
403113
  }
403114
+ footprintCacheMB = null;
403115
+ footprintCacheAt = 0;
403116
+ footprintRefreshInFlight = false;
403052
403117
  useStatusBarStore.setState({
403053
403118
  tokenUsage: { ...ZERO_USAGE },
403054
403119
  activeModel: "none",
@@ -403140,8 +403205,24 @@ async function getMainFootprintMB() {
403140
403205
  const rssMB = Math.round(process.memoryUsage().rss / 1024 / 1024);
403141
403206
  if (process.platform !== "darwin")
403142
403207
  return rssMB;
403143
- const footprint = await macFootprintMB(process.pid);
403144
- return footprint ?? rssMB;
403208
+ const now2 = Date.now();
403209
+ if (footprintCacheMB === null || now2 - footprintCacheAt >= FOOTPRINT_TTL_MS) {
403210
+ refreshFootprintMB();
403211
+ }
403212
+ return footprintCacheMB ?? rssMB;
403213
+ }
403214
+ async function refreshFootprintMB() {
403215
+ if (footprintRefreshInFlight)
403216
+ return;
403217
+ footprintRefreshInFlight = true;
403218
+ try {
403219
+ const mb = await macFootprintMB(process.pid);
403220
+ footprintCacheAt = Date.now();
403221
+ if (mb != null)
403222
+ footprintCacheMB = mb;
403223
+ } finally {
403224
+ footprintRefreshInFlight = false;
403225
+ }
403145
403226
  }
403146
403227
  function macFootprintMB(pid) {
403147
403228
  return new Promise((resolve14) => {
@@ -403194,7 +403275,7 @@ function startMemoryPoll(intervalMs = 2000) {
403194
403275
  });
403195
403276
  }, intervalMs);
403196
403277
  }
403197
- var MODEL_PRICING, FREE_PRICING, DEFAULT_PRICING, FREE, M025, M033, M1, M3, M30, M75, COPILOT_PRICING, LOCAL_PROVIDERS, ZERO_USAGE, ZERO_PROCESS_RSS, useStatusBarStore, memPollStarted = false, memPollTimer = null;
403278
+ var MODEL_PRICING, FREE_PRICING, DEFAULT_PRICING, FREE, M025, M033, M1, M3, M30, M75, COPILOT_PRICING, LOCAL_PROVIDERS, ZERO_USAGE, ZERO_PROCESS_RSS, useStatusBarStore, FOOTPRINT_TTL_MS = 30000, footprintCacheMB = null, footprintCacheAt = 0, footprintRefreshInFlight = false, memPollStarted = false, memPollTimer = null;
403198
403279
  var init_statusbar = __esm(() => {
403199
403280
  init_esm();
403200
403281
  init_middleware();
@@ -403204,6 +403285,8 @@ var init_statusbar = __esm(() => {
403204
403285
  init_platform();
403205
403286
  init_lifecycle();
403206
403287
  MODEL_PRICING = {
403288
+ "claude-fable-5": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
403289
+ "claude-mythos-5": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
403207
403290
  "claude-opus-4-8": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
403208
403291
  "claude-opus-4-7": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
403209
403292
  "claude-opus-4-6": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
@@ -403239,10 +403322,10 @@ var init_statusbar = __esm(() => {
403239
403322
  "gemini-2.5-flash-lite": { input: 0.1, cacheWrite: 0.1, cacheRead: 0.01, output: 0.4 },
403240
403323
  "gemini-2.0-flash": { input: 0.1, cacheWrite: 0.1, cacheRead: 0.025, output: 0.4 },
403241
403324
  "gemini-2.0-flash-lite": { input: 0.075, cacheWrite: 0.075, cacheRead: 0.019, output: 0.3 },
403242
- "deepseek-v4-pro": { input: 1.74, cacheWrite: 1.74, cacheRead: 0.0145, output: 3.48 },
403243
- "deepseek-v4-flash": { input: 0.14, cacheWrite: 0.14, cacheRead: 0.014, output: 0.28 },
403244
- "deepseek-chat": { input: 0.14, cacheWrite: 0.14, cacheRead: 0.014, output: 0.28 },
403245
- "deepseek-reasoner": { input: 0.14, cacheWrite: 0.14, cacheRead: 0.014, output: 0.28 },
403325
+ "deepseek-v4-pro": { input: 0.435, cacheWrite: 0.435, cacheRead: 0.003625, output: 0.87 },
403326
+ "deepseek-v4-flash": { input: 0.14, cacheWrite: 0.14, cacheRead: 0.0028, output: 0.28 },
403327
+ "deepseek-chat": { input: 0.14, cacheWrite: 0.14, cacheRead: 0.0028, output: 0.28 },
403328
+ "deepseek-reasoner": { input: 0.14, cacheWrite: 0.14, cacheRead: 0.0028, output: 0.28 },
403246
403329
  "deepseek-v3": { input: 0.28, cacheWrite: 0.28, cacheRead: 0.028, output: 0.42 },
403247
403330
  "deepseek-r1": { input: 0.28, cacheWrite: 0.28, cacheRead: 0.028, output: 0.42 },
403248
403331
  "llama-3.3-70b": { input: 0.59, cacheWrite: 0.59, cacheRead: 0.295, output: 0.79 },
@@ -403251,9 +403334,17 @@ var init_statusbar = __esm(() => {
403251
403334
  "qwen3-32b": { input: 0.29, cacheWrite: 0.29, cacheRead: 0.145, output: 0.59 },
403252
403335
  "gpt-oss-20b": { input: 0.075, cacheWrite: 0.075, cacheRead: 0.0375, output: 0.3 },
403253
403336
  "gpt-oss-120b": { input: 0.15, cacheWrite: 0.15, cacheRead: 0.075, output: 0.6 },
403337
+ "grok-4.3": { input: 1.25, cacheWrite: 1.25, cacheRead: 0.2, output: 2.5 },
403338
+ "grok-4.20": { input: 1.25, cacheWrite: 1.25, cacheRead: 0.2, output: 2.5 },
403339
+ "grok-4.1-fast": { input: 0.2, cacheWrite: 0.2, cacheRead: 0.05, output: 0.5 },
403340
+ "grok-4-fast": { input: 0.2, cacheWrite: 0.2, cacheRead: 0.05, output: 0.5 },
403341
+ "grok-code-fast": { input: 0.2, cacheWrite: 0.2, cacheRead: 0.02, output: 1.5 },
403342
+ "grok-4": { input: 3, cacheWrite: 3, cacheRead: 0.75, output: 15 },
403343
+ "grok-3": { input: 3, cacheWrite: 3, cacheRead: 0.75, output: 15 },
403344
+ "grok-3-mini": { input: 0.3, cacheWrite: 0.3, cacheRead: 0.075, output: 0.5 },
403254
403345
  "mistral-large": { input: 0.5, cacheWrite: 0.5, cacheRead: 0.05, output: 1.5 },
403255
- "mistral-medium": { input: 0.4, cacheWrite: 0.4, cacheRead: 0.04, output: 2 },
403256
- "mistral-small": { input: 0.1, cacheWrite: 0.1, cacheRead: 0.01, output: 0.3 },
403346
+ "mistral-medium": { input: 1.5, cacheWrite: 1.5, cacheRead: 0.15, output: 7.5 },
403347
+ "mistral-small": { input: 0.15, cacheWrite: 0.15, cacheRead: 0.015, output: 0.6 },
403257
403348
  codestral: { input: 0.3, cacheWrite: 0.3, cacheRead: 0.03, output: 0.9 },
403258
403349
  magistral: { input: 0.5, cacheWrite: 0.5, cacheRead: 0.05, output: 1.5 },
403259
403350
  ministral: { input: 0.1, cacheWrite: 0.1, cacheRead: 0.01, output: 0.1 },
@@ -403644,7 +403735,9 @@ var exports_telemetry = {};
403644
403735
  __export(exports_telemetry, {
403645
403736
  telemetryDisabled: () => telemetryDisabled,
403646
403737
  sendBeacon: () => sendBeacon,
403647
- maybeShowTelemetryNotice: () => maybeShowTelemetryNotice
403738
+ maybeShowTelemetryNotice: () => maybeShowTelemetryNotice,
403739
+ detectTerminalBucket: () => detectTerminalBucket,
403740
+ detectRuntime: () => detectRuntime
403648
403741
  });
403649
403742
  import { randomUUID as randomUUID3 } from "crypto";
403650
403743
  import { existsSync as existsSync36, mkdirSync as mkdirSync20, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "fs";
@@ -403707,6 +403800,33 @@ function normArch() {
403707
403800
  return "x64";
403708
403801
  return "other";
403709
403802
  }
403803
+ function detectTerminalBucket() {
403804
+ const term = process.env.TERM_PROGRAM?.toLowerCase() ?? "";
403805
+ if (process.env.KITTY_WINDOW_ID || term === "kitty")
403806
+ return "kitty";
403807
+ if (term === "ghostty")
403808
+ return "ghostty";
403809
+ if (process.env.ITERM_SESSION_ID || term === "iterm.app" || term === "iterm2")
403810
+ return "iterm";
403811
+ if (term === "vscode")
403812
+ return "vscode";
403813
+ if (process.env.WEZTERM_PANE !== undefined || term === "wezterm")
403814
+ return "wezterm";
403815
+ if (term === "warp")
403816
+ return "warp";
403817
+ if (process.env.TMUX)
403818
+ return "tmux";
403819
+ return "other";
403820
+ }
403821
+ function detectRuntime() {
403822
+ const bun = process.versions.bun;
403823
+ if (bun)
403824
+ return `bun-${bun.split(".")[0]}`;
403825
+ const node = process.versions.node;
403826
+ if (node)
403827
+ return `node-${node.split(".")[0]}`;
403828
+ return "other";
403829
+ }
403710
403830
  function sendBeacon(fields, configEnabled) {
403711
403831
  if (telemetryDisabled(configEnabled))
403712
403832
  return;
@@ -403726,7 +403846,15 @@ function sendBeacon(fields, configEnabled) {
403726
403846
  if (fields.provider)
403727
403847
  params.set("pv", fields.provider.slice(0, 24));
403728
403848
  if (fields.model)
403729
- params.set("md", fields.model.slice(0, 32));
403849
+ params.set("md", fields.model.slice(0, 40));
403850
+ if (fields.mode)
403851
+ params.set("mo", fields.mode.slice(0, 16));
403852
+ if (fields.terminal)
403853
+ params.set("tm", fields.terminal.slice(0, 16));
403854
+ if (fields.runtime)
403855
+ params.set("rt", fields.runtime.slice(0, 16));
403856
+ if (fields.repomap)
403857
+ params.set("rm", fields.repomap.slice(0, 8));
403730
403858
  const url2 = `${endpoint()}?${params.toString()}`;
403731
403859
  fetch(url2, {
403732
403860
  method: "GET",
@@ -404079,7 +404207,7 @@ async function start2(opts) {
404079
404207
  }
404080
404208
  }
404081
404209
  try {
404082
- const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
404210
+ const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2, detectTerminalBucket: detectTerminalBucket2, detectRuntime: detectRuntime2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
404083
404211
  const { detectModelFamily: detectModelFamily2, telemetryModelInfo } = await Promise.resolve().then(() => (init_provider_options(), exports_provider_options));
404084
404212
  const { CURRENT_VERSION: CURRENT_VERSION2, detectInstallMethod: detectInstallMethod2 } = await Promise.resolve().then(() => (init_version(), exports_version));
404085
404213
  const { loadConfig: loadConfig2, saveGlobalConfig: saveGlobalConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config2));
@@ -404093,7 +404221,11 @@ async function start2(opts) {
404093
404221
  install: detectInstallMethod2(),
404094
404222
  family: hasModel ? detectModelFamily2(cfg.defaultModel) : undefined,
404095
404223
  provider: info2?.provider,
404096
- model: info2?.model
404224
+ model: info2?.model,
404225
+ mode: cfg.defaultForgeMode ?? "default",
404226
+ terminal: detectTerminalBucket2(),
404227
+ runtime: detectRuntime2(),
404228
+ repomap: process.env.SOULFORGE_NO_REPOMAP === "1" ? "skipped" : "on"
404097
404229
  }, cfg.telemetry);
404098
404230
  } catch {}
404099
404231
  opts.createRoot(r).render(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AppRoot, {
@@ -412602,9 +412734,9 @@ function telemetryModelInfo(modelId) {
412602
412734
  const rawProvider = slash >= 0 ? modelId.slice(0, slash) : "";
412603
412735
  const builtin = isBuiltinProvider(rawProvider);
412604
412736
  const provider = builtin ? rawProvider : "custom";
412605
- const base = extractBaseModel2(modelId);
412606
- const known = builtin && TELEMETRY_MODEL_PATTERNS.some((re) => re.test(base));
412607
- const model = known ? base.slice(0, 32) : "other";
412737
+ const raw = (slash >= 0 ? modelId.slice(slash + 1) : modelId).toLowerCase();
412738
+ const known = builtin && raw.length <= 40 && TELEMETRY_MODEL_SLUG.test(raw);
412739
+ const model = known ? raw : "other";
412608
412740
  return { provider, model };
412609
412741
  }
412610
412742
  function getSupportedClaudeEfforts(modelId) {
@@ -413087,7 +413219,7 @@ function buildGroqOptions(config2) {
413087
413219
  function isDeepSeekReasoner(base) {
413088
413220
  return base === "deepseek-reasoner" || base.includes("reasoner") || base.endsWith("-think");
413089
413221
  }
413090
- var parseOpusVersion2, isAdaptiveOnly2, extractBaseModel2, getModelId2, supportsTemperature2, NO_SUPPORT, ANTHROPIC_FULL, OPENAI_FULL, GOOGLE_FULL, XAI_FULL, DEEPSEEK_FULL, OPENROUTER_FULL, GATEWAY_FULL, COMPAT_ONLY, PROVIDER_CONSTRAINTS, LEGACY_PREFIXES, TELEMETRY_MODEL_PATTERNS, CACHE_EPHEMERAL_5M, CACHE_EPHEMERAL_1H, EPHEMERAL_CACHE_5M, EPHEMERAL_CACHE_1H, EPHEMERAL_CACHE;
413222
+ var parseOpusVersion2, isAdaptiveOnly2, extractBaseModel2, getModelId2, supportsTemperature2, NO_SUPPORT, ANTHROPIC_FULL, OPENAI_FULL, GOOGLE_FULL, XAI_FULL, DEEPSEEK_FULL, OPENROUTER_FULL, GATEWAY_FULL, COMPAT_ONLY, PROVIDER_CONSTRAINTS, LEGACY_PREFIXES, TELEMETRY_MODEL_SLUG, CACHE_EPHEMERAL_5M, CACHE_EPHEMERAL_1H, EPHEMERAL_CACHE_5M, EPHEMERAL_CACHE_1H, EPHEMERAL_CACHE;
413091
413223
  var init_provider_options = __esm(() => {
413092
413224
  init_models();
413093
413225
  init_providers();
@@ -413206,14 +413338,7 @@ var init_provider_options = __esm(() => {
413206
413338
  "claude-2",
413207
413339
  "claude-instant"
413208
413340
  ];
413209
- TELEMETRY_MODEL_PATTERNS = [
413210
- /^claude-[a-z]+-\d+(?:[.-]\d+)?(?:-\d{8})?$/,
413211
- /^gpt-[a-z0-9.]+(?:-[a-z0-9.]+)?$/,
413212
- /^o[1-9](?:-[a-z]+)?$/,
413213
- /^gemini-[0-9.]+-[a-z]+(?:-[a-z0-9]+)?$/,
413214
- /^grok-[0-9]+(?:-[a-z]+)?$/,
413215
- /^deepseek-[a-z]+(?:-[a-z0-9]+)?$/
413216
- ];
413341
+ TELEMETRY_MODEL_SLUG = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){0,5}$/;
413217
413342
  CACHE_EPHEMERAL_5M = {
413218
413343
  cacheControl: { type: "ephemeral", ttl: "5m" }
413219
413344
  };
@@ -415103,7 +415228,7 @@ var init_approval_gates = __esm(() => {
415103
415228
  });
415104
415229
 
415105
415230
  // src/core/utils/path-display.ts
415106
- import { realpathSync as realpathSync3, statSync as statSync5 } from "fs";
415231
+ import { realpathSync as realpathSync3, statSync as statSync6 } from "fs";
415107
415232
  import { homedir as homedir11, platform as platform4 } from "os";
415108
415233
  import { isAbsolute, relative as relative5, resolve as resolve15, sep as sep2 } from "path";
415109
415234
  function canonicalizePath(p) {
@@ -435297,7 +435422,7 @@ function isTextWithEncodingHint(fileBuffer, bytesRead, encoding) {
435297
435422
  var MAX_BYTES = 512;
435298
435423
 
435299
435424
  // node_modules/isbinaryfile/lib/index.js
435300
- import { statSync as statSync6, openSync, readSync, closeSync } from "fs";
435425
+ import { statSync as statSync7, openSync, readSync, closeSync } from "fs";
435301
435426
  import { open, stat as stat4 } from "fs/promises";
435302
435427
 
435303
435428
  class Reader {
@@ -435406,7 +435531,7 @@ async function isBinaryFile(file2, options) {
435406
435531
  }
435407
435532
  function isBinaryFileSync(file2, options) {
435408
435533
  if (isString(file2)) {
435409
- const fileStat = statSync6(file2);
435534
+ const fileStat = statSync7(file2);
435410
435535
  isStatFile(fileStat);
435411
435536
  const fileDescriptor = openSync(file2, "r");
435412
435537
  const allocBuffer = Buffer.alloc(MAX_BYTES2 + UTF8_BOUNDARY_RESERVE);
@@ -435501,7 +435626,7 @@ var MAX_BYTES2 = 512, UTF8_BOUNDARY_RESERVE = 3;
435501
435626
  var init_lib2 = () => {};
435502
435627
 
435503
435628
  // src/core/tools/binary-detect.ts
435504
- import { existsSync as existsSync41, statSync as statSync7 } from "fs";
435629
+ import { existsSync as existsSync41, statSync as statSync8 } from "fs";
435505
435630
  import { extname as extname3, resolve as resolve28 } from "path";
435506
435631
  function binaryHint(ext) {
435507
435632
  if (IMAGE_EXTS.has(ext))
@@ -435524,7 +435649,7 @@ function checkBinaryFile(filePath) {
435524
435649
  try {
435525
435650
  if (!existsSync41(filePath))
435526
435651
  return null;
435527
- const stat5 = statSync7(filePath);
435652
+ const stat5 = statSync8(filePath);
435528
435653
  if (!stat5.isFile())
435529
435654
  return null;
435530
435655
  if (!isBinaryFileSync(filePath))
@@ -437511,7 +437636,7 @@ import {
437511
437636
  existsSync as existsSync42,
437512
437637
  openSync as openSync2,
437513
437638
  readFileSync as readFileSync22,
437514
- statSync as statSync8,
437639
+ statSync as statSync9,
437515
437640
  unlinkSync as unlinkSync8,
437516
437641
  writeSync
437517
437642
  } from "fs";
@@ -437576,7 +437701,7 @@ function isRenderableImage(filePath) {
437576
437701
  if (!IMAGE_EXTENSIONS2.has(ext))
437577
437702
  return false;
437578
437703
  try {
437579
- const stat5 = statSync8(filePath);
437704
+ const stat5 = statSync9(filePath);
437580
437705
  return stat5.isFile() && stat5.size > 0 && stat5.size <= MAX_IMAGE_SIZE;
437581
437706
  } catch {
437582
437707
  return false;
@@ -438017,7 +438142,7 @@ import {
438017
438142
  existsSync as existsSync43,
438018
438143
  readdirSync as readdirSync10,
438019
438144
  readFileSync as readFileSync23,
438020
- statSync as statSync9,
438145
+ statSync as statSync10,
438021
438146
  unlinkSync as unlinkSync9,
438022
438147
  writeFileSync as writeFileSync18
438023
438148
  } from "fs";
@@ -438628,7 +438753,7 @@ async function showImage(args2, cwd2, toolCallId, signal) {
438628
438753
  const filePath = resolve34(cwd2, args2.path);
438629
438754
  let stat5;
438630
438755
  try {
438631
- stat5 = statSync9(filePath);
438756
+ stat5 = statSync10(filePath);
438632
438757
  } catch {
438633
438758
  return { success: false, output: `File not found: ${args2.path}` };
438634
438759
  }
@@ -438770,7 +438895,7 @@ async function restoreSessionImages(messages, cwd2) {
438770
438895
  const filePath = resolve34(cwd2, path);
438771
438896
  if (!existsSync43(filePath))
438772
438897
  continue;
438773
- const stat5 = statSync9(filePath);
438898
+ const stat5 = statSync10(filePath);
438774
438899
  if (!stat5.isFile() || stat5.size > MAX_IMAGE_SIZE2)
438775
438900
  continue;
438776
438901
  data = readFileSync23(filePath);
@@ -438860,7 +438985,7 @@ var init_show_image = __esm(() => {
438860
438985
  });
438861
438986
 
438862
438987
  // src/core/skills/manager.ts
438863
- import { existsSync as existsSync44, readdirSync as readdirSync11, readFileSync as readFileSync24, realpathSync as realpathSync4, rmSync as rmSync6, statSync as statSync10 } from "fs";
438988
+ import { existsSync as existsSync44, readdirSync as readdirSync11, readFileSync as readFileSync24, realpathSync as realpathSync4, rmSync as rmSync6, statSync as statSync11 } from "fs";
438864
438989
  import { homedir as homedir13 } from "os";
438865
438990
  import { dirname as dirname22, join as join47 } from "path";
438866
438991
  async function searchSkills(query2) {
@@ -438974,7 +439099,7 @@ function scanSkillDir(dir, scope, byName, seenPaths) {
438974
439099
  }
438975
439100
  function isDirectorySafe(path) {
438976
439101
  try {
438977
- return statSync10(path).isDirectory();
439102
+ return statSync11(path).isDirectory();
438978
439103
  } catch {
438979
439104
  return false;
438980
439105
  }
@@ -447257,14 +447382,13 @@ What each part means:
447257
447382
  - + before a symbol = exported (part of the public API)
447258
447383
  - \u2190 arrows = "imported by" \u2014 shows which files depend on this one
447259
447384
  - Signatures show function/type shapes so you can understand APIs without reading files
447260
- - Key dependencies section shows external packages and how widely they're used`, SOUL_MAP_USAGE = `This map answers most structural questions directly:
447261
- - "Where is X?" \u2192 find the file and line in the map
447262
- - "What does file Y export?" \u2192 listed under that file
447263
- - "What depends on Z?" \u2192 check the \u2190 arrows and blast radius
447264
- - "What packages does this project use?" \u2192 Key dependencies section
447265
-
447266
- For deeper questions, feed symbol names from the map into navigate() or analyze().
447267
- The map gives you the names, LSP gives you the details.`, LEGEND = `+ = exported. (\u2192N) = blast radius. [NEW] = modified in last 48h.
447385
+ - Key dependencies section shows external packages and how widely they're used`, SOUL_MAP_USAGE = `This map is a ranked, truncated index \u2014 an orientation layer, not the codebase. It surfaces the highest-impact files and exports; lower-ranked symbols, bodies, and whole files are cut (see "+N more", "... (N more)"). Use it to locate, not to conclude.
447386
+
447387
+ - "Where is X?" \u2192 the map points you at a file + line to confirm with a read/navigate.
447388
+ - "What does Y export?" \u2192 a starting list; verify before asserting the full surface.
447389
+ - "What depends on Z?" \u2192 (\u2192N) and \u2190 arrows orient blast radius; soul_impact confirms it.
447390
+
447391
+ Absence from the map is NOT absence from the codebase \u2014 a missing symbol may be ranked out, not nonexistent. Before stating any claim about how the code behaves, confirm it with a soul tool (soul_grep() / soul_find() / navigate() / read()). The map tells you where to look; the tools tell you what's true. Reason from the snapshot, answer from the tools.`, LEGEND = `+ = exported. (\u2192N) = blast radius. [NEW] = modified in last 48h.
447268
447392
  `, DIR_TREE_DEPTH = 2, DIR_TREE_TTL_MS = 60000, dirTreeCache;
447269
447393
  var init_soul_map = __esm(() => {
447270
447394
  init_file_tree();
@@ -447273,7 +447397,7 @@ var init_soul_map = __esm(() => {
447273
447397
 
447274
447398
  // src/core/prompts/shared/tool-guidance.ts
447275
447399
  var TOOL_GUIDANCE_WITH_MAP = `<tool_usage>
447276
- A Soul Map is loaded in context \u2014 every file, exported symbol, signature, line number, dependency edge. It is your first source of truth; tools retrieve just-in-time what the map does not already answer.
447400
+ A Soul Map is loaded in context \u2014 a ranked, truncated index of the codebase (files, exported symbols, signatures, line numbers, dependency edges). It is your orientation layer, not ground truth: it surfaces the highest-impact symbols and cuts the rest ("+N more", "... (N more)"). Use it to find where to look \u2014 then confirm with a soul tool before asserting anything about how the code behaves. Absence from the map \u2260 absence from the codebase. The snapshot exists to keep context cheap (no full-map dump); the tools, not the snapshot, are what ground your answers.
447277
447401
 
447278
447402
  <workflow>
447279
447403
  PLAN from the map (zero tool calls) \u2192 DISCOVER in parallel (soul_find/soul_grep/navigate) only when the map does not answer \u2192 READ in one parallel batch with Soul Map line numbers \u2192 EDIT (ast_edit for TS/JS, structural_edit for other languages, multi_edit for config/raw text) \u2192 VERIFY with project (typecheck/lint/test). Commit to the plan. Skip re-reads of files you have.
@@ -447281,7 +447405,7 @@ When one discovery needs the output of the previous (search \u2192 filter \u2192
447281
447405
  </workflow>
447282
447406
 
447283
447407
  <soul_map_usage>
447284
- The map answers structural questions for free: "Where is X?" \u2192 file + line. "What does Y export?" \u2192 listed under the file. "What depends on Z?" \u2192 (\u2192N) blast radius + \u2190 arrows. "What packages?" \u2192 Key dependencies section. Feed symbol names into navigate/analyze for bodies.
447408
+ The map orients structural questions cheaply: "Where is X?" \u2192 a file + line to confirm. "What does Y export?" \u2192 a partial list (truncated \u2014 verify). "What depends on Z?" \u2192 (\u2192N) + \u2190 arrows, confirmed by soul_impact. "What packages?" \u2192 Key dependencies. Feed symbol names into navigate/analyze for bodies. A vague request has no built-in anchor \u2014 that's exactly when to fire a soul tool first rather than answer off the snapshot. Never quote the map as fact; quote what a tool returned.
447285
447409
  </soul_map_usage>
447286
447410
 
447287
447411
  <soul_map_updates>
@@ -467072,7 +467196,7 @@ async function setupAgent(opts, merged) {
467072
467196
  }
467073
467197
  const providerOpts = await buildProviderOptions(modelId, merged);
467074
467198
  try {
467075
- const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
467199
+ const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2, detectRuntime: detectRuntime2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
467076
467200
  const { detectModelFamily: detectModelFamily2, telemetryModelInfo: telemetryModelInfo2 } = await Promise.resolve().then(() => (init_provider_options(), exports_provider_options));
467077
467201
  const { CURRENT_VERSION: CURRENT_VERSION2, detectInstallMethod: detectInstallMethod2 } = await Promise.resolve().then(() => (init_version(), exports_version));
467078
467202
  const { saveGlobalConfig: saveGlobalConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config2));
@@ -467084,7 +467208,10 @@ async function setupAgent(opts, merged) {
467084
467208
  install: detectInstallMethod2(),
467085
467209
  family: detectModelFamily2(modelId),
467086
467210
  provider: info2.provider,
467087
- model: info2.model
467211
+ model: info2.model,
467212
+ mode: opts.mode,
467213
+ runtime: detectRuntime2(),
467214
+ repomap: merged.repoMap === false || opts.noRepomap || process.env.SOULFORGE_NO_REPOMAP === "1" ? "skipped" : "on"
467088
467215
  }, merged.telemetry);
467089
467216
  } catch {}
467090
467217
  const repoMapDisabled = merged.repoMap === false || opts.noRepomap || process.env.SOULFORGE_NO_REPOMAP === "1";
@@ -468224,10 +468351,15 @@ class HearthDaemon {
468224
468351
  }
468225
468352
  await this.startSocket();
468226
468353
  try {
468227
- const { sendBeacon: sendBeacon2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
468354
+ const { sendBeacon: sendBeacon2, detectRuntime: detectRuntime2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
468228
468355
  const { CURRENT_VERSION: CURRENT_VERSION2, detectInstallMethod: detectInstallMethod2 } = await Promise.resolve().then(() => (init_version(), exports_version));
468229
468356
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config2));
468230
- sendBeacon2({ surface: "hearth", version: CURRENT_VERSION2, install: detectInstallMethod2() }, loadConfig2().telemetry);
468357
+ sendBeacon2({
468358
+ surface: "hearth",
468359
+ version: CURRENT_VERSION2,
468360
+ install: detectInstallMethod2(),
468361
+ runtime: detectRuntime2()
468362
+ }, loadConfig2().telemetry);
468231
468363
  } catch {}
468232
468364
  const tuiOwner = readBridgeOwner();
468233
468365
  this.tuiOwnerPid = tuiOwner && tuiOwner !== process.pid ? tuiOwner : null;
@@ -470231,7 +470363,7 @@ var init_headless = __esm(() => {
470231
470363
  });
470232
470364
 
470233
470365
  // src/core/presets/registry.ts
470234
- import { existsSync as existsSync54, mkdirSync as mkdirSync25, readFileSync as readFileSync29, statSync as statSync11, writeFileSync as writeFileSync21 } from "fs";
470366
+ import { existsSync as existsSync54, mkdirSync as mkdirSync25, readFileSync as readFileSync29, statSync as statSync12, writeFileSync as writeFileSync21 } from "fs";
470235
470367
  import { join as join56 } from "path";
470236
470368
  function getCacheDirInternal() {
470237
470369
  return join56(configDir(), "presets");
@@ -470259,7 +470391,7 @@ function cacheAge() {
470259
470391
  if (!existsSync54(file2))
470260
470392
  return Number.POSITIVE_INFINITY;
470261
470393
  try {
470262
- return Date.now() - statSync11(file2).mtimeMs;
470394
+ return Date.now() - statSync12(file2).mtimeMs;
470263
470395
  } catch {
470264
470396
  return Number.POSITIVE_INFINITY;
470265
470397
  }
@@ -486969,6 +487101,10 @@ function useTextDrip(fullText, streaming) {
486969
487101
  const delta = fullText.length - prevLenRef.current;
486970
487102
  if (delta > 0) {
486971
487103
  bufferRef.current += delta;
487104
+ } else if (delta < 0) {
487105
+ bufferRef.current = fullText.length;
487106
+ velocityRef.current = MIN_SPEED;
487107
+ setDrip({ revealed: 0, fresh: 0 });
486972
487108
  }
486973
487109
  prevLenRef.current = fullText.length;
486974
487110
  }, [fullText]);
@@ -487097,7 +487233,7 @@ function DripText({ content, streaming }) {
487097
487233
  opacity,
487098
487234
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Markdown, {
487099
487235
  text: `${display}${cursor}`,
487100
- streaming: true
487236
+ streaming
487101
487237
  }, undefined, false, undefined, this)
487102
487238
  }, undefined, false, undefined, this);
487103
487239
  }
@@ -502346,7 +502482,7 @@ var init_hearth2 = __esm(() => {
502346
502482
 
502347
502483
  // src/components/settings/HearthSettings.tsx
502348
502484
  import { spawn as spawn22 } from "child_process";
502349
- import { appendFileSync as appendFileSync5, existsSync as existsSync59, readFileSync as readFileSync33, statSync as statSync12, watch as watch3 } from "fs";
502485
+ import { appendFileSync as appendFileSync5, existsSync as existsSync59, readFileSync as readFileSync33, statSync as statSync13, watch as watch3 } from "fs";
502350
502486
  import { tmpdir as tmpdir6 } from "os";
502351
502487
  import { delimiter as delimiter2, dirname as dirname25, join as join64, resolve as resolve45 } from "path";
502352
502488
  import { decodePasteBytes as decodePasteBytes6, TextAttributes as TextAttributes27 } from "@opentui/core";
@@ -505446,7 +505582,7 @@ function findSourceCheckout(startPath) {
505446
505582
  }
505447
505583
  function isExecutable(p3) {
505448
505584
  try {
505449
- const st4 = statSync12(p3);
505585
+ const st4 = statSync13(p3);
505450
505586
  if (!st4.isFile())
505451
505587
  return false;
505452
505588
  if (IS_WIN)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proxysoul/soulforge",
3
- "version": "2.20.8",
3
+ "version": "2.20.10",
4
4
  "description": "Graph-powered code intelligence — multi-agent coding with codebase-aware AI",
5
5
  "repository": {
6
6
  "type": "git",