@proxysoul/soulforge 2.20.7 → 2.20.9

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 +87 -39
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -71947,7 +71947,7 @@ var package_default;
71947
71947
  var init_package = __esm(() => {
71948
71948
  package_default = {
71949
71949
  name: "@proxysoul/soulforge",
71950
- version: "2.20.7",
71950
+ version: "2.20.9",
71951
71951
  description: "Graph-powered code intelligence \u2014 multi-agent coding with codebase-aware AI",
71952
71952
  repository: {
71953
71953
  type: "git",
@@ -100840,11 +100840,11 @@ var init_lifecycle = __esm(() => {
100840
100840
  PROXY_PROVIDERS = [
100841
100841
  { id: "claude", name: "Claude", flag: "-claude-login", prefix: "claude-" },
100842
100842
  { id: "google", name: "Google (Gemini)", flag: "-login", prefix: "gemini-" },
100843
- { id: "openai", name: "OpenAI", flag: "-codex-login", prefix: "codex-" },
100843
+ { id: "openai", name: "OpenAI (Codex)", flag: "-codex-login", prefix: "codex-" },
100844
100844
  { id: "codex", name: "Codex (device)", flag: "-codex-device-login", prefix: "codex-" },
100845
- { id: "qwen", name: "Qwen", flag: "-qwen-login", prefix: "qwen-" },
100846
- { id: "kimi", name: "Kimi", flag: "-kimi-login", prefix: "kimi-" },
100847
- { id: "iflow", name: "iFlow", flag: "-iflow-login", prefix: "iflow-" }
100845
+ { id: "antigravity", name: "Antigravity", flag: "-antigravity-login", prefix: "antigravity-" },
100846
+ { id: "xai", name: "xAI (Grok)", flag: "-xai-login", prefix: "xai-" },
100847
+ { id: "kimi", name: "Kimi", flag: "-kimi-login", prefix: "kimi-" }
100848
100848
  ];
100849
100849
  AUTH_DIR = join19(homedir3(), ".cli-proxy-api");
100850
100850
  VERSION_CACHE_TTL = 10 * 60 * 1000;
@@ -396346,7 +396346,7 @@ var init_clipboard2 = __esm(() => {
396346
396346
  import { MouseButton } from "@opentui/core";
396347
396347
  function useCopySelection() {
396348
396348
  const renderer = useRenderer();
396349
- const copySelection = import_react19.useCallback(() => {
396349
+ const copySelectionInner = import_react19.useCallback((clear) => {
396350
396350
  const sel = renderer.getSelection();
396351
396351
  if (!sel)
396352
396352
  return false;
@@ -396357,9 +396357,12 @@ function useCopySelection() {
396357
396357
  const clipboardText = focus?.getClipboardText && sel.selectedRenderables.includes(focus) ? focus.getClipboardText(text2) : text2;
396358
396358
  renderer.copyToClipboardOSC52(clipboardText);
396359
396359
  copyToClipboard2(clipboardText);
396360
- renderer.clearSelection();
396360
+ if (clear)
396361
+ renderer.clearSelection();
396361
396362
  return true;
396362
396363
  }, [renderer]);
396364
+ const copySelection = import_react19.useCallback(() => copySelectionInner(true), [copySelectionInner]);
396365
+ const copyOnSelect = import_react19.useCallback(() => copySelectionInner(false), [copySelectionInner]);
396363
396366
  const onMouseDown = import_react19.useCallback((evt) => {
396364
396367
  if (IS_WIN)
396365
396368
  return;
@@ -396370,7 +396373,7 @@ function useCopySelection() {
396370
396373
  evt.preventDefault();
396371
396374
  evt.stopPropagation();
396372
396375
  }, [copySelection]);
396373
- const onMouseUp = IS_WIN ? undefined : copySelection;
396376
+ const onMouseUp = IS_WIN ? undefined : copyOnSelect;
396374
396377
  return { copySelection, onMouseDown, onMouseUp };
396375
396378
  }
396376
396379
  var import_react19;
@@ -403644,7 +403647,9 @@ var exports_telemetry = {};
403644
403647
  __export(exports_telemetry, {
403645
403648
  telemetryDisabled: () => telemetryDisabled,
403646
403649
  sendBeacon: () => sendBeacon,
403647
- maybeShowTelemetryNotice: () => maybeShowTelemetryNotice
403650
+ maybeShowTelemetryNotice: () => maybeShowTelemetryNotice,
403651
+ detectTerminalBucket: () => detectTerminalBucket,
403652
+ detectRuntime: () => detectRuntime
403648
403653
  });
403649
403654
  import { randomUUID as randomUUID3 } from "crypto";
403650
403655
  import { existsSync as existsSync36, mkdirSync as mkdirSync20, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "fs";
@@ -403707,6 +403712,33 @@ function normArch() {
403707
403712
  return "x64";
403708
403713
  return "other";
403709
403714
  }
403715
+ function detectTerminalBucket() {
403716
+ const term = process.env.TERM_PROGRAM?.toLowerCase() ?? "";
403717
+ if (process.env.KITTY_WINDOW_ID || term === "kitty")
403718
+ return "kitty";
403719
+ if (term === "ghostty")
403720
+ return "ghostty";
403721
+ if (process.env.ITERM_SESSION_ID || term === "iterm.app" || term === "iterm2")
403722
+ return "iterm";
403723
+ if (term === "vscode")
403724
+ return "vscode";
403725
+ if (process.env.WEZTERM_PANE !== undefined || term === "wezterm")
403726
+ return "wezterm";
403727
+ if (term === "warp")
403728
+ return "warp";
403729
+ if (process.env.TMUX)
403730
+ return "tmux";
403731
+ return "other";
403732
+ }
403733
+ function detectRuntime() {
403734
+ const bun = process.versions.bun;
403735
+ if (bun)
403736
+ return `bun-${bun.split(".")[0]}`;
403737
+ const node = process.versions.node;
403738
+ if (node)
403739
+ return `node-${node.split(".")[0]}`;
403740
+ return "other";
403741
+ }
403710
403742
  function sendBeacon(fields, configEnabled) {
403711
403743
  if (telemetryDisabled(configEnabled))
403712
403744
  return;
@@ -403726,7 +403758,15 @@ function sendBeacon(fields, configEnabled) {
403726
403758
  if (fields.provider)
403727
403759
  params.set("pv", fields.provider.slice(0, 24));
403728
403760
  if (fields.model)
403729
- params.set("md", fields.model.slice(0, 32));
403761
+ params.set("md", fields.model.slice(0, 40));
403762
+ if (fields.mode)
403763
+ params.set("mo", fields.mode.slice(0, 16));
403764
+ if (fields.terminal)
403765
+ params.set("tm", fields.terminal.slice(0, 16));
403766
+ if (fields.runtime)
403767
+ params.set("rt", fields.runtime.slice(0, 16));
403768
+ if (fields.repomap)
403769
+ params.set("rm", fields.repomap.slice(0, 8));
403730
403770
  const url2 = `${endpoint()}?${params.toString()}`;
403731
403771
  fetch(url2, {
403732
403772
  method: "GET",
@@ -404079,7 +404119,7 @@ async function start2(opts) {
404079
404119
  }
404080
404120
  }
404081
404121
  try {
404082
- const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
404122
+ const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2, detectTerminalBucket: detectTerminalBucket2, detectRuntime: detectRuntime2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
404083
404123
  const { detectModelFamily: detectModelFamily2, telemetryModelInfo } = await Promise.resolve().then(() => (init_provider_options(), exports_provider_options));
404084
404124
  const { CURRENT_VERSION: CURRENT_VERSION2, detectInstallMethod: detectInstallMethod2 } = await Promise.resolve().then(() => (init_version(), exports_version));
404085
404125
  const { loadConfig: loadConfig2, saveGlobalConfig: saveGlobalConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config2));
@@ -404093,7 +404133,11 @@ async function start2(opts) {
404093
404133
  install: detectInstallMethod2(),
404094
404134
  family: hasModel ? detectModelFamily2(cfg.defaultModel) : undefined,
404095
404135
  provider: info2?.provider,
404096
- model: info2?.model
404136
+ model: info2?.model,
404137
+ mode: cfg.defaultForgeMode ?? "default",
404138
+ terminal: detectTerminalBucket2(),
404139
+ runtime: detectRuntime2(),
404140
+ repomap: process.env.SOULFORGE_NO_REPOMAP === "1" ? "skipped" : "on"
404097
404141
  }, cfg.telemetry);
404098
404142
  } catch {}
404099
404143
  opts.createRoot(r).render(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AppRoot, {
@@ -412602,9 +412646,9 @@ function telemetryModelInfo(modelId) {
412602
412646
  const rawProvider = slash >= 0 ? modelId.slice(0, slash) : "";
412603
412647
  const builtin = isBuiltinProvider(rawProvider);
412604
412648
  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";
412649
+ const raw = (slash >= 0 ? modelId.slice(slash + 1) : modelId).toLowerCase();
412650
+ const known = builtin && raw.length <= 40 && TELEMETRY_MODEL_SLUG.test(raw);
412651
+ const model = known ? raw : "other";
412608
412652
  return { provider, model };
412609
412653
  }
412610
412654
  function getSupportedClaudeEfforts(modelId) {
@@ -413087,7 +413131,7 @@ function buildGroqOptions(config2) {
413087
413131
  function isDeepSeekReasoner(base) {
413088
413132
  return base === "deepseek-reasoner" || base.includes("reasoner") || base.endsWith("-think");
413089
413133
  }
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;
413134
+ 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
413135
  var init_provider_options = __esm(() => {
413092
413136
  init_models();
413093
413137
  init_providers();
@@ -413206,14 +413250,7 @@ var init_provider_options = __esm(() => {
413206
413250
  "claude-2",
413207
413251
  "claude-instant"
413208
413252
  ];
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
- ];
413253
+ TELEMETRY_MODEL_SLUG = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){0,5}$/;
413217
413254
  CACHE_EPHEMERAL_5M = {
413218
413255
  cacheControl: { type: "ephemeral", ttl: "5m" }
413219
413256
  };
@@ -447257,14 +447294,13 @@ What each part means:
447257
447294
  - + before a symbol = exported (part of the public API)
447258
447295
  - \u2190 arrows = "imported by" \u2014 shows which files depend on this one
447259
447296
  - 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.
447297
+ - 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.
447298
+
447299
+ - "Where is X?" \u2192 the map points you at a file + line to confirm with a read/navigate.
447300
+ - "What does Y export?" \u2192 a starting list; verify before asserting the full surface.
447301
+ - "What depends on Z?" \u2192 (\u2192N) and \u2190 arrows orient blast radius; soul_impact confirms it.
447302
+
447303
+ 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
447304
  `, DIR_TREE_DEPTH = 2, DIR_TREE_TTL_MS = 60000, dirTreeCache;
447269
447305
  var init_soul_map = __esm(() => {
447270
447306
  init_file_tree();
@@ -447273,7 +447309,7 @@ var init_soul_map = __esm(() => {
447273
447309
 
447274
447310
  // src/core/prompts/shared/tool-guidance.ts
447275
447311
  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.
447312
+ 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
447313
 
447278
447314
  <workflow>
447279
447315
  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 +447317,7 @@ When one discovery needs the output of the previous (search \u2192 filter \u2192
447281
447317
  </workflow>
447282
447318
 
447283
447319
  <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.
447320
+ 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
447321
  </soul_map_usage>
447286
447322
 
447287
447323
  <soul_map_updates>
@@ -467072,7 +467108,7 @@ async function setupAgent(opts, merged) {
467072
467108
  }
467073
467109
  const providerOpts = await buildProviderOptions(modelId, merged);
467074
467110
  try {
467075
- const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
467111
+ const { sendBeacon: sendBeacon2, maybeShowTelemetryNotice: maybeShowTelemetryNotice2, detectRuntime: detectRuntime2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
467076
467112
  const { detectModelFamily: detectModelFamily2, telemetryModelInfo: telemetryModelInfo2 } = await Promise.resolve().then(() => (init_provider_options(), exports_provider_options));
467077
467113
  const { CURRENT_VERSION: CURRENT_VERSION2, detectInstallMethod: detectInstallMethod2 } = await Promise.resolve().then(() => (init_version(), exports_version));
467078
467114
  const { saveGlobalConfig: saveGlobalConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config2));
@@ -467084,7 +467120,10 @@ async function setupAgent(opts, merged) {
467084
467120
  install: detectInstallMethod2(),
467085
467121
  family: detectModelFamily2(modelId),
467086
467122
  provider: info2.provider,
467087
- model: info2.model
467123
+ model: info2.model,
467124
+ mode: opts.mode,
467125
+ runtime: detectRuntime2(),
467126
+ repomap: merged.repoMap === false || opts.noRepomap || process.env.SOULFORGE_NO_REPOMAP === "1" ? "skipped" : "on"
467088
467127
  }, merged.telemetry);
467089
467128
  } catch {}
467090
467129
  const repoMapDisabled = merged.repoMap === false || opts.noRepomap || process.env.SOULFORGE_NO_REPOMAP === "1";
@@ -468224,10 +468263,15 @@ class HearthDaemon {
468224
468263
  }
468225
468264
  await this.startSocket();
468226
468265
  try {
468227
- const { sendBeacon: sendBeacon2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
468266
+ const { sendBeacon: sendBeacon2, detectRuntime: detectRuntime2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
468228
468267
  const { CURRENT_VERSION: CURRENT_VERSION2, detectInstallMethod: detectInstallMethod2 } = await Promise.resolve().then(() => (init_version(), exports_version));
468229
468268
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config2));
468230
- sendBeacon2({ surface: "hearth", version: CURRENT_VERSION2, install: detectInstallMethod2() }, loadConfig2().telemetry);
468269
+ sendBeacon2({
468270
+ surface: "hearth",
468271
+ version: CURRENT_VERSION2,
468272
+ install: detectInstallMethod2(),
468273
+ runtime: detectRuntime2()
468274
+ }, loadConfig2().telemetry);
468231
468275
  } catch {}
468232
468276
  const tuiOwner = readBridgeOwner();
468233
468277
  this.tuiOwnerPid = tuiOwner && tuiOwner !== process.pid ? tuiOwner : null;
@@ -486969,6 +487013,10 @@ function useTextDrip(fullText, streaming) {
486969
487013
  const delta = fullText.length - prevLenRef.current;
486970
487014
  if (delta > 0) {
486971
487015
  bufferRef.current += delta;
487016
+ } else if (delta < 0) {
487017
+ bufferRef.current = fullText.length;
487018
+ velocityRef.current = MIN_SPEED;
487019
+ setDrip({ revealed: 0, fresh: 0 });
486972
487020
  }
486973
487021
  prevLenRef.current = fullText.length;
486974
487022
  }, [fullText]);
@@ -487097,7 +487145,7 @@ function DripText({ content, streaming }) {
487097
487145
  opacity,
487098
487146
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Markdown, {
487099
487147
  text: `${display}${cursor}`,
487100
- streaming: true
487148
+ streaming
487101
487149
  }, undefined, false, undefined, this)
487102
487150
  }, undefined, false, undefined, this);
487103
487151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proxysoul/soulforge",
3
- "version": "2.20.7",
3
+ "version": "2.20.9",
4
4
  "description": "Graph-powered code intelligence — multi-agent coding with codebase-aware AI",
5
5
  "repository": {
6
6
  "type": "git",