@proxysoul/soulforge 2.15.2 → 2.15.3

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.3",
62504
62504
  description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
62505
62505
  repository: {
62506
62506
  type: "git",
@@ -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",
@@ -484851,19 +484985,12 @@ var init_registry = __esm(() => {
484851
484985
  category: "System",
484852
484986
  tags: ["onboarding", "setup", "welcome"]
484853
484987
  },
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
484988
  {
484862
484989
  cmd: "/timeouts",
484863
484990
  ic: "clock",
484864
- desc: "Set tool call timeout (shell, project, agents)",
484991
+ desc: "Configure tool and watchdog timeouts",
484865
484992
  category: "System",
484866
- tags: ["timeout", "shell", "agent"]
484993
+ tags: ["timeout", "shell", "agent", "watchdog", "stall"]
484867
484994
  },
484868
484995
  {
484869
484996
  cmd: "/checkpoint",
@@ -488369,6 +488496,21 @@ var init_compaction_logs = __esm(() => {
488369
488496
  })));
488370
488497
  });
488371
488498
 
488499
+ // src/types/index.ts
488500
+ function clampWatchdogTimeouts(raw2) {
488501
+ const clamp = (value, min, max, fallback) => {
488502
+ if (value === undefined)
488503
+ return fallback;
488504
+ return Math.max(min, Math.min(max, value));
488505
+ };
488506
+ return {
488507
+ firstChunkMs: clamp(raw2?.firstChunkMs, 30000, 600000, 180000),
488508
+ chunkMs: clamp(raw2?.chunkMs, 30000, 600000, 120000),
488509
+ toolMaxMs: clamp(raw2?.toolMaxMs, 120000, 1800000, 900000),
488510
+ forceResolveMs: clamp(raw2?.forceResolveMs, 1000, 30000, 5000)
488511
+ };
488512
+ }
488513
+
488372
488514
  // src/hooks/chat/message-processing.ts
488373
488515
  function safeParseArgs(raw2) {
488374
488516
  if (!raw2)
@@ -490222,9 +490364,10 @@ Proceeding without it will significantly reduce capabilities \u2014 no soul tool
490222
490364
  if (!result) {
490223
490365
  throw new Error("Stream aborted before result was assigned");
490224
490366
  }
490225
- const STALL_CHUNK_MS = 120000;
490226
- const STALL_FIRST_CHUNK_MS = 180000;
490227
- const STALL_TOOL_MAX_MS = 900000;
490367
+ const wd = clampWatchdogTimeouts(effectiveConfig2.watchdogTimeouts);
490368
+ const STALL_CHUNK_MS = wd.chunkMs;
490369
+ const STALL_FIRST_CHUNK_MS = wd.firstChunkMs;
490370
+ const STALL_TOOL_MAX_MS = wd.toolMaxMs;
490228
490371
  let lastActivityTs = Date.now();
490229
490372
  let lastToolActivityTs = Date.now();
490230
490373
  let toolsInFlight = 0;
@@ -490268,7 +490411,7 @@ Proceeding without it will significantly reduce capabilities \u2014 no soul tool
490268
490411
  lastToolActivityTs = Date.now();
490269
490412
  });
490270
490413
  let stallAbortedAt = 0;
490271
- const STALL_FORCE_RESOLVE_MS = 5000;
490414
+ const STALL_FORCE_RESOLVE_MS = wd.forceResolveMs;
490272
490415
  if (effectiveConfig2.watchdog)
490273
490416
  stallWatchdog = setInterval(() => {
490274
490417
  if (stallAborted && Date.now() - stallAbortedAt >= STALL_FORCE_RESOLVE_MS) {
@@ -506814,6 +506957,18 @@ function OptionRow2({
506814
506957
  textFaint,
506815
506958
  successColor
506816
506959
  }) {
506960
+ if (option2.kind === "separator") {
506961
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
506962
+ flexDirection: "row",
506963
+ backgroundColor: popupBg,
506964
+ paddingX: 1,
506965
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
506966
+ fg: textFaint,
506967
+ bg: popupBg,
506968
+ children: "\u2500".repeat(innerW - 4)
506969
+ }, undefined, false, undefined, this)
506970
+ }, undefined, false, undefined, this);
506971
+ }
506817
506972
  const isDisabled = option2.disabled === true;
