@proxysoul/soulforge 2.9.5 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17293,6 +17293,60 @@ var init_dist7 = __esm(() => {
17293
17293
  __reExport(src_exports, bundle_full_exports);
17294
17294
  });
17295
17295
 
17296
+ // src/core/utils/ensure-soulforge-dir.ts
17297
+ import { execSync } from "child_process";
17298
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
17299
+ import { join } from "path";
17300
+ function ensureSoulforgeDir(cwd) {
17301
+ const dir = join(cwd, ENTRY);
17302
+ if (!existsSync(dir))
17303
+ mkdirSync(dir, {
17304
+ recursive: true
17305
+ });
17306
+ if (!patched.has(cwd)) {
17307
+ patched.add(cwd);
17308
+ try {
17309
+ ensureGitignore(cwd);
17310
+ } catch {}
17311
+ }
17312
+ return dir;
17313
+ }
17314
+ function ensureGitignore(cwd) {
17315
+ const status = gitCheckIgnoreStatus(cwd);
17316
+ if (status !== 1)
17317
+ return;
17318
+ const gitignorePath = join(cwd, ".gitignore");
17319
+ if (existsSync(gitignorePath)) {
17320
+ const content = readFileSync(gitignorePath, "utf-8");
17321
+ const eol = content.includes(`\r
17322
+ `) ? `\r
17323
+ ` : `
17324
+ `;
17325
+ const prefix = content.length > 0 && !content.endsWith(`
17326
+ `) ? eol : "";
17327
+ appendFileSync(gitignorePath, `${prefix}.soulforge${eol}`);
17328
+ } else {
17329
+ writeFileSync(gitignorePath, `.soulforge
17330
+ `);
17331
+ }
17332
+ }
17333
+ function gitCheckIgnoreStatus(cwd) {
17334
+ try {
17335
+ execSync("git check-ignore -q .soulforge", {
17336
+ cwd,
17337
+ stdio: "pipe",
17338
+ timeout: 3000
17339
+ });
17340
+ return 0;
17341
+ } catch (err2) {
17342
+ return err2.status ?? 128;
17343
+ }
17344
+ }
17345
+ var ENTRY = ".soulforge", patched;
17346
+ var init_ensure_soulforge_dir = __esm(() => {
17347
+ patched = new Set;
17348
+ });
17349
+
17296
17350
  // src/core/security/forbidden.ts
17297
17351
  var exports_forbidden = {};
