@wrongstack/tools 0.298.3 → 0.299.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.
- package/dist/bash.js +14 -0
- package/dist/builtin.js +396 -0
- package/dist/codebase-index/background-indexer.d.ts +6 -1
- package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +34 -0
- package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +34 -0
- package/dist/codebase-index/index-service.d.ts +24 -2
- package/dist/codebase-index/index.d.ts +4 -2
- package/dist/codebase-index/index.js +382 -0
- package/dist/codebase-index/project-server.js +177 -1
- package/dist/codebase-index/schema.d.ts +23 -0
- package/dist/codebase-index/worker-protocol.d.ts +14 -0
- package/dist/codebase-index/worker.js +164 -0
- package/dist/codebase-index/writer-graph-reader.d.ts +24 -1
- package/dist/codebase-index/writer.d.ts +21 -1
- package/dist/exec.js +4 -0
- package/dist/index.js +396 -0
- package/dist/pack.js +394 -0
- package/dist/ps-slash.js +4 -0
- package/dist/read.js +164 -0
- package/dist/tool-tier.js +396 -0
- package/package.json +3 -3
package/dist/tool-tier.js
CHANGED
|
@@ -7082,6 +7082,10 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
|
7082
7082
|
const start = Date.now();
|
|
7083
7083
|
const pidStr = String(process.pid);
|
|
7084
7084
|
const hostStr = os2.hostname();
|
|
7085
|
+
try {
|
|
7086
|
+
await fs6.mkdir(path9.dirname(lockfilePath), { recursive: true });
|
|
7087
|
+
} catch {
|
|
7088
|
+
}
|
|
7085
7089
|
while (Date.now() - start < timeoutMs) {
|
|
7086
7090
|
try {
|
|
7087
7091
|
await fs6.writeFile(lockfilePath, `${pidStr}:${hostStr}:${Date.now()}`, { flag: "wx" });
|
|
@@ -7747,6 +7751,16 @@ function parseKillCommand(command) {
|
|
|
7747
7751
|
if (pgrepMatch) {
|
|
7748
7752
|
return null;
|
|
7749
7753
|
}
|
|
7754
|
+
const posixScriptMatch = normalized.match(SCRIPT_KILL_RE_POSIX);
|
|
7755
|
+
if (posixScriptMatch) {
|
|
7756
|
+
return {
|
|
7757
|
+
name: "kill-script",
|
|
7758
|
+
signal: "FORCE",
|
|
7759
|
+
isGroupKill: false,
|
|
7760
|
+
isAllKill: false,
|
|
7761
|
+
originalCommand: command
|
|
7762
|
+
};
|
|
7763
|
+
}
|
|
7750
7764
|
return null;
|
|
7751
7765
|
}
|
|
7752
7766
|
async function getProtectedEntries() {
|
|
@@ -10538,6 +10552,136 @@ function mapWriterRefRow(row) {
|
|
|
10538
10552
|
}
|
|
10539
10553
|
|
|
10540
10554
|
// src/codebase-index/writer-graph-reader.ts
|
|
10555
|
+
var MAX_SQL_VARS = 900;
|
|
10556
|
+
function chunkedIdQuery(stmt, ids, buildSql, extraArgs = []) {
|
|
10557
|
+
const results = [];
|
|
10558
|
+
for (let start = 0; start < ids.length; start += MAX_SQL_VARS) {
|
|
10559
|
+
const chunk = ids.slice(start, start + MAX_SQL_VARS);
|
|
10560
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
10561
|
+
const sql = buildSql(placeholders);
|
|
10562
|
+
results.push(...stmt(sql).all(...chunk, ...extraArgs));
|
|
10563
|
+
}
|
|
10564
|
+
return results;
|
|
10565
|
+
}
|
|
10566
|
+
function chunkedIdScalar(stmt, ids, buildSql, extraArgs = []) {
|
|
10567
|
+
let total = 0;
|
|
10568
|
+
for (let start = 0; start < ids.length; start += MAX_SQL_VARS) {
|
|
10569
|
+
const chunk = ids.slice(start, start + MAX_SQL_VARS);
|
|
10570
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
10571
|
+
const sql = buildSql(placeholders);
|
|
10572
|
+
const rows = stmt(sql).all(...chunk, ...extraArgs);
|
|
10573
|
+
total += rows[0]?.n ?? 0;
|
|
10574
|
+
}
|
|
10575
|
+
return total;
|
|
10576
|
+
}
|
|
10577
|
+
function mapCallSiteRow(row) {
|
|
10578
|
+
return {
|
|
10579
|
+
symbol: {
|
|
10580
|
+
id: row.sym_id,
|
|
10581
|
+
name: row.sym_name,
|
|
10582
|
+
kind: row.sym_kind,
|
|
10583
|
+
lang: row.sym_lang,
|
|
10584
|
+
file: row.sym_file,
|
|
10585
|
+
line: row.sym_line,
|
|
10586
|
+
signature: row.sym_signature
|
|
10587
|
+
},
|
|
10588
|
+
callType: row.call_type,
|
|
10589
|
+
line: row.ref_line
|
|
10590
|
+
};
|
|
10591
|
+
}
|
|
10592
|
+
function resolveSymbolIds(stmt, symbolName, file) {
|
|
10593
|
+
const baseSql = file ? `SELECT id FROM symbols WHERE name = ? AND file = ? ORDER BY id` : `SELECT id FROM symbols WHERE name = ? ORDER BY id`;
|
|
10594
|
+
const args = file ? [symbolName, file] : [symbolName];
|
|
10595
|
+
const rows = stmt(baseSql).all(...args);
|
|
10596
|
+
return rows.map((r) => r.id);
|
|
10597
|
+
}
|
|
10598
|
+
function findIncomingCallsByName(stmt, symbolName, file, limit) {
|
|
10599
|
+
const targetIds = resolveSymbolIds(stmt, symbolName, file);
|
|
10600
|
+
if (targetIds.length === 0) return { calls: [], symbolFound: false, ambiguous: false, totalMatches: 0 };
|
|
10601
|
+
let matchIds = targetIds;
|
|
10602
|
+
let ambiguous = false;
|
|
10603
|
+
if (file !== void 0) {
|
|
10604
|
+
const allNamedIds = resolveSymbolIds(stmt, symbolName, void 0);
|
|
10605
|
+
if (allNamedIds.length > targetIds.length) {
|
|
10606
|
+
matchIds = allNamedIds;
|
|
10607
|
+
ambiguous = true;
|
|
10608
|
+
}
|
|
10609
|
+
}
|
|
10610
|
+
const useFallback = !file;
|
|
10611
|
+
const rows = chunkedIdQuery(
|
|
10612
|
+
stmt,
|
|
10613
|
+
matchIds,
|
|
10614
|
+
(ph) => `SELECT
|
|
10615
|
+
s.id AS sym_id,
|
|
10616
|
+
s.name AS sym_name,
|
|
10617
|
+
s.kind AS sym_kind,
|
|
10618
|
+
s.lang AS sym_lang,
|
|
10619
|
+
s.file AS sym_file,
|
|
10620
|
+
s.line AS sym_line,
|
|
10621
|
+
s.signature AS sym_signature,
|
|
10622
|
+
r.call_type,
|
|
10623
|
+
r.line AS ref_line
|
|
10624
|
+
FROM refs r
|
|
10625
|
+
JOIN symbols s ON s.id = r.from_id
|
|
10626
|
+
WHERE r.to_id IN (${ph})
|
|
10627
|
+
ORDER BY r.line, r.id`,
|
|
10628
|
+
[]
|
|
10629
|
+
);
|
|
10630
|
+
if (useFallback) {
|
|
10631
|
+
const fallbackRows = stmt(
|
|
10632
|
+
`SELECT
|
|
10633
|
+
s.id AS sym_id,
|
|
10634
|
+
s.name AS sym_name,
|
|
10635
|
+
s.kind AS sym_kind,
|
|
10636
|
+
s.lang AS sym_lang,
|
|
10637
|
+
s.file AS sym_file,
|
|
10638
|
+
s.line AS sym_line,
|
|
10639
|
+
s.signature AS sym_signature,
|
|
10640
|
+
r.call_type,
|
|
10641
|
+
r.line AS ref_line
|
|
10642
|
+
FROM refs r
|
|
10643
|
+
JOIN symbols s ON s.id = r.from_id
|
|
10644
|
+
WHERE r.to_id IS NULL AND r.to_name = ?
|
|
10645
|
+
ORDER BY r.line, r.id`
|
|
10646
|
+
).all(symbolName);
|
|
10647
|
+
rows.push(...fallbackRows);
|
|
10648
|
+
}
|
|
10649
|
+
rows.sort((a, b) => a.ref_line - b.ref_line || a.sym_id - b.sym_id);
|
|
10650
|
+
const allCalls = rows.map(mapCallSiteRow);
|
|
10651
|
+
return { calls: allCalls.slice(0, limit), symbolFound: true, ambiguous, totalMatches: allCalls.length };
|
|
10652
|
+
}
|
|
10653
|
+
function findOutgoingCallsByName(stmt, symbolName, file, limit) {
|
|
10654
|
+
const sourceIds = resolveSymbolIds(stmt, symbolName, file);
|
|
10655
|
+
if (sourceIds.length === 0) return { calls: [], symbolFound: false, unresolvedCount: 0, totalMatches: 0 };
|
|
10656
|
+
const unresolvedCount = chunkedIdScalar(
|
|
10657
|
+
stmt,
|
|
10658
|
+
sourceIds,
|
|
10659
|
+
(ph) => `SELECT COUNT(*) AS n FROM refs WHERE from_id IN (${ph}) AND to_id IS NULL`
|
|
10660
|
+
);
|
|
10661
|
+
const rows = chunkedIdQuery(
|
|
10662
|
+
stmt,
|
|
10663
|
+
sourceIds,
|
|
10664
|
+
(ph) => `SELECT
|
|
10665
|
+
s.id AS sym_id,
|
|
10666
|
+
s.name AS sym_name,
|
|
10667
|
+
s.kind AS sym_kind,
|
|
10668
|
+
s.lang AS sym_lang,
|
|
10669
|
+
s.file AS sym_file,
|
|
10670
|
+
s.line AS sym_line,
|
|
10671
|
+
s.signature AS sym_signature,
|
|
10672
|
+
r.call_type,
|
|
10673
|
+
r.line AS ref_line
|
|
10674
|
+
FROM refs r
|
|
10675
|
+
JOIN symbols s ON s.id = r.to_id
|
|
10676
|
+
WHERE r.from_id IN (${ph})
|
|
10677
|
+
AND r.to_id IS NOT NULL -- INNER JOIN already excludes NULL to_id; this is defensive belt-and-suspenders
|
|
10678
|
+
ORDER BY r.line, r.id`,
|
|
10679
|
+
[]
|
|
10680
|
+
);
|
|
10681
|
+
rows.sort((a, b) => a.ref_line - b.ref_line || a.sym_id - b.sym_id);
|
|
10682
|
+
const calls = rows.map(mapCallSiteRow).slice(0, limit);
|
|
10683
|
+
return { calls, symbolFound: true, unresolvedCount, totalMatches: rows.length };
|
|
10684
|
+
}
|
|
10541
10685
|
function findRefsToWithStatement(stmt, symbolId) {
|
|
10542
10686
|
return stmt(
|
|
10543
10687
|
"SELECT id, from_id, to_name, to_id, call_type, line FROM refs WHERE to_id = ? OR to_name = (SELECT name FROM symbols WHERE id = ?)"
|
|
@@ -11773,6 +11917,20 @@ var IndexStore = class _IndexStore {
|
|
|
11773
11917
|
return false;
|
|
11774
11918
|
}
|
|
11775
11919
|
}
|
|
11920
|
+
/**
|
|
11921
|
+
* Find all symbols that reference the named target symbol (incoming callers).
|
|
11922
|
+
* Accepts a name instead of an id so the agent doesn't need a prior lookup.
|
|
11923
|
+
*/
|
|
11924
|
+
findIncomingCallsByName(symbolName, file, limit = 100) {
|
|
11925
|
+
return findIncomingCallsByName((sql) => this.stmt(sql), symbolName, file, limit);
|
|
11926
|
+
}
|
|
11927
|
+
/**
|
|
11928
|
+
* Find all symbols that the named source symbol references (outgoing callees).
|
|
11929
|
+
* Accepts a name instead of an id so the agent doesn't need a prior lookup.
|
|
11930
|
+
*/
|
|
11931
|
+
findOutgoingCallsByName(symbolName, file, limit = 100) {
|
|
11932
|
+
return findOutgoingCallsByName((sql) => this.stmt(sql), symbolName, file, limit);
|
|
11933
|
+
}
|
|
11776
11934
|
/**
|
|
11777
11935
|
* Find all references TO a given symbol (who calls / uses this symbol?).
|
|
11778
11936
|
*/
|
|
@@ -13155,6 +13313,22 @@ function symbolGraphService(args) {
|
|
|
13155
13313
|
indexStorePool.release(store);
|
|
13156
13314
|
}
|
|
13157
13315
|
}
|
|
13316
|
+
function incomingCallsService(args) {
|
|
13317
|
+
const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
|
|
13318
|
+
try {
|
|
13319
|
+
return store.findIncomingCallsByName(args.symbol, args.file, args.limit ?? 100);
|
|
13320
|
+
} finally {
|
|
13321
|
+
indexStorePool.release(store);
|
|
13322
|
+
}
|
|
13323
|
+
}
|
|
13324
|
+
function outgoingCallsService(args) {
|
|
13325
|
+
const store = indexStorePool.acquire(args.projectRoot, { indexDir: args.indexDir });
|
|
13326
|
+
try {
|
|
13327
|
+
return store.findOutgoingCallsByName(args.symbol, args.file, args.limit ?? 100);
|
|
13328
|
+
} finally {
|
|
13329
|
+
indexStorePool.release(store);
|
|
13330
|
+
}
|
|
13331
|
+
}
|
|
13158
13332
|
|
|
13159
13333
|
// src/codebase-index/background-indexer.ts
|
|
13160
13334
|
var DEFAULT_FULL_INDEX_TIMEOUT_MS = 24e4;
|
|
@@ -13366,6 +13540,10 @@ async function callInline(op, args, opts) {
|
|
|
13366
13540
|
return fileGraphService(args);
|
|
13367
13541
|
case "symbolGraph":
|
|
13368
13542
|
return symbolGraphService(args);
|
|
13543
|
+
case "incomingCalls":
|
|
13544
|
+
return incomingCallsService(args);
|
|
13545
|
+
case "outgoingCalls":
|
|
13546
|
+
return outgoingCallsService(args);
|
|
13369
13547
|
default:
|
|
13370
13548
|
throw new Error(`unknown index op: ${String(op)}`);
|
|
13371
13549
|
}
|
|
@@ -13461,6 +13639,12 @@ async function codebaseIndexStats(args, opts = {}) {
|
|
|
13461
13639
|
signal: opts.signal
|
|
13462
13640
|
});
|
|
13463
13641
|
}
|
|
13642
|
+
async function incomingCallsService2(args) {
|
|
13643
|
+
return callIndexOp("incomingCalls", args, { timeoutMs: DEFAULT_QUERY_TIMEOUT_MS });
|
|
13644
|
+
}
|
|
13645
|
+
async function outgoingCallsService2(args) {
|
|
13646
|
+
return callIndexOp("outgoingCalls", args, { timeoutMs: DEFAULT_QUERY_TIMEOUT_MS });
|
|
13647
|
+
}
|
|
13464
13648
|
|
|
13465
13649
|
// src/codebase-index/codebase-index-tool.ts
|
|
13466
13650
|
var codebaseIndexTool = {
|
|
@@ -13525,6 +13709,214 @@ var codebaseIndexTool = {
|
|
|
13525
13709
|
}
|
|
13526
13710
|
};
|
|
13527
13711
|
|
|
13712
|
+
// src/codebase-index/codebase-incoming-calls-tool.ts
|
|
13713
|
+
var codebaseIncomingCallsTool = {
|
|
13714
|
+
name: "codebase-incoming-calls",
|
|
13715
|
+
category: "Project",
|
|
13716
|
+
icon: "index",
|
|
13717
|
+
description: "Find all callers of a function, method, or symbol \u2014 who invokes or references it. Uses the codebase index ref graph for instant, exact results. Always use this instead of grep when checking impact of a change.",
|
|
13718
|
+
usageHint: 'CALL THIS BEFORE REFACTORING OR CHANGING ANY FUNCTION:\n\n- NEVER use grep or manual line reading to check where a function is called.\n- ALWAYS call codebase-incoming-calls({ symbol: "funcName" }) first.\n- Returns exact files, line numbers, caller signatures, and call types in milliseconds.\n- Use `file` to disambiguate when multiple symbols share a name.\n- Combine with codebase-outgoing-calls to see what the symbol itself calls.\nIf the index is not built, run codebase-index first.',
|
|
13719
|
+
permission: "auto",
|
|
13720
|
+
mutating: false,
|
|
13721
|
+
capabilities: ["fs.read"],
|
|
13722
|
+
timeoutMs: 35e3,
|
|
13723
|
+
inputSchema: {
|
|
13724
|
+
type: "object",
|
|
13725
|
+
properties: {
|
|
13726
|
+
symbol: {
|
|
13727
|
+
type: "string",
|
|
13728
|
+
description: "The function/method/type name to find callers for"
|
|
13729
|
+
},
|
|
13730
|
+
file: {
|
|
13731
|
+
type: "string",
|
|
13732
|
+
description: "Scope to a specific file when multiple symbols share the same name"
|
|
13733
|
+
},
|
|
13734
|
+
limit: {
|
|
13735
|
+
type: "integer",
|
|
13736
|
+
description: "Maximum call sites to return (default 50, max 200)",
|
|
13737
|
+
minimum: 1,
|
|
13738
|
+
maximum: 200
|
|
13739
|
+
}
|
|
13740
|
+
},
|
|
13741
|
+
required: ["symbol"]
|
|
13742
|
+
},
|
|
13743
|
+
async execute(input, ctx) {
|
|
13744
|
+
const state = getIndexState();
|
|
13745
|
+
if (state.indexing && !state.ready) {
|
|
13746
|
+
return {
|
|
13747
|
+
symbol: input.symbol,
|
|
13748
|
+
calls: [],
|
|
13749
|
+
total: 0,
|
|
13750
|
+
indexStatus: `Indexing in progress (${state.currentFile}/${state.totalFiles} files) \u2014 retry in a moment.`
|
|
13751
|
+
};
|
|
13752
|
+
}
|
|
13753
|
+
if (state.lastError) {
|
|
13754
|
+
const circuit = state.circuit;
|
|
13755
|
+
const retryHint = circuit.state === "open" ? `Indexing is paused (circuit open, retry in ${Math.ceil(circuit.cooldownRemainingMs / 1e3)}s).` : "Try /codebase-reindex.";
|
|
13756
|
+
return {
|
|
13757
|
+
symbol: input.symbol,
|
|
13758
|
+
calls: [],
|
|
13759
|
+
total: 0,
|
|
13760
|
+
indexStatus: `Index build failed: ${state.lastError}. ${retryHint}`
|
|
13761
|
+
};
|
|
13762
|
+
}
|
|
13763
|
+
const limit = Math.max(1, Math.min(Math.trunc(input.limit ?? 50), 200));
|
|
13764
|
+
const { calls, symbolFound, ambiguous, totalMatches } = await incomingCallsService2(
|
|
13765
|
+
{
|
|
13766
|
+
projectRoot: ctx.projectRoot,
|
|
13767
|
+
indexDir: codebaseIndexDirOverride(ctx),
|
|
13768
|
+
symbol: input.symbol,
|
|
13769
|
+
file: input.file,
|
|
13770
|
+
limit
|
|
13771
|
+
}
|
|
13772
|
+
);
|
|
13773
|
+
if (!symbolFound) {
|
|
13774
|
+
let hasPersistedIndex = state.ready;
|
|
13775
|
+
if (!hasPersistedIndex) {
|
|
13776
|
+
try {
|
|
13777
|
+
const stats = await codebaseIndexStats({
|
|
13778
|
+
projectRoot: ctx.projectRoot,
|
|
13779
|
+
indexDir: codebaseIndexDirOverride(ctx)
|
|
13780
|
+
});
|
|
13781
|
+
hasPersistedIndex = stats.totalFiles > 0 || stats.lastIndexed !== null;
|
|
13782
|
+
} catch {
|
|
13783
|
+
}
|
|
13784
|
+
}
|
|
13785
|
+
if (!hasPersistedIndex) {
|
|
13786
|
+
return {
|
|
13787
|
+
symbol: input.symbol,
|
|
13788
|
+
calls: [],
|
|
13789
|
+
total: 0,
|
|
13790
|
+
indexStatus: "No persisted index data found. Run codebase-index to build it."
|
|
13791
|
+
};
|
|
13792
|
+
}
|
|
13793
|
+
return {
|
|
13794
|
+
symbol: input.symbol,
|
|
13795
|
+
calls: [],
|
|
13796
|
+
total: 0,
|
|
13797
|
+
note: `Symbol "${input.symbol}" not found in the index. Use codebase-search to verify the name.`
|
|
13798
|
+
};
|
|
13799
|
+
}
|
|
13800
|
+
const notes = [];
|
|
13801
|
+
if (totalMatches > limit) {
|
|
13802
|
+
notes.push(`Results capped at ${limit} of ${totalMatches} call sites. Increase \`limit\` or use \`file\` to narrow.`);
|
|
13803
|
+
}
|
|
13804
|
+
if (ambiguous) {
|
|
13805
|
+
notes.push(`Symbol "${input.symbol}" exists in multiple files. Results include callers of all same-named symbols. Use codebase-search to find the exact file and pass it as \`file\`.`);
|
|
13806
|
+
}
|
|
13807
|
+
return {
|
|
13808
|
+
symbol: input.symbol,
|
|
13809
|
+
calls,
|
|
13810
|
+
total: calls.length,
|
|
13811
|
+
...notes.length > 0 ? { note: notes.join(" ") } : {}
|
|
13812
|
+
};
|
|
13813
|
+
}
|
|
13814
|
+
};
|
|
13815
|
+
|
|
13816
|
+
// src/codebase-index/codebase-outgoing-calls-tool.ts
|
|
13817
|
+
var codebaseOutgoingCallsTool = {
|
|
13818
|
+
name: "codebase-outgoing-calls",
|
|
13819
|
+
category: "Project",
|
|
13820
|
+
icon: "index",
|
|
13821
|
+
description: "Find all functions/methods/symbols that a given symbol calls or depends on \u2014 its callees. Uses the codebase index ref graph for instant, exact results. Use this to understand a function's dependencies before modifying it.",
|
|
13822
|
+
usageHint: 'USE THIS TO UNDERSTAND A FUNCTION\'S DEPENDENCIES:\n\n- Call codebase-outgoing-calls({ symbol: "funcName" }) to see everything it calls.\n- Returns exact files, line numbers, callee signatures, and call types in milliseconds.\n- Use `file` to disambiguate when multiple symbols share a name.\n- Pair with codebase-incoming-calls for a complete impact picture: incoming = who calls you, outgoing = what you call.\nIf the index is not built, run codebase-index first.',
|
|
13823
|
+
permission: "auto",
|
|
13824
|
+
mutating: false,
|
|
13825
|
+
capabilities: ["fs.read"],
|
|
13826
|
+
timeoutMs: 35e3,
|
|
13827
|
+
inputSchema: {
|
|
13828
|
+
type: "object",
|
|
13829
|
+
properties: {
|
|
13830
|
+
symbol: {
|
|
13831
|
+
type: "string",
|
|
13832
|
+
description: "The function/method/type name to find callees for"
|
|
13833
|
+
},
|
|
13834
|
+
file: {
|
|
13835
|
+
type: "string",
|
|
13836
|
+
description: "Scope to a specific file when multiple symbols share the same name"
|
|
13837
|
+
},
|
|
13838
|
+
limit: {
|
|
13839
|
+
type: "integer",
|
|
13840
|
+
description: "Maximum call sites to return (default 50, max 200)",
|
|
13841
|
+
minimum: 1,
|
|
13842
|
+
maximum: 200
|
|
13843
|
+
}
|
|
13844
|
+
},
|
|
13845
|
+
required: ["symbol"]
|
|
13846
|
+
},
|
|
13847
|
+
async execute(input, ctx) {
|
|
13848
|
+
const state = getIndexState();
|
|
13849
|
+
if (state.indexing && !state.ready) {
|
|
13850
|
+
return {
|
|
13851
|
+
symbol: input.symbol,
|
|
13852
|
+
calls: [],
|
|
13853
|
+
total: 0,
|
|
13854
|
+
indexStatus: `Indexing in progress (${state.currentFile}/${state.totalFiles} files) \u2014 retry in a moment.`
|
|
13855
|
+
};
|
|
13856
|
+
}
|
|
13857
|
+
if (state.lastError) {
|
|
13858
|
+
const circuit = state.circuit;
|
|
13859
|
+
const retryHint = circuit.state === "open" ? `Indexing is paused (circuit open, retry in ${Math.ceil(circuit.cooldownRemainingMs / 1e3)}s).` : "Try /codebase-reindex.";
|
|
13860
|
+
return {
|
|
13861
|
+
symbol: input.symbol,
|
|
13862
|
+
calls: [],
|
|
13863
|
+
total: 0,
|
|
13864
|
+
indexStatus: `Index build failed: ${state.lastError}. ${retryHint}`
|
|
13865
|
+
};
|
|
13866
|
+
}
|
|
13867
|
+
const limit = Math.max(1, Math.min(Math.trunc(input.limit ?? 50), 200));
|
|
13868
|
+
const { calls, symbolFound, unresolvedCount, totalMatches } = await outgoingCallsService2(
|
|
13869
|
+
{
|
|
13870
|
+
projectRoot: ctx.projectRoot,
|
|
13871
|
+
indexDir: codebaseIndexDirOverride(ctx),
|
|
13872
|
+
symbol: input.symbol,
|
|
13873
|
+
file: input.file,
|
|
13874
|
+
limit
|
|
13875
|
+
}
|
|
13876
|
+
);
|
|
13877
|
+
if (!symbolFound) {
|
|
13878
|
+
let hasPersistedIndex = state.ready;
|
|
13879
|
+
if (!hasPersistedIndex) {
|
|
13880
|
+
try {
|
|
13881
|
+
const stats = await codebaseIndexStats({
|
|
13882
|
+
projectRoot: ctx.projectRoot,
|
|
13883
|
+
indexDir: codebaseIndexDirOverride(ctx)
|
|
13884
|
+
});
|
|
13885
|
+
hasPersistedIndex = stats.totalFiles > 0 || stats.lastIndexed !== null;
|
|
13886
|
+
} catch {
|
|
13887
|
+
}
|
|
13888
|
+
}
|
|
13889
|
+
if (!hasPersistedIndex) {
|
|
13890
|
+
return {
|
|
13891
|
+
symbol: input.symbol,
|
|
13892
|
+
calls: [],
|
|
13893
|
+
total: 0,
|
|
13894
|
+
indexStatus: "No persisted index data found. Run codebase-index to build it."
|
|
13895
|
+
};
|
|
13896
|
+
}
|
|
13897
|
+
return {
|
|
13898
|
+
symbol: input.symbol,
|
|
13899
|
+
calls: [],
|
|
13900
|
+
total: 0,
|
|
13901
|
+
note: `Symbol "${input.symbol}" not found in the index. Use codebase-search to verify the name.`
|
|
13902
|
+
};
|
|
13903
|
+
}
|
|
13904
|
+
const notes = [];
|
|
13905
|
+
if (totalMatches > limit) {
|
|
13906
|
+
notes.push(`Results capped at ${limit} of ${totalMatches} call sites. Increase \`limit\` or use \`file\` to narrow.`);
|
|
13907
|
+
}
|
|
13908
|
+
if (unresolvedCount > 0) {
|
|
13909
|
+
notes.push(`${unresolvedCount} unresolved reference(s) not shown \u2014 their targets could not be resolved during indexing.`);
|
|
13910
|
+
}
|
|
13911
|
+
return {
|
|
13912
|
+
symbol: input.symbol,
|
|
13913
|
+
calls,
|
|
13914
|
+
total: calls.length,
|
|
13915
|
+
...notes.length > 0 ? { note: notes.join(" ") } : {}
|
|
13916
|
+
};
|
|
13917
|
+
}
|
|
13918
|
+
};
|
|
13919
|
+
|
|
13528
13920
|
// src/codebase-index/codebase-search-tool.ts
|
|
13529
13921
|
var codebaseSearchTool = {
|
|
13530
13922
|
name: "codebase-search",
|
|
@@ -24896,6 +25288,8 @@ var TIER1_TOOLS = [
|
|
|
24896
25288
|
editTool,
|
|
24897
25289
|
codebaseStatsTool,
|
|
24898
25290
|
codebaseSearchTool,
|
|
25291
|
+
codebaseIncomingCallsTool,
|
|
25292
|
+
codebaseOutgoingCallsTool,
|
|
24899
25293
|
codebaseIndexTool,
|
|
24900
25294
|
bashTool,
|
|
24901
25295
|
grepTool,
|
|
@@ -24946,6 +25340,8 @@ var builtinTools = [
|
|
|
24946
25340
|
editTool,
|
|
24947
25341
|
codebaseStatsTool,
|
|
24948
25342
|
codebaseSearchTool,
|
|
25343
|
+
codebaseIncomingCallsTool,
|
|
25344
|
+
codebaseOutgoingCallsTool,
|
|
24949
25345
|
codebaseIndexTool,
|
|
24950
25346
|
deadCodeScanTool,
|
|
24951
25347
|
replaceTool,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.299.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack built-in tools: read/write/edit, bash/exec, grep/glob, git, fetch, test, lint, and more.",
|
|
6
6
|
"repository": {
|
|
@@ -250,8 +250,8 @@
|
|
|
250
250
|
"@typescript/typescript6": "^6.0.2",
|
|
251
251
|
"turndown": "^7.2.4",
|
|
252
252
|
"undici": "^8.9.0",
|
|
253
|
-
"@wrongstack/core": "0.
|
|
254
|
-
"@wrongstack/kanban": "0.
|
|
253
|
+
"@wrongstack/core": "0.299.0",
|
|
254
|
+
"@wrongstack/kanban": "0.299.0"
|
|
255
255
|
},
|
|
256
256
|
"devDependencies": {
|
|
257
257
|
"@types/node": "^26.1.2",
|