506818
506973
  const bg2 = isActive && !isDisabled ? popupHl : popupBg;
506819
506974
  const activeColor = option2.color ?? brandSecondary;
@@ -506940,9 +507095,11 @@ function CommandPicker({ visible, config: config2, onClose }) {
506940
507095
  initial[sel.key] = sel.value;
506941
507096
  setSelectorState(initial);
506942
507097
  }
506943
- let idx = filteredOptions.findIndex((o3) => o3.value === config2.currentValue);
506944
- if (idx < 0)
506945
- idx = filteredOptions.findIndex((o3) => !o3.disabled);
507098
+ const curVal = config2.currentValue;
507099
+ let idx = curVal ? Array.isArray(curVal) ? filteredOptions.findIndex((o3) => curVal.includes(o3.value)) : filteredOptions.findIndex((o3) => o3.value === curVal) : -1;
507100
+ if (idx < 0) {
507101
+ idx = filteredOptions.findIndex((o3) => !o3.disabled && o3.kind !== "separator");
507102
+ }
506946
507103
  const startIdx = idx >= 0 ? idx : 0;
506947
507104
  setCursor(startIdx);
506948
507105
  setScrollOffset(Math.max(0, startIdx - Math.floor(maxVisible / 2)));
@@ -507041,7 +507198,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507041
507198
  if (prev > 0) {
507042
507199
  let next = prev - 1;
507043
507200
  const start3 = next;
507044
- while (filteredOptions[next]?.disabled) {
507201
+ while (filteredOptions[next]?.kind === "separator" || filteredOptions[next]?.disabled) {
507045
507202
  next = next > 0 ? next - 1 : filteredOptions.length - 1;
507046
507203
  if (next === start3)
507047
507204
  break;
@@ -507063,7 +507220,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507063
507220
  if (prev < filteredOptions.length - 1) {
507064
507221
  let next = prev + 1;
507065
507222
  const start3 = next;
507066
- while (filteredOptions[next]?.disabled) {
507223
+ while (filteredOptions[next]?.kind === "separator" || filteredOptions[next]?.disabled) {
507067
507224
  next = next < filteredOptions.length - 1 ? next + 1 : 0;
507068
507225
  if (next === start3)
507069
507226
  break;
@@ -507138,7 +507295,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507138
507295
  }
507139
507296
  if (evt.name === "return" && focusZone === ZONE_LIST) {
507140
507297
  const option2 = filteredOptions[cursor];
507141
- if (option2 && !option2.disabled) {
507298
+ if (option2 && !option2.disabled && option2.kind !== "separator") {
507142
507299
  const cb = config2.onSelect;
507143
507300
  const val = option2.value;
507144
507301
  const s2 = config2.scopeEnabled ? scope : undefined;
@@ -507236,7 +507393,7 @@ function CommandPicker({ visible, config: config2, onClose }) {
507236
507393
  }, undefined, false, undefined, this) : filteredOptions.slice(clampedOffset, clampedOffset + maxVisible).map((option2, vi) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(OptionRow2, {
507237
507394
  option: option2,
507238
507395
  isActive: vi + clampedOffset === cursor,
507239
- isCurrent: option2.value === config2.currentValue,
507396
+ isCurrent: config2.currentValue ? Array.isArray(config2.currentValue) ? config2.currentValue.includes(option2.value) : option2.value === config2.currentValue : false,
507240
507397
  innerW,
507241
507398
  popupBg: POPUP_BG,
507242
507399
  popupHl: POPUP_HL,
@@ -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.3",
49662
49662
  description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
49663
49663
  repository: {
49664
49664
  type: "git",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proxysoul/soulforge",
3
- "version": "2.15.2",
3
+ "version": "2.15.3",
4
4
  "description": "Graph-powered code intelligence — multi-agent coding with codebase-aware AI",
5
5
  "repository": {
6
6
  "type": "git",