17298
17352
  __export(exports_forbidden, {
@@ -17306,9 +17360,9 @@ __export(exports_forbidden, {
17306
17360
  addSessionPattern: () => addSessionPattern,
17307
17361
  addProjectPattern: () => addProjectPattern
17308
17362
  });
17309
- import { existsSync, readFileSync, realpathSync, watch, writeFileSync } from "fs";
17363
+ import { existsSync as existsSync2, readFileSync as readFileSync2, realpathSync, watch, writeFileSync as writeFileSync2 } from "fs";
17310
17364
  import { homedir } from "os";
17311
- import { basename as basename2, join, resolve } from "path";
17365
+ import { basename as basename2, join as join2, resolve } from "path";
17312
17366
  function globToRegex(pattern) {
17313
17367
  const cached = regexCache.get(pattern);
17314
17368
  if (cached)
@@ -17320,9 +17374,9 @@ function globToRegex(pattern) {
17320
17374
  }
17321
17375
  function loadPatternsFromFile(filePath) {
17322
17376
  try {
17323
- if (!existsSync(filePath))
17377
+ if (!existsSync2(filePath))
17324
17378
  return [];
17325
- const raw2 = readFileSync(filePath, "utf-8");
17379
+ const raw2 = readFileSync2(filePath, "utf-8");
17326
17380
  const parsed = JSON.parse(raw2);
17327
17381
  return Array.isArray(parsed.patterns) ? parsed.patterns : [];
17328
17382
  } catch {
@@ -17331,9 +17385,9 @@ function loadPatternsFromFile(filePath) {
17331
17385
  }
17332
17386
  function parseIgnoreFile(filePath) {
17333
17387
  try {
17334
- if (!existsSync(filePath))
17388
+ if (!existsSync2(filePath))
17335
17389
  return [];
17336
- const content = readFileSync(filePath, "utf-8");
17390
+ const content = readFileSync2(filePath, "utf-8");
17337
17391
  return content.split(`
17338
17392
  `).map((l3) => l3.trim()).filter((l3) => l3.length > 0 && !l3.startsWith("#"));
17339
17393
  } catch {
@@ -17341,18 +17395,18 @@ function parseIgnoreFile(filePath) {
17341
17395
  }
17342
17396
  }
17343
17397
  function initForbidden(cwd) {
17344
- const globalFile = join(homedir(), ".soulforge", "forbidden.json");
17345
- const projectFile = join(cwd, ".soulforge", "forbidden.json");
17398
+ const globalFile = join2(homedir(), ".soulforge", "forbidden.json");
17399
+ const projectFile = join2(cwd, ".soulforge", "forbidden.json");
17346
17400
  globalPatterns = loadPatternsFromFile(globalFile);
17347
17401
  projectPatterns = loadPatternsFromFile(projectFile);
17348
17402
  sessionPatternsMap.clear();
17349
- const aiIgnorePath = join(cwd, ".aiignore");
17403
+ const aiIgnorePath = join2(cwd, ".aiignore");
17350
17404
  aiIgnorePatterns = parseIgnoreFile(aiIgnorePath);
17351
17405
  if (aiIgnoreWatcher) {
17352
17406
  aiIgnoreWatcher.close();
17353
17407
  aiIgnoreWatcher = null;
17354
17408
  }
17355
- if (existsSync(aiIgnorePath)) {
17409
+ if (existsSync2(aiIgnorePath)) {
17356
17410
  try {
17357
17411
  aiIgnoreWatcher = watch(aiIgnorePath, () => {
17358
17412
  aiIgnorePatterns = parseIgnoreFile(aiIgnorePath);
@@ -17385,28 +17439,23 @@ function clearTabSessionPatterns(tabId) {
17385
17439
  sessionPatternsMap.delete(tabId);
17386
17440
  }
17387
17441
  function addProjectPattern(cwd, pattern) {
17388
- const filePath = join(cwd, ".soulforge", "forbidden.json");
17442
+ const filePath = join2(cwd, ".soulforge", "forbidden.json");
17389
17443
  const existing = loadPatternsFromFile(filePath);
17390
17444
  if (!existing.includes(pattern)) {
17391
17445
  existing.push(pattern);
17392
- const {
17393
- mkdirSync
17394
- } = __require("fs");
17395
- mkdirSync(join(cwd, ".soulforge"), {
17396
- recursive: true
17397
- });
17398
- writeFileSync(filePath, JSON.stringify({
17446
+ ensureSoulforgeDir(cwd);
17447
+ writeFileSync2(filePath, JSON.stringify({
17399
17448
  patterns: existing
17400
17449
  }, null, 2));
17401
17450
  projectPatterns = existing;
17402
17451
  }
17403
17452
  }
17404
17453
  function removeProjectPattern(cwd, pattern) {
17405
- const filePath = join(cwd, ".soulforge", "forbidden.json");
17454
+ const filePath = join2(cwd, ".soulforge", "forbidden.json");
17406
17455
  const existing = loadPatternsFromFile(filePath);
17407
17456
  const updated = existing.filter((p2) => p2 !== pattern);
17408
17457
  if (updated.length !== existing.length) {
17409
- writeFileSync(filePath, JSON.stringify({
17458
+ writeFileSync2(filePath, JSON.stringify({
17410
17459
  patterns: updated
17411
17460
  }, null, 2));
17412
17461
  projectPatterns = updated;
@@ -17462,6 +17511,7 @@ function buildForbiddenContext(tabId) {
17462
17511
  }
17463
17512
  var BUILTIN_PATTERNS, globalPatterns, projectPatterns, sessionPatternsMap, aiIgnorePatterns, initialized = false, aiIgnoreWatcher = null, regexCache;
17464
17513
  var init_forbidden = __esm(() => {
17514
+ init_ensure_soulforge_dir();
17465
17515
  BUILTIN_PATTERNS = [
17466
17516
  ".env",
17467
17517
  ".env.*",
@@ -18553,7 +18603,7 @@ __export(exports_file_tree, {
18553
18603
  IGNORED_DIRS: () => IGNORED_DIRS
18554
18604
  });
18555
18605
  import { readdirSync } from "fs";
18556
- import { join as join2 } from "path";
18606
+ import { join as join3 } from "path";
18557
18607
  function walkDir(dir, prefix, depth, lines) {
18558
18608
  if (depth <= 0)
18559
18609
  return;
@@ -18573,7 +18623,7 @@ function walkDir(dir, prefix, depth, lines) {
18573
18623
  const childPrefix = isLast ? " " : "\u2502 ";
18574
18624
  lines.push(`${prefix}${connector}${entry.name}${entry.isDirectory() ? "/" : ""}`);
18575
18625
  if (entry.isDirectory()) {
18576
- walkDir(join2(dir, entry.name), prefix + childPrefix, depth - 1, lines);
18626
+ walkDir(join3(dir, entry.name), prefix + childPrefix, depth - 1, lines);
18577
18627
  }
18578
18628
  }
18579
18629
  } catch {}
@@ -18586,7 +18636,7 @@ var init_file_tree = __esm(() => {
18586
18636
  // src/core/intelligence/repo-map-utils.ts
18587
18637
  import { readdir, stat } from "fs/promises";
18588
18638
  import { homedir as homedir2 } from "os";
18589
- import { extname, join as join3, resolve as resolve2 } from "path";
18639
+ import { extname, join as join4, resolve as resolve2 } from "path";
18590
18640
  function barrelToDir(barrelPath) {
18591
18641
  return barrelPath.replace(BARREL_RE, "");
18592
18642
  }
@@ -18801,7 +18851,7 @@ async function collectFilesViaGit(dir) {
18801
18851
  const ext = extname(line).toLowerCase();
18802
18852
  if (!(ext in INDEXABLE_EXTENSIONS))
18803
18853
  continue;
18804
- const fullPath = join3(dir, line);
18854
+ const fullPath = join4(dir, line);
18805
18855
  if (isForbidden(fullPath))
18806
18856
  continue;
18807
18857
  try {
@@ -18835,7 +18885,7 @@ async function collectFilesWalk(dir, depth, counter, out2) {
18835
18885
  break;
18836
18886
  if (entry.name.startsWith(".") && entry.name !== ".")
18837
18887
  continue;
18838
- const fullPath = join3(dir, entry.name);
18888
+ const fullPath = join4(dir, entry.name);
18839
18889
  if (entry.isDirectory()) {
18840
18890
  if (!IGNORED_DIRS.has(entry.name)) {
18841
18891
  await collectFilesWalk(fullPath, depth + 1, ctx, files);
@@ -22241,10 +22291,10 @@ var exports_tree_sitter2 = {};
22241
22291
  __export(exports_tree_sitter2, {
22242
22292
  TreeSitterBackend: () => TreeSitterBackend
22243
22293
  });
22244
- import { existsSync as existsSync2 } from "fs";
22294
+ import { existsSync as existsSync3 } from "fs";
22245
22295
  import { readFile } from "fs/promises";
22246
22296
  import { homedir as homedir3 } from "os";
22247
- import { dirname, join as join4, resolve as resolve3 } from "path";
22297
+ import { dirname, join as join5, resolve as resolve3 } from "path";
22248
22298
  function extractImportSpecifiers(node, language) {
22249
22299
  const specifiers = [];
22250
22300
  collectSpecifiers(node, language, specifiers);
@@ -22483,7 +22533,7 @@ function createQuery(lang254, source) {
22483
22533
  var BUNDLED_WASM_DIR, QUERIES, GRAMMAR_FILES, HEADER_EXTS, TSQueryClass = null, TreeSitterBackend;
22484
22534
  var init_tree_sitter2 = __esm(() => {
22485
22535
  init_types2();
22486
- BUNDLED_WASM_DIR = join4(homedir3(), ".soulforge", "wasm");
22536
+ BUNDLED_WASM_DIR = join5(homedir3(), ".soulforge", "wasm");
22487
22537
  QUERIES = {
22488
22538
  typescript: `
22489
22539
  (function_declaration name: (identifier) @name) @func
@@ -23388,13 +23438,13 @@ var init_tree_sitter2 = __esm(() => {
23388
23438
  resolveWasm(filename) {
23389
23439
  const basename3 = filename.split("/").pop() ?? filename;
23390
23440
  if (TreeSitterBackend.IS_BUNDLED) {
23391
- return join4(BUNDLED_WASM_DIR, basename3);
23441
+ return join5(BUNDLED_WASM_DIR, basename3);
23392
23442
  }
23393
23443
  let dir = import.meta.dir;
23394
23444
  for (let i4 = 0;i4 < 5; i4++) {
23395
23445
  for (const sub of ["node_modules/web-tree-sitter", "node_modules/tree-sitter-wasms/out"]) {
23396
- const p2 = join4(dir, sub, basename3);
23397
- if (existsSync2(p2))
23446
+ const p2 = join5(dir, sub, basename3);
23447
+ if (existsSync3(p2))
23398
23448
  return p2;
23399
23449
  }
23400
23450
  const parent = dirname(dir);
@@ -23402,14 +23452,14 @@ var init_tree_sitter2 = __esm(() => {
23402
23452
  break;
23403
23453
  dir = parent;
23404
23454
  }
23405
- return join4(BUNDLED_WASM_DIR, basename3);
23455
+ return join5(BUNDLED_WASM_DIR, basename3);
23406
23456
  }
23407
23457
  async doInit() {
23408
23458
  let wasmPath = this.resolveWasm("tree-sitter.wasm");
23409
- if (!existsSync2(wasmPath)) {
23459
+ if (!existsSync3(wasmPath)) {
23410
23460
  wasmPath = this.resolveWasm("web-tree-sitter.wasm");
23411
23461
  }
23412
- if (!existsSync2(wasmPath)) {
23462
+ if (!existsSync3(wasmPath)) {
23413
23463
  throw new Error(`tree-sitter.wasm not found in ${BUNDLED_WASM_DIR} or node_modules`);
23414
23464
  }
23415
23465
  const mod = await Promise.resolve().then(() => (init_tree_sitter(), exports_tree_sitter));
@@ -24138,10 +24188,10 @@ __export(exports_repo_map, {
24138
24188
  RepoMap: () => RepoMap
24139
24189
  });
24140
24190
  import { Database } from "bun:sqlite";
24141
- import { execSync } from "child_process";
24142
- import { chmodSync, existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, statSync } from "fs";
24191
+ import { execSync as execSync2 } from "child_process";
24192
+ import { chmodSync, existsSync as existsSync4, readFileSync as readFileSync3, statSync } from "fs";
24143
24193
  import { stat as statAsync } from "fs/promises";
24144
- import { dirname as dirname2, extname as extname2, join as join5, relative, resolve as resolve4 } from "path";
24194
+ import { dirname as dirname2, extname as extname2, join as join6, relative, resolve as resolve4 } from "path";
24145
24195
 
24146
24196
  class RepoMap {
24147
24197
  db;
@@ -24167,12 +24217,8 @@ class RepoMap {
24167
24217
  lastRenderedPaths = [];
24168
24218
  constructor(cwd) {
24169
24219
  this.cwd = cwd;
24170
- const dbDir = join5(cwd, ".soulforge");
24171
- if (!existsSync3(dbDir))
24172
- mkdirSync(dbDir, {
24173
- recursive: true
24174
- });
24175
- const dbPath = join5(dbDir, "repomap.db");
24220
+ const dbDir = ensureSoulforgeDir(cwd);
24221
+ const dbPath = join6(dbDir, "repomap.db");
24176
24222
  this.db = new Database(dbPath);
24177
24223
  this.db.run("PRAGMA journal_mode = WAL");
24178
24224
  this.db.run("PRAGMA busy_timeout = 5000");
@@ -24601,7 +24647,7 @@ class RepoMap {
24601
24647
  let lineCount = 0;
24602
24648
  let content;
24603
24649
  try {
24604
- content = readFileSync2(absPath, "utf-8");
24650
+ content = readFileSync3(absPath, "utf-8");
24605
24651
  lineCount = content.split(`
24606
24652
  `).length;
24607
24653
  } catch {
@@ -24857,7 +24903,7 @@ class RepoMap {
24857
24903
  if (this.goModulePrefix !== undefined)
24858
24904
  return this.goModulePrefix;
24859
24905
  try {
24860
- const goMod = readFileSync2(join5(this.cwd, "go.mod"), "utf-8");
24906
+ const goMod = readFileSync3(join6(this.cwd, "go.mod"), "utf-8");
24861
24907
  const match = goMod.match(/^module\s+(\S+)/m);
24862
24908
  this.goModulePrefix = match?.[1] ?? null;
24863
24909
  } catch {
@@ -24871,7 +24917,7 @@ class RepoMap {
24871
24917
  this.tsconfigPaths = null;
24872
24918
  for (const name2 of ["tsconfig.json", "jsconfig.json"]) {
24873
24919
  try {
24874
- const raw2 = readFileSync2(join5(this.cwd, name2), "utf-8");
24920
+ const raw2 = readFileSync3(join6(this.cwd, name2), "utf-8");
24875
24921
  const config = JSON.parse(raw2);
24876
24922
  const paths = config?.compilerOptions?.paths;
24877
24923
  if (paths && typeof paths === "object") {
@@ -24965,21 +25011,21 @@ class RepoMap {
24965
25011
  }
24966
25012
  resolveRelPath(relBase) {
24967
25013
  const stripped = relBase.replace(/\.(m?js|cjs|jsx)$/, "");
24968
- const base = join5(this.cwd, stripped);
25014
+ const base = join6(this.cwd, stripped);
24969
25015
  const candidates = [base];
24970
25016
  if (stripped !== relBase)
24971
- candidates.push(join5(this.cwd, relBase));
25017
+ candidates.push(join6(this.cwd, relBase));
24972
25018
  const ext = extname2(stripped);
24973
25019
  if (!ext) {
24974
25020
  for (const tryExt of Object.keys(INDEXABLE_EXTENSIONS)) {
24975
25021
  candidates.push(base + tryExt);
24976
25022
  }
24977
25023
  for (const tryExt of [".ts", ".tsx", ".js", ".jsx", ".py", ".rb", ".php"]) {
24978
- candidates.push(join5(base, `index${tryExt}`));
25024
+ candidates.push(join6(base, `index${tryExt}`));
24979
25025
  }
24980
- candidates.push(join5(base, "__init__.py"));
24981
- candidates.push(join5(base, "mod.rs"));
24982
- candidates.push(join5(base, "lib.rs"));
25026
+ candidates.push(join6(base, "__init__.py"));
25027
+ candidates.push(join6(base, "mod.rs"));
25028
+ candidates.push(join6(base, "lib.rs"));
24983
25029
  candidates.push(`${base}.go`);
24984
25030
  }
24985
25031
  for (const candidate of candidates) {
@@ -25050,7 +25096,7 @@ class RepoMap {
25050
25096
  const fileRow = getFilePath.get(ref.file_id);
25051
25097
  if (!fileRow)
25052
25098
  continue;
25053
- const absPath = join5(this.cwd, fileRow.path);
25099
+ const absPath = join6(this.cwd, fileRow.path);
25054
25100
  const resolved = this.resolveImportSource(ref.import_source, absPath);
25055
25101
  if (resolved !== null) {
25056
25102
  update.run(resolved, ref.rowid);
@@ -25270,7 +25316,7 @@ class RepoMap {
25270
25316
  const update = this.db.prepare("UPDATE symbols SET qualified_name = ? WHERE id = ?");
25271
25317
  let enriched = 0;
25272
25318
  for (const file of files) {
25273
- const absPath = join5(this.cwd, file.path);
25319
+ const absPath = join6(this.cwd, file.path);
25274
25320
  let raw2;
25275
25321
  try {
25276
25322
  raw2 = await documentSymbols2(absPath);
@@ -25563,7 +25609,7 @@ class RepoMap {
25563
25609
  if (this.hasGit !== null)
25564
25610
  return this.hasGit;
25565
25611
  try {
25566
- execSync("git rev-parse --git-dir", {
25612
+ execSync2("git rev-parse --git-dir", {
25567
25613
  cwd: this.cwd,
25568
25614
  stdio: "pipe",
25569
25615
  timeout: 3000
@@ -25679,8 +25725,8 @@ class RepoMap {
25679
25725
  return this.entryPointsCache;
25680
25726
  this.entryPointsCache = [];
25681
25727
  try {
25682
- const pkgPath = join5(this.cwd, "package.json");
25683
- const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
25728
+ const pkgPath = join6(this.cwd, "package.json");
25729
+ const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
25684
25730
  for (const field of ["module", "main", "source"]) {
25685
25731
  if (typeof pkg[field] === "string") {
25686
25732
  this.entryPointsCache.push(pkg[field].replace(/^\.\//, ""));
@@ -25716,7 +25762,7 @@ class RepoMap {
25716
25762
  "config.ru"
25717
25763
  ];
25718
25764
  for (const p2 of commonEntryPoints) {
25719
- if (existsSync3(join5(this.cwd, p2)))
25765
+ if (existsSync4(join6(this.cwd, p2)))
25720
25766
  this.entryPointsCache.push(p2);
25721
25767
  }
25722
25768
  return this.entryPointsCache;
@@ -25791,7 +25837,7 @@ class RepoMap {
25791
25837
  let lines = fileCache.get(row.path);
25792
25838
  if (!lines) {
25793
25839
  try {
25794
- const content = readFileSync2(join5(this.cwd, row.path), "utf-8");
25840
+ const content = readFileSync3(join6(this.cwd, row.path), "utf-8");
25795
25841
  lines = content.split(`
25796
25842
  `);
25797
25843
  fileCache.set(row.path, lines);
@@ -25874,11 +25920,11 @@ class RepoMap {
25874
25920
  const cachedMtime = existingById.get(sym.sym_id) ?? existingByKey.get(`${sym.file_path}\x00${sym.name}`);
25875
25921
  if (cachedMtime === sym.file_mtime)
25876
25922
  continue;
25877
- const absPath = join5(this.cwd, sym.file_path);
25923
+ const absPath = join6(this.cwd, sym.file_path);
25878
25924
  let code = "";
25879
25925
  let lineSpan = sym.end_line - sym.line;
25880
25926
  try {
25881
- const content = readFileSync2(absPath, "utf-8");
25927
+ const content = readFileSync3(absPath, "utf-8");
25882
25928
  const lines = content.split(`
25883
25929
  `);
25884
25930
  const startLine = Math.max(0, sym.line - 1);
@@ -26057,7 +26103,7 @@ class RepoMap {
26057
26103
  return;
26058
26104
  const files = this.db.query("SELECT path, mtime_ms FROM files").all();
26059
26105
  for (const f3 of files) {
26060
- const absPath = join5(this.cwd, f3.path);
26106
+ const absPath = join6(this.cwd, f3.path);
26061
26107
  try {
26062
26108
  const st = statSync(absPath);
26063
26109
  if (st.mtimeMs !== f3.mtime_ms) {
@@ -26079,7 +26125,7 @@ class RepoMap {
26079
26125
  for (let i4 = 0;i4 < filesWithImports.length; i4++) {
26080
26126
  const file = filesWithImports[i4];
26081
26127
  try {
26082
- const content = readFileSync2(join5(this.cwd, file.path), "utf-8");
26128
+ const content = readFileSync3(join6(this.cwd, file.path), "utf-8");
26083
26129
  fileContents.set(file.id, content.split(`
26084
26130
  `));
26085
26131
  } catch {}
@@ -26526,7 +26572,7 @@ class RepoMap {
26526
26572
  const results = [];
26527
26573
  const seenPaths = new Set;
26528
26574
  for (const row of rows) {
26529
- const absPath = join5(this.cwd, row.path);
26575
+ const absPath = join6(this.cwd, row.path);
26530
26576
  if (seenPaths.has(absPath))
26531
26577
  continue;
26532
26578
  seenPaths.add(absPath);
@@ -26620,7 +26666,7 @@ class RepoMap {
26620
26666
  if (seen.has(key2))
26621
26667
  continue;
26622
26668
  seen.add(key2);
26623
- const absPath = join5(this.cwd, row.path);
26669
+ const absPath = join6(this.cwd, row.path);
26624
26670
  try {
26625
26671
  const stat2 = statSync(absPath);
26626
26672
  if (Math.abs(stat2.mtimeMs - row.mtime_ms) > 1000)
@@ -26674,7 +26720,7 @@ class RepoMap {
26674
26720
  const rows = this.db.query("SELECT path, mtime_ms FROM files WHERE path LIKE ? ESCAPE '\\' ORDER BY pagerank DESC LIMIT ?").all(likePattern, limit);
26675
26721
  const results = [];
26676
26722
  for (const row of rows) {
26677
- const absPath = join5(this.cwd, row.path);
26723
+ const absPath = join6(this.cwd, row.path);
26678
26724
  try {
26679
26725
  const stat2 = statSync(absPath);
26680
26726
  if (Math.abs(stat2.mtimeMs - row.mtime_ms) > 1000)
@@ -26755,7 +26801,7 @@ class RepoMap {
26755
26801
  return trackable.map((row) => {
26756
26802
  let usedInternally = false;
26757
26803
  try {
26758
- const raw2 = readFileSync2(join5(this.cwd, row.path), "utf-8");
26804
+ const raw2 = readFileSync3(join6(this.cwd, row.path), "utf-8");
26759
26805
  const content = raw2.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/(["'`])(?:(?!\1|\\).|\\.)*\1/g, "").replace(/^\s*export\s+(type\s+)?\{[^}]*\}/gm, "");
26760
26806
  const re3 = new RegExp(`\\b${escaped(row.name)}\\b`, "g");
26761
26807
  const matches2 = content.match(re3);
@@ -26842,7 +26888,7 @@ class RepoMap {
26842
26888
  const importerDir = ref.file_path.substring(0, ref.file_path.lastIndexOf("/")) || ".";
26843
26889
  let resolved = ref.import_source;
26844
26890
  if (resolved.startsWith(".")) {
26845
- resolved = join5(importerDir, resolved).replace(/\\/g, "/");
26891
+ resolved = join6(importerDir, resolved).replace(/\\/g, "/");
26846
26892
  } else {
26847
26893
  const segments = resolved.replace(/^crate::/, "").split(/[:./]/);
26848
26894
  for (const seg of segments) {
@@ -27430,6 +27476,7 @@ class RepoMap {
27430
27476
  }
27431
27477
  }
27432
27478
  var init_repo_map = __esm(() => {
27479
+ init_ensure_soulforge_dir();
27433
27480
  init_clone_detection();
27434
27481
  init_repo_map_constants();
27435
27482
  init_repo_map_utils();
@@ -27487,8 +27534,8 @@ var exports_router = {};
27487
27534
  __export(exports_router, {
27488
27535
  CodeIntelligenceRouter: () => CodeIntelligenceRouter
27489
27536
  });
27490
- import { existsSync as existsSync4, readdirSync as readdirSync2 } from "fs";
27491
- import { extname as extname3, join as join6 } from "path";
27537
+ import { existsSync as existsSync5, readdirSync as readdirSync2 } from "fs";
27538
+ import { extname as extname3, join as join7 } from "path";
27492
27539
 
27493
27540
  class CodeIntelligenceRouter {
27494
27541
  backends = [];
@@ -27521,7 +27568,7 @@ class CodeIntelligenceRouter {
27521
27568
  if (this.detectedLanguage)
27522
27569
  return this.detectedLanguage;
27523
27570
  for (const [configFile, lang254] of Object.entries(PROJECT_FILE_TO_LANGUAGE)) {
27524
- if (existsSync4(join6(this.cwd, configFile))) {
27571
+ if (existsSync5(join7(this.cwd, configFile))) {
27525
27572
  this.detectedLanguage = lang254;
27526
27573
  return lang254;
27527
27574
  }
@@ -27646,7 +27693,7 @@ class CodeIntelligenceRouter {
27646
27693
  if (this.config.language)
27647
27694
  add(this.config.language);
27648
27695
  for (const [configFile, lang254] of Object.entries(PROJECT_FILE_TO_LANGUAGE)) {
27649
- if (existsSync4(join6(this.cwd, configFile)))
27696
+ if (existsSync5(join7(this.cwd, configFile)))
27650
27697
  add(lang254);
27651
27698
  }
27652
27699
  const SKIP = new Set(["node_modules", ".git", "dist", "build", "out", "vendor", "__pycache__", ".venv", "venv", "target", ".next", ".nuxt", ".output", "coverage", ".turbo", ".cache"]);
@@ -27682,7 +27729,7 @@ class CodeIntelligenceRouter {
27682
27729
  for (const entry of entries) {
27683
27730
  if (entry.isDirectory() && !SKIP.has(entry.name) && !entry.name.startsWith(".")) {
27684
27731
  queue.push({
27685
- dir: join6(item.dir, entry.name),
27732
+ dir: join7(item.dir, entry.name),
27686
27733
  depth: item.depth + 1
27687
27734
  });
27688
27735
  }
@@ -27719,14 +27766,14 @@ class CodeIntelligenceRouter {
27719
27766
  });
27720
27767
  for (const entry of entries) {
27721
27768
  if (entry.isFile() && exts.some((ext) => entry.name.endsWith(ext))) {
27722
- return join6(item.dir, entry.name);
27769
+ return join7(item.dir, entry.name);
27723
27770
  }
27724
27771
  }
27725
27772
  if (item.depth < MAX_DEPTH2) {
27726
27773
  for (const entry of entries) {
27727
27774
  if (entry.isDirectory() && !SKIP.has(entry.name) && !entry.name.startsWith(".")) {
27728
27775
  queue.push({
27729
- dir: join6(item.dir, entry.name),
27776
+ dir: join7(item.dir, entry.name),
27730
27777
  depth: item.depth + 1
27731
27778
  });
27732
27779
  }
@@ -28174,22 +28221,22 @@ var init_protocol = __esm(() => {
28174
28221
  });
28175
28222
 
28176
28223
  // src/config/index.ts
28177
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
28224
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
28178
28225
  import { homedir as homedir4 } from "os";
28179
- import { join as join7 } from "path";
28226
+ import { join as join8 } from "path";
28180
28227
  function loadConfig() {
28181
- if (!existsSync5(CONFIG_DIR)) {
28228
+ if (!existsSync6(CONFIG_DIR)) {
28182
28229
  mkdirSync2(CONFIG_DIR, {
28183
28230
  recursive: true,
28184
28231
  mode: 448
28185
28232
  });
28186
28233
  }
28187
- if (!existsSync5(CONFIG_FILE)) {
28188
- writeFileSync2(CONFIG_FILE, JSON.stringify(DEFAULT_CONFIG, null, 2));
28234
+ if (!existsSync6(CONFIG_FILE)) {
28235
+ writeFileSync3(CONFIG_FILE, JSON.stringify(DEFAULT_CONFIG, null, 2));
28189
28236
  return DEFAULT_CONFIG;
28190
28237
  }
28191
28238
  try {
28192
- const raw2 = readFileSync3(CONFIG_FILE, "utf-8");
28239
+ const raw2 = readFileSync4(CONFIG_FILE, "utf-8");
28193
28240
  return {
28194
28241
  ...DEFAULT_CONFIG,
28195
28242
  ...JSON.parse(raw2)
@@ -28201,11 +28248,11 @@ function loadConfig() {
28201
28248
  }
28202
28249
  }
28203
28250
  function loadProjectConfig(cwd) {
28204
- const projectFile = join7(cwd, ".soulforge", "config.json");
28205
- if (!existsSync5(projectFile))
28251
+ const projectFile = join8(cwd, ".soulforge", "config.json");
28252
+ if (!existsSync6(projectFile))
28206
28253
  return null;
28207
28254
  try {
28208
- const raw2 = readFileSync3(projectFile, "utf-8");
28255
+ const raw2 = readFileSync4(projectFile, "utf-8");
28209
28256
  return JSON.parse(raw2);
28210
28257
  } catch (err2) {
28211
28258
  process.stderr.write(`[soulforge] Failed to parse ${projectFile}: ${err2 instanceof Error ? err2.message : String(err2)} \u2014 ignoring project config
@@ -28215,8 +28262,9 @@ function loadProjectConfig(cwd) {
28215
28262
  }
28216
28263
  var CONFIG_DIR, CONFIG_FILE, DEFAULT_CONFIG;
28217
28264
  var init_config = __esm(() => {
28218
- CONFIG_DIR = join7(homedir4(), ".soulforge");
28219
- CONFIG_FILE = join7(CONFIG_DIR, "config.json");
28265
+ init_ensure_soulforge_dir();
28266
+ CONFIG_DIR = join8(homedir4(), ".soulforge");
28267
+ CONFIG_FILE = join8(CONFIG_DIR, "config.json");
28220
28268
  DEFAULT_CONFIG = {
28221
28269
  defaultModel: "none",
28222
28270
  routerRules: [],
@@ -28256,13 +28304,13 @@ var init_config = __esm(() => {
28256
28304
  });
28257
28305
 
28258
28306
  // src/core/intelligence/backends/lsp/server-registry.ts
28259
- import { execSync as execSync2 } from "child_process";
28260
- import { existsSync as existsSync6 } from "fs";
28307
+ import { execSync as execSync3 } from "child_process";
28308
+ import { existsSync as existsSync7 } from "fs";
28261
28309
  import { homedir as homedir5 } from "os";
28262
- import { join as join8 } from "path";
28310
+ import { join as join9 } from "path";
28263
28311
  function commandExists(cmd) {
28264
28312
  try {
28265
- execSync2(`command -v ${cmd}`, {
28313
+ execSync3(`command -v ${cmd}`, {
28266
28314
  stdio: "ignore"
28267
28315
  });
28268
28316
  return true;
@@ -28271,15 +28319,15 @@ function commandExists(cmd) {
28271
28319
  }
28272
28320
  }
28273
28321
  function commandExistsInMason(cmd) {
28274
- const fullPath = join8(MASON_BIN_DIR, cmd);
28275
- return existsSync6(fullPath) ? fullPath : null;
28322
+ const fullPath = join9(MASON_BIN_DIR, cmd);
28323
+ return existsSync7(fullPath) ? fullPath : null;
28276
28324
  }
28277
28325
  function findInSoulforge(cmd) {
28278
- const npmBin = join8(SOULFORGE_BIN_DIR, "node_modules", ".bin", cmd);
28279
- if (existsSync6(npmBin))
28326
+ const npmBin = join9(SOULFORGE_BIN_DIR, "node_modules", ".bin", cmd);
28327
+ if (existsSync7(npmBin))
28280
28328
  return npmBin;
28281
- const directBin = join8(SOULFORGE_BIN_DIR, "bin", cmd);
28282
- if (existsSync6(directBin))
28329
+ const directBin = join9(SOULFORGE_BIN_DIR, "bin", cmd);
28330
+ if (existsSync7(directBin))
28283
28331
  return directBin;
28284
28332
  return null;
28285
28333
  }
@@ -28482,8 +28530,8 @@ var init_server_registry = __esm(() => {
28482
28530
  args: ["--stdio"]
28483
28531
  }]
28484
28532
  };
28485
- MASON_BIN_DIR = join8(homedir5(), ".local", "share", "soulforge", "mason", "bin");
28486
- SOULFORGE_BIN_DIR = join8(homedir5(), ".soulforge", "lsp-servers");
28533
+ MASON_BIN_DIR = join9(homedir5(), ".local", "share", "soulforge", "mason", "bin");
28534
+ SOULFORGE_BIN_DIR = join9(homedir5(), ".soulforge", "lsp-servers");
28487
28535
  probeCache = new Map;
28488
28536
  });
28489
28537
 
@@ -29426,9 +29474,10 @@ function trackProcess(proc) {
29426
29474
  tracked.add(proc);
29427
29475
  proc.on("exit", () => tracked.delete(proc));
29428
29476
  }
29429
- var tracked;
29477
+ var tracked, trackedBun;
29430
29478
  var init_process_tracker = __esm(() => {
29431
29479
  tracked = new Set;
29480
+ trackedBun = new Set;
29432
29481
  });
29433
29482
 
29434
29483
  // src/core/intelligence/backends/lsp/standalone-client.ts
@@ -30038,9 +30087,9 @@ var exports_lsp = {};
30038
30087
  __export(exports_lsp, {
30039
30088
  LspBackend: () => LspBackend
30040
30089
  });
30041
- import { existsSync as existsSync7, readdirSync as readdirSync3 } from "fs";
30090
+ import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
30042
30091
  import { readdir as readdir2, readFile as readFile4 } from "fs/promises";
30043
- import { dirname as dirname3, join as join9, resolve as resolve5 } from "path";
30092
+ import { dirname as dirname3, join as join10, resolve as resolve5 } from "path";
30044
30093
  function getNvimBridge() {
30045
30094
  if (_nvimBridge === null) {
30046
30095
  try {
@@ -30067,18 +30116,18 @@ class LspBackend {
30067
30116
  async findAnchorFile() {
30068
30117
  const candidates = ["src/index.ts", "src/main.ts", "src/app.ts", "index.ts", "main.ts", "src/index.js", "src/main.js", "index.js", "main.py", "src/main.py", "main.go", "src/main.go", "src/lib.rs", "src/main.rs"];
30069
30118
  for (const candidate of candidates) {
30070
- const full = join9(this.cwd, candidate);
30071
- if (existsSync7(full))
30119
+ const full = join10(this.cwd, candidate);
30120
+ if (existsSync8(full))
30072
30121
  return full;
30073
30122
  }
30074
- for (const dir of [join9(this.cwd, "src"), this.cwd]) {
30075
- if (!existsSync7(dir))
30123
+ for (const dir of [join10(this.cwd, "src"), this.cwd]) {
30124
+ if (!existsSync8(dir))
30076
30125
  continue;
30077
30126
  try {
30078
30127
  const files = await readdir2(dir);
30079
30128
  const source = files.find((f3) => f3.endsWith(".ts") || f3.endsWith(".js") || f3.endsWith(".py") || f3.endsWith(".go") || f3.endsWith(".rs"));
30080
30129
  if (source)
30081
- return join9(dir, source);
30130
+ return join10(dir, source);
30082
30131
  } catch {}
30083
30132
  }
30084
30133
  return null;
@@ -31229,7 +31278,7 @@ function findProjectRootForLanguage(file, language) {
31229
31278
  } catch {}
31230
31279
  }
31231
31280
  for (const marker of nameMarkers) {
31232
- if (existsSync7(join9(dir, marker)))
31281
+ if (existsSync8(join10(dir, marker)))
31233
31282
  return dir;
31234
31283
  }
31235
31284
  dir = dirname3(dir);
@@ -201865,7 +201914,7 @@ var require_path_browserify = __commonJS((exports, module2) => {
201865
201914
  assertPath(path);
201866
201915
  return path.length > 0 && path.charCodeAt(0) === 47;
201867
201916
  },
201868
- join: function join10() {
201917
+ join: function join11() {
201869
201918
  if (arguments.length === 0)
201870
201919
  return ".";
201871
201920
  var joined;