agentsbestfriend 0.1.3 → 0.2.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/index.js +119 -31
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5,16 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
-
}) : x)(function(x) {
|
|
11
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
-
});
|
|
14
8
|
var __esm = (fn, res) => function __init() {
|
|
15
9
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
16
10
|
};
|
|
17
|
-
var __commonJS = (cb, mod) => function
|
|
11
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
18
12
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
13
|
};
|
|
20
14
|
var __export = (target, all) => {
|
|
@@ -18065,9 +18059,52 @@ Summary:`;
|
|
|
18065
18059
|
// ../core/dist/llm/pipelines.js
|
|
18066
18060
|
import { readFile } from "fs/promises";
|
|
18067
18061
|
import { join as join4 } from "path";
|
|
18062
|
+
async function generateSummaries(projectRoot, opts) {
|
|
18063
|
+
const start = Date.now();
|
|
18064
|
+
const provider = getLlmProvider();
|
|
18065
|
+
if (!provider) {
|
|
18066
|
+
throw new LlmUnavailableError("none", "LLM provider is set to 'none'");
|
|
18067
|
+
}
|
|
18068
|
+
if (!await provider.isAvailable()) {
|
|
18069
|
+
throw new LlmUnavailableError(provider.name, "Cannot reach Ollama. Is it running?");
|
|
18070
|
+
}
|
|
18071
|
+
const db = createProjectDb(projectRoot);
|
|
18072
|
+
const stats = {
|
|
18073
|
+
generated: 0,
|
|
18074
|
+
skipped: 0,
|
|
18075
|
+
errors: 0,
|
|
18076
|
+
durationMs: 0
|
|
18077
|
+
};
|
|
18078
|
+
try {
|
|
18079
|
+
const rows = opts?.force ? db.select({ id: files.id, path: files.path }).from(files).all() : db.select({ id: files.id, path: files.path }).from(files).where(isNull(files.summary)).all();
|
|
18080
|
+
const batchSize = opts?.batchSize ?? 5;
|
|
18081
|
+
for (let i = 0; i < rows.length; i += batchSize) {
|
|
18082
|
+
const batch = rows.slice(i, i + batchSize);
|
|
18083
|
+
for (const row of batch) {
|
|
18084
|
+
try {
|
|
18085
|
+
const absPath = join4(projectRoot, row.path);
|
|
18086
|
+
const content = await readFile(absPath, "utf-8");
|
|
18087
|
+
const summary = await provider.generateSummary(content, row.path);
|
|
18088
|
+
db.update(files).set({ summary }).where(eq(files.id, row.id)).run();
|
|
18089
|
+
stats.generated++;
|
|
18090
|
+
} catch (err) {
|
|
18091
|
+
if (err instanceof LlmUnavailableError)
|
|
18092
|
+
throw err;
|
|
18093
|
+
stats.errors++;
|
|
18094
|
+
}
|
|
18095
|
+
}
|
|
18096
|
+
}
|
|
18097
|
+
stats.skipped = rows.length === 0 ? db.select({ id: files.id }).from(files).all().length : 0;
|
|
18098
|
+
stats.durationMs = Date.now() - start;
|
|
18099
|
+
return stats;
|
|
18100
|
+
} finally {
|
|
18101
|
+
closeDb(db);
|
|
18102
|
+
}
|
|
18103
|
+
}
|
|
18068
18104
|
var init_pipelines = __esm({
|
|
18069
18105
|
"../core/dist/llm/pipelines.js"() {
|
|
18070
18106
|
"use strict";
|
|
18107
|
+
init_drizzle_orm();
|
|
18071
18108
|
init_connection();
|
|
18072
18109
|
init_schema2();
|
|
18073
18110
|
init_llm();
|
|
@@ -18177,7 +18214,7 @@ var init_search = __esm({
|
|
|
18177
18214
|
|
|
18178
18215
|
// ../core/dist/utils/index.js
|
|
18179
18216
|
import { createHash } from "crypto";
|
|
18180
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
18217
|
+
import { readFileSync as readFileSync3, openSync, readSync, closeSync } from "fs";
|
|
18181
18218
|
import { extname } from "path";
|
|
18182
18219
|
function hashFileContent(content) {
|
|
18183
18220
|
return createHash("sha256").update(content, "utf-8").digest("hex");
|
|
@@ -18267,9 +18304,9 @@ function countLines(content) {
|
|
|
18267
18304
|
function isBinaryFile(filePath) {
|
|
18268
18305
|
try {
|
|
18269
18306
|
const buffer = Buffer.alloc(8192);
|
|
18270
|
-
const fd =
|
|
18271
|
-
const bytesRead =
|
|
18272
|
-
|
|
18307
|
+
const fd = openSync(filePath, "r");
|
|
18308
|
+
const bytesRead = readSync(fd, buffer, 0, 8192, 0);
|
|
18309
|
+
closeSync(fd);
|
|
18273
18310
|
for (let i = 0; i < bytesRead; i++) {
|
|
18274
18311
|
if (buffer[i] === 0)
|
|
18275
18312
|
return true;
|
|
@@ -44523,7 +44560,7 @@ function registerGitTool(server) {
|
|
|
44523
44560
|
line_start: external_exports3.number().int().optional().describe("Start line for blame range"),
|
|
44524
44561
|
line_end: external_exports3.number().int().optional().describe("End line for blame range")
|
|
44525
44562
|
}, async ({ action, file: file2, count, line_start, line_end }) => {
|
|
44526
|
-
const cwd = process.cwd();
|
|
44563
|
+
const cwd = process.env.ABF_PROJECT_ROOT || process.cwd();
|
|
44527
44564
|
if (!await isGitRepo(cwd)) {
|
|
44528
44565
|
return {
|
|
44529
44566
|
content: [
|
|
@@ -44601,16 +44638,17 @@ function errorResult(msg) {
|
|
|
44601
44638
|
|
|
44602
44639
|
// ../server/dist/tools/index-tool.js
|
|
44603
44640
|
init_indexer();
|
|
44604
|
-
|
|
44641
|
+
init_llm();
|
|
44642
|
+
var IndexActionSchema = external_exports3.enum(["status", "rebuild", "update", "summarize"]);
|
|
44605
44643
|
function registerIndexTool(server) {
|
|
44606
|
-
server.tool("abf_index", "Manage the file index: check status, trigger rebuild, or
|
|
44607
|
-
action: IndexActionSchema.describe("status: show index info, rebuild: full re-index, update: incremental update")
|
|
44644
|
+
server.tool("abf_index", "Manage the file index: check status, trigger rebuild, incremental update, or generate LLM summaries (requires Ollama).", {
|
|
44645
|
+
action: IndexActionSchema.describe("status: show index info, rebuild: full re-index, update: incremental update, summarize: generate LLM file summaries (requires Ollama)")
|
|
44608
44646
|
}, async ({ action }) => {
|
|
44609
|
-
const
|
|
44647
|
+
const projectRoot = process.env.ABF_PROJECT_ROOT || process.cwd();
|
|
44610
44648
|
try {
|
|
44611
44649
|
switch (action) {
|
|
44612
44650
|
case "status": {
|
|
44613
|
-
const status = await getIndexStatus(
|
|
44651
|
+
const status = await getIndexStatus(projectRoot);
|
|
44614
44652
|
const lastUp = status.lastUpdated ? status.lastUpdated.toISOString() : "never";
|
|
44615
44653
|
const sizeMb = (status.indexSizeBytes / (1024 * 1024)).toFixed(2);
|
|
44616
44654
|
const text4 = [
|
|
@@ -44623,7 +44661,7 @@ function registerIndexTool(server) {
|
|
|
44623
44661
|
}
|
|
44624
44662
|
case "rebuild":
|
|
44625
44663
|
case "update": {
|
|
44626
|
-
const stats = await runIndexPipeline(
|
|
44664
|
+
const stats = await runIndexPipeline(projectRoot);
|
|
44627
44665
|
const text4 = [
|
|
44628
44666
|
`Index ${action} complete (${stats.durationMs}ms)`,
|
|
44629
44667
|
`Discovered: ${stats.totalDiscovered}`,
|
|
@@ -44635,6 +44673,16 @@ function registerIndexTool(server) {
|
|
|
44635
44673
|
].filter(Boolean).join("\n");
|
|
44636
44674
|
return { content: [{ type: "text", text: text4 }] };
|
|
44637
44675
|
}
|
|
44676
|
+
case "summarize": {
|
|
44677
|
+
const stats = await generateSummaries(projectRoot);
|
|
44678
|
+
const text4 = [
|
|
44679
|
+
`Summary generation complete (${stats.durationMs}ms)`,
|
|
44680
|
+
`Generated: ${stats.generated}`,
|
|
44681
|
+
`Skipped (already have summary): ${stats.skipped}`,
|
|
44682
|
+
stats.errors > 0 ? `Errors: ${stats.errors}` : null
|
|
44683
|
+
].filter(Boolean).join("\n");
|
|
44684
|
+
return { content: [{ type: "text", text: text4 }] };
|
|
44685
|
+
}
|
|
44638
44686
|
}
|
|
44639
44687
|
} catch (err) {
|
|
44640
44688
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -44653,7 +44701,7 @@ function registerSymbolsTool(server) {
|
|
|
44653
44701
|
file_path: external_exports3.string().describe("Path to the file (relative or absolute)"),
|
|
44654
44702
|
depth: external_exports3.number().int().min(1).max(5).default(2).describe("How deep to show nested symbols")
|
|
44655
44703
|
}, async ({ file_path, depth }) => {
|
|
44656
|
-
const cwd = process.cwd();
|
|
44704
|
+
const cwd = process.env.ABF_PROJECT_ROOT || process.cwd();
|
|
44657
44705
|
const absPath = file_path.startsWith("/") ? file_path : join9(cwd, file_path);
|
|
44658
44706
|
try {
|
|
44659
44707
|
const content = readFileSync6(absPath, "utf-8");
|
|
@@ -44695,17 +44743,43 @@ function formatSymbolTree(symbols2, maxDepth, currentDepth) {
|
|
|
44695
44743
|
import { readFileSync as readFileSync7 } from "fs";
|
|
44696
44744
|
import { join as join10 } from "path";
|
|
44697
44745
|
function registerChunkTool(server) {
|
|
44698
|
-
server.tool("abf_chunk",
|
|
44699
|
-
|
|
44700
|
-
|
|
44701
|
-
|
|
44702
|
-
|
|
44703
|
-
|
|
44746
|
+
server.tool("abf_chunk", `Smart file chunking by symbol boundaries. Returns actual source code.
|
|
44747
|
+
Use EXACTLY ONE of these modes:
|
|
44748
|
+
- symbol: pass a symbol name to get its full source code directly
|
|
44749
|
+
- chunk_index: pass a 0-based chunk index to get that chunk's code
|
|
44750
|
+
- (neither): returns a chunk overview listing \u2014 use this first to discover available chunks, then call again with chunk_index to retrieve code`, {
|
|
44751
|
+
file_path: external_exports3.string().describe("Path to the file (relative or absolute)"),
|
|
44752
|
+
chunk_index: external_exports3.number().int().min(0).optional().describe("0-based chunk index to retrieve that chunk's source code. Get the index from the overview first."),
|
|
44753
|
+
symbol: external_exports3.string().optional().describe("Name of a symbol (function, class, etc.) to retrieve its full source code directly.")
|
|
44754
|
+
}, async ({ file_path, chunk_index, symbol: symbol2 }) => {
|
|
44755
|
+
const projectRoot = process.env.ABF_PROJECT_ROOT || process.cwd();
|
|
44756
|
+
const absPath = file_path.startsWith("/") ? file_path : join10(projectRoot, file_path);
|
|
44704
44757
|
try {
|
|
44705
44758
|
const content = readFileSync7(absPath, "utf-8");
|
|
44706
44759
|
const lines = content.split("\n");
|
|
44707
|
-
const { symbols:
|
|
44708
|
-
|
|
44760
|
+
const { symbols: parsedSymbols } = parseFile(absPath, content);
|
|
44761
|
+
if (symbol2) {
|
|
44762
|
+
const match = findSymbol(parsedSymbols, symbol2);
|
|
44763
|
+
if (!match) {
|
|
44764
|
+
const available = parsedSymbols.map((s) => `${s.kind} ${s.name}`).join(", ");
|
|
44765
|
+
return {
|
|
44766
|
+
content: [
|
|
44767
|
+
{
|
|
44768
|
+
type: "text",
|
|
44769
|
+
text: `Symbol "${symbol2}" not found in ${file_path}. Available: ${available || "(none)"}`
|
|
44770
|
+
}
|
|
44771
|
+
]
|
|
44772
|
+
};
|
|
44773
|
+
}
|
|
44774
|
+
const chunkLines = lines.slice(match.startLine - 1, match.endLine);
|
|
44775
|
+
const text5 = [
|
|
44776
|
+
`${match.kind} ${match.name} (L${match.startLine}-${match.endLine})`,
|
|
44777
|
+
"---",
|
|
44778
|
+
...chunkLines
|
|
44779
|
+
].join("\n");
|
|
44780
|
+
return { content: [{ type: "text", text: text5 }] };
|
|
44781
|
+
}
|
|
44782
|
+
const chunks = buildChunks(parsedSymbols, lines.length);
|
|
44709
44783
|
if (chunk_index !== void 0) {
|
|
44710
44784
|
if (chunk_index < 0 || chunk_index >= chunks.length) {
|
|
44711
44785
|
return {
|
|
@@ -44728,7 +44802,9 @@ function registerChunkTool(server) {
|
|
|
44728
44802
|
}
|
|
44729
44803
|
const overview = chunks.map((c, i) => `[${i}] ${c.label} L${c.startLine}-${c.endLine} (${c.endLine - c.startLine + 1} lines)`).join("\n");
|
|
44730
44804
|
const text4 = `${chunks.length} chunks in ${file_path}:
|
|
44731
|
-
${overview}
|
|
44805
|
+
${overview}
|
|
44806
|
+
|
|
44807
|
+
To get source code, call again with chunk_index=<number> or symbol=<name>.`;
|
|
44732
44808
|
return { content: [{ type: "text", text: text4 }] };
|
|
44733
44809
|
} catch (err) {
|
|
44734
44810
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -44736,6 +44812,18 @@ ${overview}`;
|
|
|
44736
44812
|
}
|
|
44737
44813
|
});
|
|
44738
44814
|
}
|
|
44815
|
+
function findSymbol(symbols2, name) {
|
|
44816
|
+
const lower = name.toLowerCase();
|
|
44817
|
+
for (const sym of symbols2) {
|
|
44818
|
+
if (sym.name.toLowerCase() === lower)
|
|
44819
|
+
return sym;
|
|
44820
|
+
for (const child of sym.children) {
|
|
44821
|
+
if (child.name.toLowerCase() === lower)
|
|
44822
|
+
return child;
|
|
44823
|
+
}
|
|
44824
|
+
}
|
|
44825
|
+
return void 0;
|
|
44826
|
+
}
|
|
44739
44827
|
var MAX_CHUNK_LINES = 200;
|
|
44740
44828
|
function buildChunks(symbols2, totalLines) {
|
|
44741
44829
|
if (symbols2.length === 0) {
|
|
@@ -44811,13 +44899,14 @@ function buildChunks(symbols2, totalLines) {
|
|
|
44811
44899
|
import { readFileSync as readFileSync8 } from "fs";
|
|
44812
44900
|
import { join as join11, dirname, resolve } from "path";
|
|
44813
44901
|
import { existsSync as existsSync4 } from "fs";
|
|
44902
|
+
import { execFileSync } from "child_process";
|
|
44814
44903
|
function registerDependenciesTool(server) {
|
|
44815
44904
|
server.tool("abf_dependencies", "Show imports and reverse dependencies (imported_by) for a file.", {
|
|
44816
44905
|
file_path: external_exports3.string().describe("Path to the file"),
|
|
44817
44906
|
direction: external_exports3.enum(["imports", "imported_by", "both"]).default("both").describe("Which direction to analyze"),
|
|
44818
44907
|
depth: external_exports3.number().int().min(1).max(3).default(1).describe("Depth of transitive dependencies")
|
|
44819
44908
|
}, async ({ file_path, direction, depth }) => {
|
|
44820
|
-
const cwd = process.cwd();
|
|
44909
|
+
const cwd = process.env.ABF_PROJECT_ROOT || process.cwd();
|
|
44821
44910
|
const absPath = file_path.startsWith("/") ? file_path : join11(cwd, file_path);
|
|
44822
44911
|
const relPath = file_path.startsWith("/") ? file_path.slice(cwd.length + 1) : file_path;
|
|
44823
44912
|
try {
|
|
@@ -44883,7 +44972,6 @@ function tryResolve(importPath, fromDir) {
|
|
|
44883
44972
|
return null;
|
|
44884
44973
|
}
|
|
44885
44974
|
function findImportedBy(cwd, targetRelPath) {
|
|
44886
|
-
const { execFileSync } = __require("child_process");
|
|
44887
44975
|
let filePaths;
|
|
44888
44976
|
try {
|
|
44889
44977
|
const stdout = execFileSync("git", ["ls-files", "--cached", "--others", "--exclude-standard"], { cwd, maxBuffer: 10 * 1024 * 1024 }).toString();
|
|
@@ -44944,7 +45032,7 @@ function registerImpactTool(server) {
|
|
|
44944
45032
|
symbol_name: external_exports3.string().describe("The symbol (function, class, variable) name to find references for"),
|
|
44945
45033
|
file_path: external_exports3.string().optional().describe("Optional: scope search to usages of this symbol from this file")
|
|
44946
45034
|
}, async ({ symbol_name, file_path }) => {
|
|
44947
|
-
const cwd = process.cwd();
|
|
45035
|
+
const cwd = process.env.ABF_PROJECT_ROOT || process.cwd();
|
|
44948
45036
|
try {
|
|
44949
45037
|
const results = await ripgrepSearch({
|
|
44950
45038
|
query: `\\b${escapeRegex2(symbol_name)}\\b`,
|