@proxysoul/soulforge 2.15.2 → 2.15.4

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
@@ -62500,7 +62500,7 @@ var package_default;
62500
62500
  var init_package = __esm(() => {
62501
62501
  package_default = {
62502
62502
  name: "@proxysoul/soulforge",
62503
- version: "2.15.2",
62503
+ version: "2.15.4",
62504
62504
  description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
62505
62505
  repository: {
62506
62506
  type: "git",
@@ -62521,7 +62521,7 @@ var init_package = __esm(() => {
62521
62521
  "soulforge-remote": "./dist/soulforge-remote.sh"
62522
62522
  },
62523
62523
  engines: {
62524
- bun: ">=1.2.0"
62524
+ bun: ">=1.3.13"
62525
62525
  },
62526
62526
  files: [
62527
62527
  "dist",
@@ -477974,24 +477974,170 @@ Reopen the editor (Ctrl+E twice) for changes to take effect.`);
477974
477974
  }
477975
477975
  function handleTimeouts(_input, ctx) {
477976
477976
  const cfg = loadConfig();
477977
- const current = cfg.toolTimeout ?? 2;
477978
- const options = [
477979
- { value: "1", label: "1 min" },
477980
- { value: "2", label: "2 min", description: "default" },
477981
- { value: "5", label: "5 min" },
477982
- { value: "10", label: "10 min" },
477983
- { value: "20", label: "20 min" },
477984
- { value: "0", label: "No timeout", description: "tools run until completion" }
477985
- ];
477977
+ const currentToolTimeout = cfg.toolTimeout ?? 2;
477978
+ const watchdogEnabled = cfg.watchdog ?? false;
477979
+ const wd = cfg.watchdogTimeouts ?? {};
477980
+ const currentTool = `tool:${currentToolTimeout}`;
477981
+ const wdFirstSec = (wd.firstChunkMs ?? 180000) / 1000;
477982
+ const wdChunkSec = (wd.chunkMs ?? 120000) / 1000;
477983
+ const wdToolSec = (wd.toolMaxMs ?? 900000) / 1000;
477984
+ const wdForceSec = (wd.forceResolveMs ?? 5000) / 1000;
477985
+ const wdFirst = `wd-first:${wdFirstSec}`;
477986
+ const wdChunk = `wd-chunk:${wdChunkSec}`;
477987
+ const wdTool = `wd-tool:${wdToolSec}`;
477988
+ const wdForce = `wd-force:${wdForceSec}`;
477989
+ const timeoutPickers = {
477990
+ "tool-timeout": (_input2, ctx2) => {
477991
+ ctx2.openCommandPicker({
477992
+ title: "Tool Timeout",
477993
+ icon: icon("clock"),
477994
+ currentValue: currentTool,
477995
+ scopeEnabled: false,
477996
+ options: [
477997
+ { value: "tool:1", label: "1 min" },
477998
+ { value: "tool:2", label: "2 min", description: "default" },
477999
+ { value: "tool:5", label: "5 min" },
478000
+ { value: "tool:10", label: "10 min" },
478001
+ { value: "tool:20", label: "20 min" },
478002
+ { value: "tool:0", label: "No timeout", description: "tools run until completion" }
478003
+ ],
478004
+ onSelect: (value) => {
478005
+ const timeout = Number(value.split(":")[1]);
478006
+ ctx2.saveToScope({ toolTimeout: timeout }, "global");
478007
+ sysMsg(ctx2, `Tool timeout \u2192 ${timeout === 0 ? "none" : `${timeout}m`} (global)`);
478008
+ }
478009
+ });
478010
+ },
478011
+ "watchdog-toggle": (_input2, ctx2) => {
478012
+ ctx2.openCommandPicker({
478013
+ title: "Watchdog",
478014
+ icon: icon("clock"),
478015
+ currentValue: watchdogEnabled ? "watchdog:on" : "watchdog:off",
478016
+ scopeEnabled: false,
478017
+ options: [
478018
+ {
478019
+ value: "watchdog:on",
478020
+ label: "Watchdog: On",
478021
+ description: "enable auto-retry on stalls"
478022
+ },
478023
+ {
478024
+ value: "watchdog:off",
478025
+ label: "Watchdog: Off",
478026
+ description: "disable auto-retry on stalls"
478027
+ }
478028
+ ],
478029
+ onSelect: (value) => {
478030
+ const enabled = value === "watchdog:on";
478031
+ ctx2.saveToScope({ watchdog: enabled }, "global");
478032
+ sysMsg(ctx2, `Watchdog ${enabled ? "enabled" : "disabled"} (global)`);
478033
+ }
478034
+ });
478035
+ },
478036
+ "wd-first": (_input2, ctx2) => {
478037
+ ctx2.openCommandPicker({
478038
+ title: "Watchdog \u2014 First Chunk Timeout",
478039
+ icon: icon("clock"),
478040
+ currentValue: wdFirst,
478041
+ scopeEnabled: false,
478042
+ options: [
478043
+ { value: "wd-first:5", label: "5s" },
478044
+ { value: "wd-first:15", label: "15s" },
478045
+ { value: "wd-first:30", label: "30s" },
478046
+ { value: "wd-first:60", label: "60s" },
478047
+ { value: "wd-first:120", label: "120s" },
478048
+ { value: "wd-first:180", label: "180s", description: "default" }
478049
+ ],
478050
+ onSelect: (value) => {
478051
+ const sec = Number(value.split(":")[1]);
478052
+ ctx2.saveToScope({ watchdogTimeouts: { ...wd, firstChunkMs: sec * 1000 } }, "global");
478053
+ sysMsg(ctx2, `Watchdog first-chunk timeout \u2192 ${sec}s (global)`);
478054
+ }
478055
+ });
478056
+ },
478057
+ "wd-chunk": (_input2, ctx2) => {
478058
+ ctx2.openCommandPicker({
478059
+ title: "Watchdog \u2014 Chunk Timeout",
478060
+ icon: icon("clock"),
478061
+ currentValue: wdChunk,
478062
+ scopeEnabled: false,
478063
+ options: [
478064
+ { value: "wd-chunk:5", label: "5s" },
478065
+ { value: "wd-chunk:15", label: "15s" },
478066
+ { value: "wd-chunk:30", label: "30s" },
478067
+ { value: "wd-chunk:60", label: "60s" },
478068
+ { value: "wd-chunk:120", label: "120s", description: "default" },
478069
+ { value: "wd-chunk:180", label: "180s" }
478070
+ ],
478071
+ onSelect: (value) => {
478072
+ const sec = Number(value.split(":")[1]);
478073
+ ctx2.saveToScope({ watchdogTimeouts: { ...wd, chunkMs: sec * 1000 } }, "global");
478074
+ sysMsg(ctx2, `Watchdog chunk timeout \u2192 ${sec}s (global)`);
478075
+ }
478076
+ });
478077
+ },
478078
+ "wd-tool": (_input2, ctx2) => {
478079
+ ctx2.openCommandPicker({
478080
+ title: "Watchdog \u2014 Tool Max Timeout",
478081
+ icon: icon("clock"),
478082
+ currentValue: wdTool,
478083
+ scopeEnabled: false,
478084
+ options: [
478085
+ { value: "wd-tool:60", label: "1 min" },
478086
+ { value: "wd-tool:300", label: "5 min" },
478087
+ { value: "wd-tool:600", label: "10 min" },
478088
+ { value: "wd-tool:900", label: "15 min", description: "default" },
478089
+ { value: "wd-tool:1800", label: "30 min" },
478090
+ { value: "wd-tool:3600", label: "60 min" }
478091
+ ],
478092
+ onSelect: (value) => {
478093
+ const sec = Number(value.split(":")[1]);
478094
+ ctx2.saveToScope({ watchdogTimeouts: { ...wd, toolMaxMs: sec * 1000 } }, "global");
478095
+ sysMsg(ctx2, `Watchdog tool-max timeout \u2192 ${sec}s (global)`);
478096
+ }
478097
+ });
478098
+ },
478099
+ "wd-force": (_input2, ctx2) => {
478100
+ ctx2.openCommandPicker({
478101
+ title: "Watchdog \u2014 Force-Resolve Timeout",
478102
+ icon: icon("clock"),
478103
+ currentValue: wdForce,
478104
+ scopeEnabled: false,
478105
+ options: [
478106
+ { value: "wd-force:1", label: "1s" },
478107
+ { value: "wd-force:5", label: "5s", description: "default" },
478108
+ { value: "wd-force:10", label: "10s" },
478109
+ { value: "wd-force:30", label: "30s" }
478110
+ ],
478111
+ onSelect: (value) => {
478112
+ const sec = Number(value.split(":")[1]);
478113
+ ctx2.saveToScope({ watchdogTimeouts: { ...wd, forceResolveMs: sec * 1000 } }, "global");
478114
+ sysMsg(ctx2, `Watchdog force-resolve timeout \u2192 ${sec}s (global)`);
478115
+ }
478116
+ });
478117
+ }
478118
+ };
477986
478119
  ctx.openCommandPicker({
477987
- title: "Tool Timeout",
478120
+ title: "Timeouts & Watchdog",
477988
478121
  icon: icon("clock"),
477989
- currentValue: String(current),
478122
+ currentValue: currentTool,
477990
478123
  scopeEnabled: false,
477991
- options,
478124
+ options: [
478125
+ {
478126
+ value: "tool-timeout",
478127
+ label: "Tool Timeout",
478128
+ description: `${currentToolTimeout === 0 ? "none" : `${currentToolTimeout}m`}`
478129
+ },
478130
+ { value: "watchdog-toggle", label: "Watchdog", description: watchdogEnabled ? "On" : "Off" },
478131
+ { value: "wd-first", label: "First Chunk Timeout", description: `${wdFirstSec}s` },
478132
+ { value: "wd-chunk", label: "Chunk Timeout", description: `${wdChunkSec}s` },
478133
+ { value: "wd-tool", label: "Tool Max Timeout", description: `${wdToolSec}s` },
478134
+ { value: "wd-force", label: "Force-Resolve Timeout", description: `${wdForceSec}s` }
478135
+ ],
477992
478136
  onSelect: (value) => {
477993
- ctx.saveToScope({ toolTimeout: Number(value) }, "global");
477994
- sysMsg(ctx, `Tool timeout \u2192 ${value === "0" ? "none" : `${value}m`} (global)`);
478137
+ const handler4 = timeoutPickers[value];
478138
+ if (handler4) {
478139
+ handler4("", ctx);
478140
+ }
477995
478141
  }
477996
478142
  });
477997
478143
  }
@@ -478338,8 +478484,8 @@ function register4(map2) {
478338
478484
  map2.set("/settings", handleSettingsHub);
478339
478485
  map2.set("/lock-in", handleLockIn);
478340
478486
  map2.set("/theme", handleTheme);
478341
- map2.set("/watchdog", handleWatchdog);
478342
478487
  map2.set("/timeouts", handleTimeouts);
478488
+ map2.set("/watchdog", handleTimeouts);
478343
478489
  }
478344
478490
  function matchConfigPrefix(cmd) {
478345
478491
  if (cmd === "/font nerd")
@@ -478356,7 +478502,7 @@ function matchConfigPrefix(cmd) {
478356
478502
  return handleTheme;
478357
478503
  return null;
478358
478504
  }
478359
- var handleVerbose, handleWatchdog, handleVimHints, settingsHandlers, OPACITY_LEVELS, OPACITY_OPTIONS, BORDER_STRENGTH_OPTIONS, BORDER_STRENGTH_LABELS, handleTheme = (input, ctx) => {
478505
+ var handleVerbose, handleVimHints, settingsHandlers, OPACITY_LEVELS, OPACITY_OPTIONS, BORDER_STRENGTH_OPTIONS, BORDER_STRENGTH_LABELS, handleTheme = (input, ctx) => {
478360
478506
  const arg = input.replace(/^\/theme\s*/, "").trim();
478361
478507
  const current = useThemeStore.getState().name;
478362
478508
  const isTransparent = useThemeStore.getState().tokens.bgApp === "transparent";
@@ -478476,18 +478622,6 @@ var init_config3 = __esm(() => {
478476
478622
  offDescription: "show compact tool call summaries",
478477
478623
  messageTemplate: (v4, s2) => `Verbose mode ${v4 === "on" ? "on" : "off"} (${s2})`
478478
478624
  });
478479
- handleWatchdog = createTogglePicker({
478480
- configKey: "watchdog",
478481
- title: "Stream Stall Watchdog",
478482
- iconName: "dog",
478483
- onValue: "on",
478484
- offValue: "off",
478485
- onLabel: "On",
478486
- offLabel: "Off",
478487
- onDescription: "auto-retry when stream stalls (connection hangs)",
478488
- offDescription: "no automatic stall detection or retry",
478489
- messageTemplate: (v4, s2) => `Watchdog ${v4 === "on" ? "enabled" : "disabled"} (${s2})`
478490
- });
478491
478625
  handleVimHints = createTogglePicker({
478492
478626
  configKey: "vimHints",
478493
478627
  title: "Vim Hints",
@@ -481126,8 +481260,8 @@ var init_prerequisites = __esm(() => {
481126
481260
  PREREQUISITES = [
481127
481261
  {
481128
481262
  name: "Neovim",
481129
- description: "Embedded editor (required, v0.11+)",
481130
- required: true,
481263
+ description: "Embedded editor (optional, v0.11+)",
481264
+ required: false,
481131
481265
  check: () => getVendoredPath("nvim") !== null || commandExists3("nvim"),
481132
481266
  install: {
481133
481267
  darwin: ["brew install neovim"],
@@ -482366,6 +482500,7 @@ __export(exports_src3, {
482366
482500
  setExitSessionId: () => setExitSessionId,
482367
482501
  restart: () => restart,
482368
482502
  hardRestart: () => hardRestart,
482503
+ getActiveRenderer: () => getActiveRenderer,
482369
482504
  cleanupAndExit: () => cleanupAndExit
482370
482505
  });
482371
482506
  function setExitSessionId(id) {
@@ -482675,6 +482810,9 @@ async function start2(opts) {
482675
482810
  opts
482676
482811
  }, undefined, false, undefined, this));
482677
482812
  }
482813
+ function getActiveRenderer() {
482814
+ return renderer;
482815
+ }
482678
482816
  var import_react15, exitSessionId = null, renderer = null, cleanedUp = false, bannerPrinted = false, triggerRestart = null, RESTART_STEPS, RESTART_SPINNER;
482679
482817
  var init_src3 = __esm(async () => {
482680
482818
  init_neovim();
@@ -484851,19 +484989,12 @@ var init_registry = __esm(() => {
484851
484989
  category: "System",
484852
484990
  tags: ["onboarding", "setup", "welcome"]
484853
484991
  },
484854
- {
484855
- cmd: "/watchdog",
484856
- ic: "dog",
484857
- desc: "Toggle stream stall watchdog (auto-retry on hangs)",
484858
- category: "System",
484859
- tags: ["stall", "retry", "timeout"]
484860
- },
484861
484992
  {
484862
484993
  cmd: "/timeouts",
484863
484994
  ic: "clock",
484864
- desc: "Set tool call timeout (shell, project, agents)",
484995
+ desc: "Configure tool and watchdog timeouts",
484865
484996
  category: "System",
484866
- tags: ["timeout", "shell", "agent"]
484997
+ tags: ["timeout", "shell", "agent", "watchdog", "stall"]
484867
484998
  },
484868
484999
  {
484869
485000
  cmd: "/checkpoint",
@@ -484975,8 +485106,20 @@ var init_registry = __esm(() => {
484975
485106
  import { spawn as spawn20 } from "child_process";
484976
485107
  function suspendAndRun(opts) {
484977
485108
  return new Promise((resolve40) => {
485109
+ const renderer2 = (() => {
485110
+ try {
485111
+ return getActiveRenderer();
485112
+ } catch {
485113
+ return null;
485114
+ }
485115
+ })();
485116
+ try {
485117
+ renderer2?.suspend();
485118
+ } catch {}
484978
485119
  if (process.stdin.isTTY) {
484979
- process.stdin.setRawMode(false);
485120
+ try {
485121
+ process.stdin.setRawMode(false);
485122
+ } catch {}
484980
485123
  }
484981
485124
  if (!opts.noAltScreen) {
484982
485125
  process.stdout.write("\x1B[?1049h");
@@ -484986,29 +485129,28 @@ function suspendAndRun(opts) {
484986
485129
  stdio: "inherit",
484987
485130
  env: { ...process.env }
484988
485131
  });
484989
- proc.on("close", (code) => {
485132
+ const restore = (code) => {
484990
485133
  if (!opts.noAltScreen) {
484991
485134
  process.stdout.write("\x1B[?1049l");
484992
485135
  }
485136
+ try {
485137
+ renderer2?.resume();
485138
+ } catch {}
484993
485139
  if (process.stdin.isTTY) {
484994
- process.stdin.setRawMode(true);
484995
- process.stdin.resume();
485140
+ try {
485141
+ process.stdin.setRawMode(true);
485142
+ process.stdin.resume();
485143
+ } catch {}
484996
485144
  }
484997
485145
  resolve40({ exitCode: code });
484998
- });
484999
- proc.on("error", () => {
485000
- if (!opts.noAltScreen) {
485001
- process.stdout.write("\x1B[?1049l");
485002
- }
485003
- if (process.stdin.isTTY) {
485004
- process.stdin.setRawMode(true);
485005
- process.stdin.resume();
485006
- }
485007
- resolve40({ exitCode: null });
485008
- });
485146
+ };
485147
+ proc.on("close", (code) => restore(code));
485148
+ proc.on("error", () => restore(null));
485009
485149
  });
485010
485150
  }
485011
- var init_suspend = () => {};
485151
+ var init_suspend = __esm(async () => {
485152
+ await init_src3();
485153
+ });
485012
485154
 
485013
485155
  // src/hooks/useConfigSync.ts
485014
485156
  function useConfigSync({
@@ -488369,6 +488511,21 @@ var init_compaction_logs = __esm(() => {
488369
488511
  })));
488370
488512
  });
488371
488513
 
488514
+ // src/types/index.ts
488515
+ function clampWatchdogTimeouts(raw2) {
488516
+ const clamp = (value, min, max, fallback) => {
488517
+ if (value === undefined)
488518
+ return fallback;
488519
+ return Math.max(min, Math.min(max, value));
488520
+ };
488521
+ return {
488522
+ firstChunkMs: clamp(raw2?.firstChunkMs, 30000, 600000, 180000),
488523
+ chunkMs: clamp(raw2?.chunkMs, 30000, 600000, 120000),
488524
+ toolMaxMs: clamp(raw2?.toolMaxMs, 120000, 1800000, 900000),
488525
+ forceResolveMs: clamp(raw2?.forceResolveMs, 1000, 30000, 5000)
488526
+ };
488527
+ }
488528
+
488372
488529
  // src/hooks/chat/message-processing.ts
488373
488530
  function safeParseArgs(raw2) {
488374
488531
  if (!raw2)
@@ -490222,9 +490379,10 @@ Proceeding without it will significantly reduce capabilities \u2014 no soul tool
490222
490379
  if (!result) {
490223
490380
  throw new Error("Stream aborted before result was assigned");
490224
490381
  }
490225
- const STALL_CHUNK_MS = 120000;
490226
- const STALL_FIRST_CHUNK_MS = 180000;
490227
- const STALL_TOOL_MAX_MS = 900000;
490382
+ const wd = clampWatchdogTimeouts(effectiveConfig2.watchdogTimeouts);
490383
+ const STALL_CHUNK_MS = wd.chunkMs;
490384
+ const STALL_FIRST_CHUNK_MS = wd.firstChunkMs;
490385
+ const STALL_TOOL_MAX_MS = wd.toolMaxMs;
490228
490386
  let lastActivityTs = Date.now();
490229
490387
  let lastToolActivityTs = Date.now();
490230
490388
  let toolsInFlight = 0;
@@ -490268,7 +490426,7 @@ Proceeding without it will significantly reduce capabilities \u2014 no soul tool
490268
490426
  lastToolActivityTs = Date.now();
490269
490427
  });
490270
490428
  let stallAbortedAt = 0;
490271
- const STALL_FORCE_RESOLVE_MS = 5000;
490429
+ const STALL_FORCE_RESOLVE_MS = wd.forceResolveMs;
490272
490430
  if (effectiveConfig2.watchdog)
490273
490431
  stallWatchdog = setInterval(() => {
490274
490432
  if (stallAborted && Date.now() - stallAbortedAt >= STALL_FORCE_RESOLVE_MS) {
@@ -506814,6 +506972,18 @@ function OptionRow2({
506814
506972
  textFaint,
506815
506973
  successColor
506816
506974
  }) {
506975
+ if (option2.kind === "separator") {
506976
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
506977
+ flexDirection: "row",
506978
+ backgroundColor: popupBg,
506979
+ paddingX: 1,
506980
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
506981
+ fg: textFaint,
506982
+ bg: popupBg,
506983
+ children: "\u2500".repeat(innerW - 4)
506984
+ }, undefined, false, undefined, this)
506985
+ }, undefined, false, undefined, this);
506986
+ }
506817
506987
  const isDisabled = option2.disabled === true;
506818
506988
  const bg2 = isActive && !isDisabled ? popupHl : popupBg;
506819
506989
  const activeColor = option2.color ?? brandSecondary;
@@ -506940,9 +507110,11 @@ function CommandPicker({ visible, config: config2, onClose }) {
506940
507110
  initial[sel.key] = sel.value;
506941
507111
  setSelectorState(initial);
506942
507112
  }
506943
- let idx = filteredOptions.findIndex((o3) => o3.value === config2.currentValue);
506944
- if (idx < 0)
506945
- idx = filteredOptions.findIndex((o3) => !o3.disabled);
507113
+ const curVal = config2.currentValue;
507114
+ let idx = curVal ? Array.isArray(curVal) ? filteredOptions.findIndex((o3) => curVal.includes(o3.value)) : filteredOptions.findIndex((o3) => o3.value === curVal) : -1;
507115
+ if (idx < 0) {
507116
+ idx = filteredOptions.findIndex((o3) => !o3.disabled && o3.kind !== "separator");
507117
+ }
506946
507118
  const startIdx = idx >= 0 ? idx : 0;
506947
507119
  setCursor(startIdx);
506948
507120
  setScrollOffset(Math.max(0, startIdx - Math.floor(maxVisible / 2)));
@@ -507041,7 +507213,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507041
507213
  if (prev > 0) {
507042
507214
  let next = prev - 1;
507043
507215
  const start3 = next;
507044
- while (filteredOptions[next]?.disabled) {
507216
+ while (filteredOptions[next]?.kind === "separator" || filteredOptions[next]?.disabled) {
507045
507217
  next = next > 0 ? next - 1 : filteredOptions.length - 1;
507046
507218
  if (next === start3)
507047
507219
  break;
@@ -507063,7 +507235,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507063
507235
  if (prev < filteredOptions.length - 1) {
507064
507236
  let next = prev + 1;
507065
507237
  const start3 = next;
507066
- while (filteredOptions[next]?.disabled) {
507238
+ while (filteredOptions[next]?.kind === "separator" || filteredOptions[next]?.disabled) {
507067
507239
  next = next < filteredOptions.length - 1 ? next + 1 : 0;
507068
507240
  if (next === start3)
507069
507241
  break;
@@ -507138,7 +507310,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507138
507310
  }
507139
507311
  if (evt.name === "return" && focusZone === ZONE_LIST) {
507140
507312
  const option2 = filteredOptions[cursor];
507141
- if (option2 && !option2.disabled) {
507313
+ if (option2 && !option2.disabled && option2.kind !== "separator") {
507142
507314
  const cb = config2.onSelect;
507143
507315
  const val = option2.value;
507144
507316
  const s2 = config2.scopeEnabled ? scope : undefined;
@@ -507236,7 +507408,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507236
507408
  }, undefined, false, undefined, this) : filteredOptions.slice(clampedOffset, clampedOffset + maxVisible).map((option2, vi) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(OptionRow2, {
507237
507409
  option: option2,
507238
507410
  isActive: vi + clampedOffset === cursor,
507239
- isCurrent: option2.value === config2.currentValue,
507411
+ isCurrent: config2.currentValue ? Array.isArray(config2.currentValue) ? config2.currentValue.includes(option2.value) : option2.value === config2.currentValue : false,
507240
507412
  innerW,
507241
507413
  popupBg: POPUP_BG,
507242
507414
  popupHl: POPUP_HL,
@@ -508381,6 +508553,7 @@ function SetupStep({
508381
508553
  }) {
508382
508554
  {
508383
508555
  const t2 = useTheme();
508556
+ const renderer2 = useRenderer();
508384
508557
  const [phase, setPhase] = import_react100.useState("provider");
508385
508558
  const [cursor, setCursor] = import_react100.useState(0);
508386
508559
  const [selectedProvider, setSelectedProvider] = import_react100.useState(null);
@@ -508413,6 +508586,19 @@ function SetupStep({
508413
508586
  import_react100.useEffect(() => {
508414
508587
  setActive(isInputPhase);
508415
508588
  }, [isInputPhase, setActive]);
508589
+ import_react100.useEffect(() => {
508590
+ if (phase !== "key")
508591
+ return;
508592
+ const handler4 = (event) => {
508593
+ const cleaned = decodePasteBytes(event.bytes).replace(/[\n\r]/g, "").trim();
508594
+ if (cleaned)
508595
+ setKeyInput((v4) => v4 + cleaned);
508596
+ };
508597
+ renderer2.keyInput.on("paste", handler4);
508598
+ return () => {
508599
+ renderer2.keyInput.off("paste", handler4);
508600
+ };
508601
+ }, [phase, renderer2]);
508416
508602
  import_react100.useEffect(() => {
508417
508603
  if (phase === "fetching") {
508418
508604
  spinnerRef.current = setInterval(() => setSpinnerFrame((f3) => (f3 + 1) % SPINNER_FRAMES2.length), 80);
@@ -508730,10 +508916,11 @@ function SetupStep({
508730
508916
  ]
508731
508917
  }, undefined, true, undefined, this),
508732
508918
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(VSpacer, {}, undefined, false, undefined, this),
508733
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Field, {
508734
- label: "API key",
508735
- value: displayMask || " ",
508736
- focused: true
508919
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Search, {
508920
+ value: displayMask,
508921
+ placeholder: "paste or type your key",
508922
+ focused: true,
508923
+ icon: "key"
508737
508924
  }, undefined, false, undefined, this),
508738
508925
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(VSpacer, {}, undefined, false, undefined, this),
508739
508926
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeyCaps, {
@@ -524193,7 +524380,6 @@ var init_App = __esm(async () => {
524193
524380
  init_forbidden();
524194
524381
  init_manager();
524195
524382
  init_prerequisites();
524196
- init_suspend();
524197
524383
  init_theme();
524198
524384
  init_show_image();
524199
524385
  init_splash();
@@ -524221,6 +524407,7 @@ var init_App = __esm(async () => {
524221
524407
  await __promiseAll([
524222
524408
  init_core4(),
524223
524409
  init_react2(),
524410
+ init_suspend(),
524224
524411
  init_useGlobalKeyboard(),
524225
524412
  init_src3(),
524226
524413
  init_BrandTag(),
@@ -49658,7 +49658,7 @@ var package_default;
49658
49658
  var init_package = __esm(() => {
49659
49659
  package_default = {
49660
49660
  name: "@proxysoul/soulforge",
49661
- version: "2.15.2",
49661
+ version: "2.15.4",
49662
49662
  description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
49663
49663
  repository: {
49664
49664
  type: "git",
@@ -49679,7 +49679,7 @@ var init_package = __esm(() => {
49679
49679
  "soulforge-remote": "./dist/soulforge-remote.sh"
49680
49680
  },
49681
49681
  engines: {
49682
- bun: ">=1.2.0"
49682
+ bun: ">=1.3.13"
49683
49683
  },
49684
49684
  files: [
49685
49685
  "dist",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proxysoul/soulforge",
3
- "version": "2.15.2",
3
+ "version": "2.15.4",
4
4
  "description": "Graph-powered code intelligence — multi-agent coding with codebase-aware AI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,7 +21,7 @@
21
21
  "soulforge-remote": "./dist/soulforge-remote.sh"
22
22
  },
23
23
  "engines": {
24
- "bun": ">=1.2.0"
24
+ "bun": ">=1.3.13"
25
25
  },
26
26
  "files": [
27
27
  "dist",