@bike4mind/cli 0.2.24-recent-changes-tool.18468 → 0.2.24-sessions-command-bug-fix.18477
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/README.md +0 -31
- package/dist/{artifactExtractor-HH6SPW2Y.js → artifactExtractor-JZ5EU5YH.js} +1 -1
- package/dist/{chunk-QCZ7HG2D.js → chunk-FV2VQXYX.js} +2 -2
- package/dist/{chunk-SWBK52BT.js → chunk-GGQZHK5U.js} +2 -2
- package/dist/{chunk-5ACUY24Z.js → chunk-JHCQOESZ.js} +2 -2
- package/dist/{chunk-37CKEEXO.js → chunk-LOIWIBZT.js} +10 -1
- package/dist/{chunk-KC235R6G.js → chunk-XFN2ICKP.js} +1 -1
- package/dist/{create-NFJ2IEUS.js → create-DOGMZSYL.js} +3 -3
- package/dist/index.js +132 -424
- package/dist/{llmMarkdownGenerator-YHN4RQB6.js → llmMarkdownGenerator-XTKTGXLR.js} +1 -1
- package/dist/{markdownGenerator-ZVU573OI.js → markdownGenerator-BPNTWLQB.js} +1 -1
- package/dist/{mementoService-2FHVYTAF.js → mementoService-65C2EYD5.js} +3 -3
- package/dist/{src-HB3OM6ZM.js → src-FB7KXX74.js} +2 -2
- package/dist/{src-KVNL3XAU.js → src-SWWFC3US.js} +1 -1
- package/dist/{subtractCredits-UHBYJNNY.js → subtractCredits-GEE7TE3Y.js} +3 -3
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -183,7 +183,6 @@ export SERPER_API_KEY="your-key-here"
|
|
|
183
183
|
- ✅ `current_datetime` - No API key needed
|
|
184
184
|
- ✅ `prompt_enhancement` - No API key needed
|
|
185
185
|
- ✅ `bash_execute` - No API key needed
|
|
186
|
-
- ✅ `recent_changes` - No API key needed (git-based file search by modification time)
|
|
187
186
|
- 🔑 `weather_info` - Requires `toolApiKeys.openweather`
|
|
188
187
|
- 🔑 `web_search` - Requires `toolApiKeys.serper`
|
|
189
188
|
- 🔑 `deep_research` - Requires `toolApiKeys.serper`
|
|
@@ -265,36 +264,6 @@ You can also run any MCP server via npx or custom executables:
|
|
|
265
264
|
|
|
266
265
|
**Note:** Internal MCP servers must be built and available in the `b4m-core/packages/mcp/dist/src/` directory. The CLI will automatically find them if you're running from the monorepo. For Docker-based servers, ensure Docker is installed and the image is accessible.
|
|
267
266
|
|
|
268
|
-
## Git-Aware Code Search
|
|
269
|
-
|
|
270
|
-
The CLI includes a `recent_changes` tool that uses git history to find recently modified files. This significantly speeds up debugging by narrowing the search space to recently changed code.
|
|
271
|
-
|
|
272
|
-
### Use Cases
|
|
273
|
-
|
|
274
|
-
- **Recent bug debugging:** "I just broke something, can you help fix it?"
|
|
275
|
-
- **Understanding feature development:** "What did we change for the new dashboard?"
|
|
276
|
-
- **Finding active development areas:** "What are we actively working on?"
|
|
277
|
-
- **Code review prep:** "What changed since last release?"
|
|
278
|
-
|
|
279
|
-
### Parameters
|
|
280
|
-
|
|
281
|
-
- `since` - Time range to search (default: "7 days ago")
|
|
282
|
-
- Examples: "2 hours ago", "3 days ago", "2025-01-01"
|
|
283
|
-
- `path` - Filter to specific directory (default: entire repo)
|
|
284
|
-
- Examples: "src/components", "apps/client", "**/*.test.ts"
|
|
285
|
-
- `limit` - Maximum files to return (default: 50)
|
|
286
|
-
- `include_stats` - Show lines added/removed (default: false)
|
|
287
|
-
|
|
288
|
-
### How It Works
|
|
289
|
-
|
|
290
|
-
The tool uses `git log` to track file modifications and returns:
|
|
291
|
-
- Files sorted by activity (most commits first)
|
|
292
|
-
- Commit messages for context
|
|
293
|
-
- Optional statistics showing lines changed
|
|
294
|
-
- Filtered results based on time and path
|
|
295
|
-
|
|
296
|
-
**Performance benefit:** Instead of searching 50+ files (5-10 minutes), find the 3 relevant files in ~30 seconds.
|
|
297
|
-
|
|
298
267
|
## Context Files
|
|
299
268
|
|
|
300
269
|
The CLI supports loading project-specific instructions from context files, similar to CLAUDE.md in Claude Code. These files provide persistent instructions that are automatically included in the agent's system prompt.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CurationArtifactType
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LOIWIBZT.js";
|
|
5
5
|
|
|
6
6
|
// ../../b4m-core/packages/services/dist/src/notebookCurationService/artifactExtractor.js
|
|
7
7
|
var ARTIFACT_TAG_REGEX = /<artifact\s+(.*?)>([\s\S]*?)<\/artifact>/gi;
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
getSettingsByNames,
|
|
7
7
|
obfuscateApiKey,
|
|
8
8
|
secureParameters
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XFN2ICKP.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiKeyType,
|
|
12
12
|
MementoTier,
|
|
13
13
|
isSupportedEmbeddingModel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-LOIWIBZT.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
getSettingsMap,
|
|
8
8
|
getSettingsValue,
|
|
9
9
|
secureParameters
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XFN2ICKP.js";
|
|
11
11
|
import {
|
|
12
12
|
KnowledgeType,
|
|
13
13
|
SupportedFabFileMimeTypes
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-LOIWIBZT.js";
|
|
15
15
|
|
|
16
16
|
// ../../b4m-core/packages/services/dist/src/fabFileService/create.js
|
|
17
17
|
import { z } from "zod";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BadRequestError,
|
|
4
4
|
secureParameters
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XFN2ICKP.js";
|
|
6
6
|
import {
|
|
7
7
|
CompletionApiUsageTransaction,
|
|
8
8
|
GenericCreditDeductTransaction,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
TextGenerationUsageTransaction,
|
|
13
13
|
TransferCreditTransaction,
|
|
14
14
|
VideoGenerationUsageTransaction
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-LOIWIBZT.js";
|
|
16
16
|
|
|
17
17
|
// ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
|
|
18
18
|
import { z } from "zod";
|
|
@@ -303,8 +303,17 @@ var b4mLLMTools = z5.enum([
|
|
|
303
303
|
"sunrise_sunset",
|
|
304
304
|
"iss_tracker",
|
|
305
305
|
"planet_visibility",
|
|
306
|
+
// File operation tools
|
|
307
|
+
"file_read",
|
|
308
|
+
"create_file",
|
|
309
|
+
"edit_local_file",
|
|
310
|
+
"glob_files",
|
|
311
|
+
"grep_search",
|
|
312
|
+
"delete_file",
|
|
306
313
|
// Knowledge base search
|
|
307
|
-
"search_knowledge_base"
|
|
314
|
+
"search_knowledge_base",
|
|
315
|
+
// Shell execution
|
|
316
|
+
"bash_execute"
|
|
308
317
|
]);
|
|
309
318
|
var B4MLLMToolsList = b4mLLMTools.options.map((tool) => tool);
|
|
310
319
|
var RechartsChartTypeSchema = z5.enum([
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFabFile,
|
|
4
4
|
createFabFileSchema
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-GGQZHK5U.js";
|
|
6
|
+
import "./chunk-XFN2ICKP.js";
|
|
7
|
+
import "./chunk-LOIWIBZT.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
createFabFile,
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
getEffectiveApiKey,
|
|
5
5
|
getOpenWeatherKey,
|
|
6
6
|
getSerperKey
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FV2VQXYX.js";
|
|
8
8
|
import {
|
|
9
9
|
ConfigStore
|
|
10
10
|
} from "./chunk-23T2XGSZ.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-JHCQOESZ.js";
|
|
12
|
+
import "./chunk-GGQZHK5U.js";
|
|
13
13
|
import {
|
|
14
14
|
BFLImageService,
|
|
15
15
|
BaseStorage,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
OpenAIBackend,
|
|
22
22
|
OpenAIImageService,
|
|
23
23
|
XAIImageService
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-XFN2ICKP.js";
|
|
25
25
|
import {
|
|
26
26
|
AiEvents,
|
|
27
27
|
ApiKeyEvents,
|
|
@@ -77,7 +77,7 @@ import {
|
|
|
77
77
|
XAI_IMAGE_MODELS,
|
|
78
78
|
b4mLLMTools,
|
|
79
79
|
getMcpProviderMetadata
|
|
80
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-LOIWIBZT.js";
|
|
81
81
|
import {
|
|
82
82
|
Logger
|
|
83
83
|
} from "./chunk-OCYRD7D6.js";
|
|
@@ -1032,7 +1032,7 @@ function InputPrompt({
|
|
|
1032
1032
|
setFileSelectedIndex(0);
|
|
1033
1033
|
}, [filteredFiles]);
|
|
1034
1034
|
useInput2(
|
|
1035
|
-
(
|
|
1035
|
+
(input, key) => {
|
|
1036
1036
|
if (fileAutocomplete?.active && filteredFiles.length > 0) {
|
|
1037
1037
|
if (key.upArrow) {
|
|
1038
1038
|
setFileSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredFiles.length - 1);
|
|
@@ -2031,7 +2031,7 @@ import SelectInput4 from "ink-select-input";
|
|
|
2031
2031
|
function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
|
|
2032
2032
|
const [step, setStep] = useState6("selection");
|
|
2033
2033
|
const [selectedSession, setSelectedSession] = useState6(null);
|
|
2034
|
-
useInput6((
|
|
2034
|
+
useInput6((_input, key) => {
|
|
2035
2035
|
if (key.escape) {
|
|
2036
2036
|
if (step === "confirmation") {
|
|
2037
2037
|
setStep("selection");
|
|
@@ -2042,12 +2042,29 @@ function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
|
|
|
2042
2042
|
}
|
|
2043
2043
|
});
|
|
2044
2044
|
const hasUnsavedWork = currentSession && currentSession.messages.length > 0;
|
|
2045
|
+
const formatTimeAgo = (timestamp) => {
|
|
2046
|
+
const now = /* @__PURE__ */ new Date();
|
|
2047
|
+
const then = new Date(timestamp);
|
|
2048
|
+
const diffMs = now.getTime() - then.getTime();
|
|
2049
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
2050
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
2051
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
2052
|
+
if (diffMins < 60) {
|
|
2053
|
+
return `${diffMins}m`;
|
|
2054
|
+
} else if (diffHours < 24) {
|
|
2055
|
+
return `${diffHours}h`;
|
|
2056
|
+
} else {
|
|
2057
|
+
return `${diffDays}d`;
|
|
2058
|
+
}
|
|
2059
|
+
};
|
|
2045
2060
|
const items = sessions.map((session, index) => {
|
|
2046
|
-
const
|
|
2047
|
-
const
|
|
2061
|
+
const userMessages = session.messages.filter((msg) => msg.role === "user");
|
|
2062
|
+
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
2063
|
+
const preview = lastUserMessage ? lastUserMessage.content.slice(0, 50).replace(/\n/g, " ") + (lastUserMessage.content.length > 50 ? "..." : "") : "No messages";
|
|
2064
|
+
const timeAgo = formatTimeAgo(session.updatedAt);
|
|
2048
2065
|
return {
|
|
2049
|
-
|
|
2050
|
-
|
|
2066
|
+
key: session.id,
|
|
2067
|
+
label: `[${index + 1}] ${preview} (${timeAgo})`,
|
|
2051
2068
|
value: session
|
|
2052
2069
|
};
|
|
2053
2070
|
});
|
|
@@ -2287,6 +2304,9 @@ var SessionStore = class {
|
|
|
2287
2304
|
* Save a session to disk
|
|
2288
2305
|
*/
|
|
2289
2306
|
async save(session) {
|
|
2307
|
+
if (session.messages.length === 0) {
|
|
2308
|
+
throw new Error("Cannot save session with no messages");
|
|
2309
|
+
}
|
|
2290
2310
|
await this.init();
|
|
2291
2311
|
const filePath = path3.join(this.basePath, `${session.id}.json`);
|
|
2292
2312
|
try {
|
|
@@ -2329,13 +2349,14 @@ var SessionStore = class {
|
|
|
2329
2349
|
}
|
|
2330
2350
|
/**
|
|
2331
2351
|
* List all saved sessions
|
|
2352
|
+
* @param limit - Optional limit on number of sessions to return (returns most recent)
|
|
2332
2353
|
*/
|
|
2333
|
-
async list() {
|
|
2354
|
+
async list(limit) {
|
|
2334
2355
|
await this.init();
|
|
2335
2356
|
try {
|
|
2336
2357
|
const files = await fs3.readdir(this.basePath);
|
|
2337
2358
|
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
2338
|
-
const
|
|
2359
|
+
const sessionsWithFiles = await Promise.all(
|
|
2339
2360
|
jsonFiles.map(async (file) => {
|
|
2340
2361
|
const filePath = path3.join(this.basePath, file);
|
|
2341
2362
|
const data = await fs3.readFile(filePath, "utf-8");
|
|
@@ -2346,10 +2367,23 @@ var SessionStore = class {
|
|
|
2346
2367
|
}
|
|
2347
2368
|
return msg;
|
|
2348
2369
|
});
|
|
2349
|
-
return session;
|
|
2370
|
+
return { session, filePath };
|
|
2350
2371
|
})
|
|
2351
2372
|
);
|
|
2352
|
-
|
|
2373
|
+
const validSessions = [];
|
|
2374
|
+
for (const { session, filePath } of sessionsWithFiles) {
|
|
2375
|
+
if (session.messages.length === 0) {
|
|
2376
|
+
try {
|
|
2377
|
+
await fs3.unlink(filePath);
|
|
2378
|
+
} catch (error) {
|
|
2379
|
+
console.error(`Failed to delete empty session ${session.id}:`, error);
|
|
2380
|
+
}
|
|
2381
|
+
} else {
|
|
2382
|
+
validSessions.push(session);
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
const sorted = validSessions.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
2386
|
+
return limit ? sorted.slice(0, limit) : sorted;
|
|
2353
2387
|
} catch (error) {
|
|
2354
2388
|
console.error("Failed to list sessions:", error);
|
|
2355
2389
|
return [];
|
|
@@ -5585,15 +5619,6 @@ var llmAnalysisResponseSchema = z136.object({
|
|
|
5585
5619
|
suggestedTags: z136.array(z136.string()).default([])
|
|
5586
5620
|
});
|
|
5587
5621
|
|
|
5588
|
-
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletion.js
|
|
5589
|
-
import { z as z138 } from "zod";
|
|
5590
|
-
|
|
5591
|
-
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletionInvoke.js
|
|
5592
|
-
import { fromZodError } from "zod-validation-error";
|
|
5593
|
-
|
|
5594
|
-
// ../../b4m-core/packages/services/dist/src/llm/tools/toolManager.js
|
|
5595
|
-
var BUILT_IN_TOOL_SET = new Set(b4mLLMTools.options);
|
|
5596
|
-
|
|
5597
5622
|
// ../../b4m-core/packages/services/dist/src/llm/tools/ToolCacheManager.js
|
|
5598
5623
|
var DEFAULT_CONFIG = {
|
|
5599
5624
|
ttl: 5 * 60 * 1e3,
|
|
@@ -9955,343 +9980,8 @@ var editLocalFileTool = {
|
|
|
9955
9980
|
})
|
|
9956
9981
|
};
|
|
9957
9982
|
|
|
9958
|
-
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/recentChanges/index.js
|
|
9959
|
-
import { spawn as spawn2 } from "child_process";
|
|
9960
|
-
var DEFAULT_SINCE = "7 days ago";
|
|
9961
|
-
var DEFAULT_LIMIT = 50;
|
|
9962
|
-
var DEFAULT_INCLUDE_STATS = false;
|
|
9963
|
-
function parseStatusLine(line) {
|
|
9964
|
-
const results = [];
|
|
9965
|
-
if (line.length < 4)
|
|
9966
|
-
return results;
|
|
9967
|
-
const indexStatus = line[0];
|
|
9968
|
-
const workTreeStatus = line[1];
|
|
9969
|
-
const filePath = line.slice(3);
|
|
9970
|
-
const typeMap = {
|
|
9971
|
-
M: "modified",
|
|
9972
|
-
A: "added",
|
|
9973
|
-
D: "deleted",
|
|
9974
|
-
R: "renamed",
|
|
9975
|
-
C: "copied"
|
|
9976
|
-
};
|
|
9977
|
-
if (indexStatus !== " " && indexStatus !== "?") {
|
|
9978
|
-
results.push({
|
|
9979
|
-
path: filePath,
|
|
9980
|
-
status: "staged",
|
|
9981
|
-
type: typeMap[indexStatus] || "modified"
|
|
9982
|
-
});
|
|
9983
|
-
}
|
|
9984
|
-
if (workTreeStatus !== " " && workTreeStatus !== "?") {
|
|
9985
|
-
results.push({
|
|
9986
|
-
path: filePath,
|
|
9987
|
-
status: "unstaged",
|
|
9988
|
-
type: typeMap[workTreeStatus] || "modified"
|
|
9989
|
-
});
|
|
9990
|
-
}
|
|
9991
|
-
if (indexStatus === "?" && workTreeStatus === "?") {
|
|
9992
|
-
results.push({
|
|
9993
|
-
path: filePath,
|
|
9994
|
-
status: "untracked",
|
|
9995
|
-
type: "added"
|
|
9996
|
-
});
|
|
9997
|
-
}
|
|
9998
|
-
return results;
|
|
9999
|
-
}
|
|
10000
|
-
async function getWorkingTreeChanges(filterPath) {
|
|
10001
|
-
const args = ["status", "--porcelain"];
|
|
10002
|
-
if (filterPath) {
|
|
10003
|
-
args.push("--", filterPath);
|
|
10004
|
-
}
|
|
10005
|
-
return new Promise((resolve3) => {
|
|
10006
|
-
const proc = spawn2("git", args, {
|
|
10007
|
-
cwd: process.cwd(),
|
|
10008
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
10009
|
-
});
|
|
10010
|
-
let stdout = "";
|
|
10011
|
-
proc.stdout.on("data", (data) => {
|
|
10012
|
-
stdout += data.toString();
|
|
10013
|
-
});
|
|
10014
|
-
proc.on("close", (exitCode) => {
|
|
10015
|
-
if (exitCode !== 0) {
|
|
10016
|
-
resolve3([]);
|
|
10017
|
-
return;
|
|
10018
|
-
}
|
|
10019
|
-
const files = stdout.split("\n").filter((line) => line.length > 0).flatMap(parseStatusLine);
|
|
10020
|
-
resolve3(files);
|
|
10021
|
-
});
|
|
10022
|
-
proc.on("error", () => {
|
|
10023
|
-
resolve3([]);
|
|
10024
|
-
});
|
|
10025
|
-
});
|
|
10026
|
-
}
|
|
10027
|
-
async function getRecentChanges(params) {
|
|
10028
|
-
const { since = DEFAULT_SINCE, path: filterPath, limit = DEFAULT_LIMIT, include_stats = DEFAULT_INCLUDE_STATS } = params;
|
|
10029
|
-
const args = ["log", `--since=${since}`, "--name-only", "--pretty=format:"];
|
|
10030
|
-
if (filterPath) {
|
|
10031
|
-
args.push("--", filterPath);
|
|
10032
|
-
}
|
|
10033
|
-
return new Promise((resolve3) => {
|
|
10034
|
-
const proc = spawn2("git", args, {
|
|
10035
|
-
cwd: process.cwd(),
|
|
10036
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
10037
|
-
});
|
|
10038
|
-
let stdout = "";
|
|
10039
|
-
let stderr = "";
|
|
10040
|
-
proc.stdout.on("data", (data) => {
|
|
10041
|
-
stdout += data.toString();
|
|
10042
|
-
});
|
|
10043
|
-
proc.stderr.on("data", (data) => {
|
|
10044
|
-
stderr += data.toString();
|
|
10045
|
-
});
|
|
10046
|
-
proc.on("close", async (exitCode) => {
|
|
10047
|
-
const workingTree = await getWorkingTreeChanges(filterPath);
|
|
10048
|
-
if (exitCode !== 0) {
|
|
10049
|
-
resolve3({
|
|
10050
|
-
files: [],
|
|
10051
|
-
workingTree,
|
|
10052
|
-
timeRange: since,
|
|
10053
|
-
totalFiles: 0,
|
|
10054
|
-
error: stderr || "Git command failed"
|
|
10055
|
-
});
|
|
10056
|
-
return;
|
|
10057
|
-
}
|
|
10058
|
-
const files = stdout.split("\n").filter((line) => line.trim().length > 0).reduce((acc, filePath) => {
|
|
10059
|
-
const existing = acc.find((f) => f.path === filePath);
|
|
10060
|
-
if (existing) {
|
|
10061
|
-
existing.changes++;
|
|
10062
|
-
} else {
|
|
10063
|
-
acc.push({ path: filePath, changes: 1 });
|
|
10064
|
-
}
|
|
10065
|
-
return acc;
|
|
10066
|
-
}, []);
|
|
10067
|
-
files.sort((a, b) => b.changes - a.changes);
|
|
10068
|
-
const limitedFiles = files.slice(0, limit);
|
|
10069
|
-
if (include_stats && limitedFiles.length > 0) {
|
|
10070
|
-
const filesWithStats = await getFileStats(limitedFiles, since, filterPath);
|
|
10071
|
-
resolve3({
|
|
10072
|
-
files: filesWithStats,
|
|
10073
|
-
workingTree,
|
|
10074
|
-
timeRange: since,
|
|
10075
|
-
totalFiles: files.length
|
|
10076
|
-
});
|
|
10077
|
-
} else {
|
|
10078
|
-
resolve3({
|
|
10079
|
-
files: limitedFiles,
|
|
10080
|
-
workingTree,
|
|
10081
|
-
timeRange: since,
|
|
10082
|
-
totalFiles: files.length
|
|
10083
|
-
});
|
|
10084
|
-
}
|
|
10085
|
-
});
|
|
10086
|
-
proc.on("error", async (error) => {
|
|
10087
|
-
const workingTree = await getWorkingTreeChanges(filterPath);
|
|
10088
|
-
resolve3({
|
|
10089
|
-
files: [],
|
|
10090
|
-
workingTree,
|
|
10091
|
-
timeRange: since,
|
|
10092
|
-
totalFiles: 0,
|
|
10093
|
-
error: `Failed to execute git command: ${error.message}`
|
|
10094
|
-
});
|
|
10095
|
-
});
|
|
10096
|
-
});
|
|
10097
|
-
}
|
|
10098
|
-
async function getFileStats(files, since, filterPath) {
|
|
10099
|
-
const args = ["log", `--since=${since}`, "--numstat", "--pretty=format:"];
|
|
10100
|
-
if (filterPath) {
|
|
10101
|
-
args.push("--", filterPath);
|
|
10102
|
-
}
|
|
10103
|
-
return new Promise((resolve3) => {
|
|
10104
|
-
const proc = spawn2("git", args, {
|
|
10105
|
-
cwd: process.cwd(),
|
|
10106
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
10107
|
-
});
|
|
10108
|
-
let stdout = "";
|
|
10109
|
-
proc.stdout.on("data", (data) => {
|
|
10110
|
-
stdout += data.toString();
|
|
10111
|
-
});
|
|
10112
|
-
proc.on("close", () => {
|
|
10113
|
-
const stats = /* @__PURE__ */ new Map();
|
|
10114
|
-
stdout.split("\n").forEach((line) => {
|
|
10115
|
-
const match = line.match(/^(\d+)\s+(\d+)\s+(.+)$/);
|
|
10116
|
-
if (match) {
|
|
10117
|
-
const [, additions, deletions, filePath] = match;
|
|
10118
|
-
const existing = stats.get(filePath);
|
|
10119
|
-
if (existing) {
|
|
10120
|
-
existing.additions += parseInt(additions, 10);
|
|
10121
|
-
existing.deletions += parseInt(deletions, 10);
|
|
10122
|
-
} else {
|
|
10123
|
-
stats.set(filePath, {
|
|
10124
|
-
additions: parseInt(additions, 10),
|
|
10125
|
-
deletions: parseInt(deletions, 10)
|
|
10126
|
-
});
|
|
10127
|
-
}
|
|
10128
|
-
}
|
|
10129
|
-
});
|
|
10130
|
-
const result = files.map((file) => {
|
|
10131
|
-
const stat3 = stats.get(file.path);
|
|
10132
|
-
if (stat3) {
|
|
10133
|
-
return { ...file, ...stat3 };
|
|
10134
|
-
}
|
|
10135
|
-
return file;
|
|
10136
|
-
});
|
|
10137
|
-
resolve3(result);
|
|
10138
|
-
});
|
|
10139
|
-
proc.on("error", () => {
|
|
10140
|
-
resolve3(files);
|
|
10141
|
-
});
|
|
10142
|
-
});
|
|
10143
|
-
}
|
|
10144
|
-
function formatResult2(result) {
|
|
10145
|
-
const parts = [];
|
|
10146
|
-
if (result.error) {
|
|
10147
|
-
parts.push(`Error: ${result.error}`);
|
|
10148
|
-
parts.push("");
|
|
10149
|
-
parts.push("Make sure you are running this command in a git repository.");
|
|
10150
|
-
if (result.workingTree.length > 0) {
|
|
10151
|
-
parts.push("");
|
|
10152
|
-
parts.push(formatWorkingTree(result.workingTree));
|
|
10153
|
-
}
|
|
10154
|
-
return parts.join("\n");
|
|
10155
|
-
}
|
|
10156
|
-
if (result.workingTree.length > 0) {
|
|
10157
|
-
parts.push(formatWorkingTree(result.workingTree));
|
|
10158
|
-
parts.push("");
|
|
10159
|
-
}
|
|
10160
|
-
parts.push(`Recently committed files (${result.timeRange}):`);
|
|
10161
|
-
parts.push("");
|
|
10162
|
-
if (result.files.length === 0) {
|
|
10163
|
-
parts.push("No files changed in this time period.");
|
|
10164
|
-
} else {
|
|
10165
|
-
result.files.forEach((file, index) => {
|
|
10166
|
-
const stats = file.additions !== void 0 && file.deletions !== void 0 ? ` (+${file.additions}/-${file.deletions})` : "";
|
|
10167
|
-
parts.push(`${index + 1}. ${file.path} (${file.changes} commits)${stats}`);
|
|
10168
|
-
});
|
|
10169
|
-
if (result.totalFiles > result.files.length) {
|
|
10170
|
-
parts.push("");
|
|
10171
|
-
parts.push(`Showing ${result.files.length} of ${result.totalFiles} changed files.`);
|
|
10172
|
-
parts.push(`Use the 'limit' parameter to see more files.`);
|
|
10173
|
-
}
|
|
10174
|
-
}
|
|
10175
|
-
return parts.join("\n");
|
|
10176
|
-
}
|
|
10177
|
-
function formatWorkingTree(workingTree) {
|
|
10178
|
-
const parts = [];
|
|
10179
|
-
const staged = workingTree.filter((f) => f.status === "staged");
|
|
10180
|
-
const unstaged = workingTree.filter((f) => f.status === "unstaged");
|
|
10181
|
-
const untracked = workingTree.filter((f) => f.status === "untracked");
|
|
10182
|
-
parts.push("Working tree changes:");
|
|
10183
|
-
if (staged.length > 0) {
|
|
10184
|
-
parts.push("");
|
|
10185
|
-
parts.push(` Staged (${staged.length}):`);
|
|
10186
|
-
staged.forEach((f) => parts.push(` ${f.type}: ${f.path}`));
|
|
10187
|
-
}
|
|
10188
|
-
if (unstaged.length > 0) {
|
|
10189
|
-
parts.push("");
|
|
10190
|
-
parts.push(` Unstaged (${unstaged.length}):`);
|
|
10191
|
-
unstaged.forEach((f) => parts.push(` ${f.type}: ${f.path}`));
|
|
10192
|
-
}
|
|
10193
|
-
if (untracked.length > 0) {
|
|
10194
|
-
parts.push("");
|
|
10195
|
-
parts.push(` Untracked (${untracked.length}):`);
|
|
10196
|
-
untracked.forEach((f) => parts.push(` ${f.path}`));
|
|
10197
|
-
}
|
|
10198
|
-
return parts.join("\n");
|
|
10199
|
-
}
|
|
10200
|
-
var recentChangesTool = {
|
|
10201
|
-
name: "recent_changes",
|
|
10202
|
-
implementation: (context) => ({
|
|
10203
|
-
toolFn: async (value) => {
|
|
10204
|
-
const params = value;
|
|
10205
|
-
context.logger.info("RecentChanges: Getting recently changed files", {
|
|
10206
|
-
since: params.since || DEFAULT_SINCE,
|
|
10207
|
-
path: params.path || "all",
|
|
10208
|
-
limit: params.limit || DEFAULT_LIMIT,
|
|
10209
|
-
include_stats: params.include_stats || DEFAULT_INCLUDE_STATS
|
|
10210
|
-
});
|
|
10211
|
-
if (context.onStart) {
|
|
10212
|
-
await context.onStart("recent_changes", {
|
|
10213
|
-
since: params.since,
|
|
10214
|
-
path: params.path
|
|
10215
|
-
});
|
|
10216
|
-
}
|
|
10217
|
-
try {
|
|
10218
|
-
const result = await getRecentChanges(params);
|
|
10219
|
-
const formattedResult = formatResult2(result);
|
|
10220
|
-
context.logger.info("RecentChanges: Retrieved file changes", {
|
|
10221
|
-
totalFiles: result.totalFiles,
|
|
10222
|
-
displayedFiles: result.files.length,
|
|
10223
|
-
error: result.error
|
|
10224
|
-
});
|
|
10225
|
-
if (context.onFinish) {
|
|
10226
|
-
await context.onFinish("recent_changes", {
|
|
10227
|
-
totalFiles: result.totalFiles,
|
|
10228
|
-
displayedFiles: result.files.length
|
|
10229
|
-
});
|
|
10230
|
-
}
|
|
10231
|
-
return formattedResult;
|
|
10232
|
-
} catch (error) {
|
|
10233
|
-
context.logger.error("RecentChanges: Failed to get changes", error);
|
|
10234
|
-
if (context.onFinish) {
|
|
10235
|
-
await context.onFinish("recent_changes", {
|
|
10236
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
10237
|
-
});
|
|
10238
|
-
}
|
|
10239
|
-
throw error;
|
|
10240
|
-
}
|
|
10241
|
-
},
|
|
10242
|
-
toolSchema: {
|
|
10243
|
-
name: "recent_changes",
|
|
10244
|
-
description: `Get a list of recently changed files in the git repository, including uncommitted working tree changes (staged, unstaged, and untracked files) plus committed changes sorted by activity. This tool is extremely useful for:
|
|
10245
|
-
|
|
10246
|
-
- **Debugging recent issues**: "Something broke after my last commit" \u2192 See exactly what changed
|
|
10247
|
-
- **Understanding active development**: "What are we working on?" \u2192 See most active files and current work-in-progress
|
|
10248
|
-
- **Code review preparation**: "What changed since last release?" \u2192 Get comprehensive file list
|
|
10249
|
-
- **Feature context**: "What files are part of the new dashboard?" \u2192 Filter by path
|
|
10250
|
-
- **Current work-in-progress**: See staged, unstaged, and untracked files alongside commit history
|
|
10251
|
-
|
|
10252
|
-
The tool combines git status (working tree) with git log (commit history) to give a complete picture of recent activity. Working tree changes are shown first, followed by committed files ranked by number of commits (most active first).
|
|
10253
|
-
|
|
10254
|
-
**Time Range Examples:**
|
|
10255
|
-
- "7 days ago" (default)
|
|
10256
|
-
- "2 hours ago"
|
|
10257
|
-
- "3 weeks ago"
|
|
10258
|
-
- "2025-01-01"
|
|
10259
|
-
- "yesterday"
|
|
10260
|
-
|
|
10261
|
-
**Path Filter Examples:**
|
|
10262
|
-
- "src/components" - Only files in components directory
|
|
10263
|
-
- "apps/client" - Only client app files
|
|
10264
|
-
- "**/*.test.ts" - Only test files (use glob patterns)
|
|
10265
|
-
|
|
10266
|
-
**Performance:** Very fast (< 1 second) since it only queries git metadata, not file contents.`,
|
|
10267
|
-
parameters: {
|
|
10268
|
-
type: "object",
|
|
10269
|
-
properties: {
|
|
10270
|
-
since: {
|
|
10271
|
-
type: "string",
|
|
10272
|
-
description: 'Time range for changes (default: "7 days ago"). Examples: "2 hours ago", "3 weeks ago", "2025-01-01", "yesterday".'
|
|
10273
|
-
},
|
|
10274
|
-
path: {
|
|
10275
|
-
type: "string",
|
|
10276
|
-
description: 'Optional path filter to limit results to specific directory or pattern. Examples: "src/components", "apps/client", "**/*.test.ts".'
|
|
10277
|
-
},
|
|
10278
|
-
limit: {
|
|
10279
|
-
type: "number",
|
|
10280
|
-
description: "Maximum number of files to return (default: 50). Files are sorted by activity (most commits first)."
|
|
10281
|
-
},
|
|
10282
|
-
include_stats: {
|
|
10283
|
-
type: "boolean",
|
|
10284
|
-
description: "Include lines added/removed statistics for each file (default: false). Note: This makes the command slightly slower."
|
|
10285
|
-
}
|
|
10286
|
-
},
|
|
10287
|
-
required: []
|
|
10288
|
-
}
|
|
10289
|
-
}
|
|
10290
|
-
})
|
|
10291
|
-
};
|
|
10292
|
-
|
|
10293
9983
|
// ../../b4m-core/packages/services/dist/src/llm/tools/index.js
|
|
10294
|
-
var
|
|
9984
|
+
var tools = {
|
|
10295
9985
|
dice_roll: diceRollTool,
|
|
10296
9986
|
weather_info: weatherTool,
|
|
10297
9987
|
image_generation: imageGenerationTool,
|
|
@@ -10314,23 +10004,18 @@ var b4mTools = {
|
|
|
10314
10004
|
sunrise_sunset: sunriseSunsetTool,
|
|
10315
10005
|
iss_tracker: issTrackerTool,
|
|
10316
10006
|
planet_visibility: planetVisibilityTool,
|
|
10317
|
-
// Knowledge base search
|
|
10318
|
-
search_knowledge_base: knowledgeBaseSearchTool
|
|
10319
|
-
};
|
|
10320
|
-
var cliOnlyTools = {
|
|
10321
|
-
// File operation tools
|
|
10322
10007
|
file_read: fileReadTool,
|
|
10323
10008
|
create_file: createFileTool,
|
|
10324
10009
|
edit_local_file: editLocalFileTool,
|
|
10325
10010
|
glob_files: globFilesTool,
|
|
10326
10011
|
grep_search: grepSearchTool,
|
|
10327
10012
|
delete_file: deleteFileTool,
|
|
10013
|
+
// Knowledge base search
|
|
10014
|
+
search_knowledge_base: knowledgeBaseSearchTool,
|
|
10328
10015
|
// Shell execution
|
|
10329
|
-
bash_execute: bashExecuteTool
|
|
10330
|
-
// Git operations
|
|
10331
|
-
recent_changes: recentChangesTool
|
|
10016
|
+
bash_execute: bashExecuteTool
|
|
10332
10017
|
};
|
|
10333
|
-
var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model
|
|
10018
|
+
var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model) => {
|
|
10334
10019
|
const context = {
|
|
10335
10020
|
userId,
|
|
10336
10021
|
user,
|
|
@@ -10351,9 +10036,9 @@ var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorag
|
|
|
10351
10036
|
};
|
|
10352
10037
|
var ATLASSIAN_RECONNECT_MESSAGE = "\u26A0\uFE0F Your Atlassian connection has expired.\n\nPlease reconnect your Atlassian account in Settings > Connected Apps to continue using Confluence and Jira tools.";
|
|
10353
10038
|
var generateMcpTools = async (mcpData) => {
|
|
10354
|
-
let
|
|
10039
|
+
let tools2;
|
|
10355
10040
|
try {
|
|
10356
|
-
|
|
10041
|
+
tools2 = await mcpData.getTools();
|
|
10357
10042
|
} catch (error) {
|
|
10358
10043
|
const errorName = error instanceof Error ? error.name : "";
|
|
10359
10044
|
if (errorName === "AtlassianReconnectRequiredError") {
|
|
@@ -10362,12 +10047,12 @@ var generateMcpTools = async (mcpData) => {
|
|
|
10362
10047
|
}
|
|
10363
10048
|
throw error;
|
|
10364
10049
|
}
|
|
10365
|
-
const toolList = Array.isArray(
|
|
10366
|
-
if (!Array.isArray(
|
|
10367
|
-
console.warn(`MCP server ${mcpData.serverName} returned unexpected tools payload:`, JSON.stringify(
|
|
10050
|
+
const toolList = Array.isArray(tools2) ? tools2 : tools2?.tools || [];
|
|
10051
|
+
if (!Array.isArray(tools2)) {
|
|
10052
|
+
console.warn(`MCP server ${mcpData.serverName} returned unexpected tools payload:`, JSON.stringify(tools2));
|
|
10368
10053
|
}
|
|
10369
10054
|
if (!Array.isArray(toolList)) {
|
|
10370
|
-
throw new Error(`Expected getTools() to return an array, but got ${typeof
|
|
10055
|
+
throw new Error(`Expected getTools() to return an array, but got ${typeof tools2}`);
|
|
10371
10056
|
}
|
|
10372
10057
|
const result = toolList.map((item) => {
|
|
10373
10058
|
const { name: originalToolName, ...rest } = item;
|
|
@@ -10437,16 +10122,8 @@ var generateMcpTools = async (mcpData) => {
|
|
|
10437
10122
|
import throttle2 from "lodash/throttle.js";
|
|
10438
10123
|
|
|
10439
10124
|
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletionFeatures.js
|
|
10125
|
+
import { z as z138 } from "zod";
|
|
10440
10126
|
import uniq4 from "lodash/uniq.js";
|
|
10441
|
-
|
|
10442
|
-
// ../../b4m-core/packages/services/dist/src/llm/StatusManager.js
|
|
10443
|
-
import throttle from "lodash/throttle.js";
|
|
10444
|
-
|
|
10445
|
-
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletionProcess.js
|
|
10446
|
-
var DISABLE_SERVER_THROTTLING = process.env.DISABLE_SERVER_THROTTLING === "true";
|
|
10447
|
-
var questSaveMutex = new Mutex();
|
|
10448
|
-
|
|
10449
|
-
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletion.js
|
|
10450
10127
|
var QuestStartBodySchema = z138.object({
|
|
10451
10128
|
userId: z138.string(),
|
|
10452
10129
|
sessionId: z138.string(),
|
|
@@ -10488,6 +10165,19 @@ var QuestStartBodySchema = z138.object({
|
|
|
10488
10165
|
timezone: z138.string().optional()
|
|
10489
10166
|
});
|
|
10490
10167
|
|
|
10168
|
+
// ../../b4m-core/packages/services/dist/src/llm/StatusManager.js
|
|
10169
|
+
import throttle from "lodash/throttle.js";
|
|
10170
|
+
|
|
10171
|
+
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletionProcess.js
|
|
10172
|
+
var DISABLE_SERVER_THROTTLING = process.env.DISABLE_SERVER_THROTTLING === "true";
|
|
10173
|
+
var questSaveMutex = new Mutex();
|
|
10174
|
+
|
|
10175
|
+
// ../../b4m-core/packages/services/dist/src/llm/ChatCompletionInvoke.js
|
|
10176
|
+
import { fromZodError } from "zod-validation-error";
|
|
10177
|
+
|
|
10178
|
+
// ../../b4m-core/packages/services/dist/src/llm/tools/toolManager.js
|
|
10179
|
+
var BUILT_IN_TOOL_SET = new Set(b4mLLMTools.options);
|
|
10180
|
+
|
|
10491
10181
|
// ../../b4m-core/packages/services/dist/src/llm/ImageGeneration.js
|
|
10492
10182
|
import axios8 from "axios";
|
|
10493
10183
|
import { fileTypeFromBuffer as fileTypeFromBuffer4 } from "file-type";
|
|
@@ -10701,8 +10391,7 @@ var LOCAL_TOOLS = [
|
|
|
10701
10391
|
"dice_roll",
|
|
10702
10392
|
"math_evaluate",
|
|
10703
10393
|
"current_datetime",
|
|
10704
|
-
"bash_execute"
|
|
10705
|
-
"recent_changes"
|
|
10394
|
+
"bash_execute"
|
|
10706
10395
|
];
|
|
10707
10396
|
function isServerTool(toolName) {
|
|
10708
10397
|
return SERVER_TOOLS.includes(toolName);
|
|
@@ -10728,11 +10417,11 @@ async function executeTool(toolName, input, apiClient, localToolFn) {
|
|
|
10728
10417
|
}
|
|
10729
10418
|
|
|
10730
10419
|
// src/utils/shellRunner.ts
|
|
10731
|
-
import { spawn as
|
|
10420
|
+
import { spawn as spawn2 } from "child_process";
|
|
10732
10421
|
async function runShellCommand(options) {
|
|
10733
10422
|
const { command, cwd, timeoutMs, env, stdin } = options;
|
|
10734
10423
|
return new Promise((resolve3) => {
|
|
10735
|
-
const child =
|
|
10424
|
+
const child = spawn2("bash", ["-c", command], {
|
|
10736
10425
|
cwd,
|
|
10737
10426
|
env,
|
|
10738
10427
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -11155,21 +10844,37 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
|
|
|
11155
10844
|
adminSettings: mockAdminSettings
|
|
11156
10845
|
}
|
|
11157
10846
|
};
|
|
11158
|
-
const
|
|
10847
|
+
const toolConfig = {
|
|
11159
10848
|
// Local-only tools (no external API keys needed)
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
10849
|
+
dice_roll: {},
|
|
10850
|
+
math_evaluate: {},
|
|
10851
|
+
current_datetime: {},
|
|
10852
|
+
prompt_enhancement: {},
|
|
10853
|
+
// File operation tools (CLI-specific, local execution)
|
|
10854
|
+
file_read: {},
|
|
10855
|
+
create_file: {},
|
|
10856
|
+
edit_local_file: {},
|
|
10857
|
+
glob_files: {},
|
|
10858
|
+
grep_search: {},
|
|
10859
|
+
delete_file: {},
|
|
10860
|
+
// Shell execution (always requires permission)
|
|
10861
|
+
bash_execute: {},
|
|
11164
10862
|
// Server-side tools (executed via /api/ai/v1/tools Lambda)
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
10863
|
+
// Routed by ToolRouter to use B4M company API keys
|
|
10864
|
+
weather_info: {},
|
|
10865
|
+
web_search: {},
|
|
10866
|
+
web_fetch: {}
|
|
10867
|
+
// Disable web-only tools
|
|
10868
|
+
// blog_publish: undefined,
|
|
10869
|
+
// blog_edit: undefined,
|
|
10870
|
+
// blog_draft: undefined,
|
|
10871
|
+
// image_generation: undefined,
|
|
10872
|
+
// edit_image: undefined,
|
|
10873
|
+
// mermaid_chart: undefined,
|
|
10874
|
+
// recharts: undefined,
|
|
10875
|
+
// edit_file: undefined,
|
|
10876
|
+
// deep_research: undefined,
|
|
10877
|
+
};
|
|
11173
10878
|
const toolsMap = generateTools(
|
|
11174
10879
|
userId,
|
|
11175
10880
|
user,
|
|
@@ -11182,18 +10887,17 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
|
|
|
11182
10887
|
onStart,
|
|
11183
10888
|
onFinish,
|
|
11184
10889
|
llm,
|
|
11185
|
-
|
|
11186
|
-
model
|
|
11187
|
-
tools_to_generate
|
|
10890
|
+
toolConfig,
|
|
10891
|
+
model
|
|
11188
10892
|
);
|
|
11189
|
-
let
|
|
10893
|
+
let tools2 = Object.entries(toolsMap).filter(([key]) => toolConfig[key] !== void 0).map(
|
|
11190
10894
|
([_, tool]) => wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient)
|
|
11191
10895
|
);
|
|
11192
10896
|
if (toolFilter) {
|
|
11193
10897
|
const { allowedTools, deniedTools } = toolFilter;
|
|
11194
10898
|
const normalizedAllowed = allowedTools?.map(normalizeToolName);
|
|
11195
10899
|
const normalizedDenied = deniedTools?.map(normalizeToolName);
|
|
11196
|
-
|
|
10900
|
+
tools2 = tools2.filter((tool) => {
|
|
11197
10901
|
const toolName = tool.toolSchema.name;
|
|
11198
10902
|
if (normalizedDenied && normalizedDenied.includes(toolName)) {
|
|
11199
10903
|
return false;
|
|
@@ -11204,7 +10908,7 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
|
|
|
11204
10908
|
return true;
|
|
11205
10909
|
});
|
|
11206
10910
|
}
|
|
11207
|
-
return { tools, agentContext };
|
|
10911
|
+
return { tools: tools2, agentContext };
|
|
11208
10912
|
}
|
|
11209
10913
|
|
|
11210
10914
|
// src/config/toolSafety.ts
|
|
@@ -11643,9 +11347,9 @@ var TokenCounter = class {
|
|
|
11643
11347
|
* Count tokens in tool schemas.
|
|
11644
11348
|
* Tool schemas are sent as part of the API call and consume context.
|
|
11645
11349
|
*/
|
|
11646
|
-
countToolSchemaTokens(
|
|
11647
|
-
if (
|
|
11648
|
-
const schemaText =
|
|
11350
|
+
countToolSchemaTokens(tools2) {
|
|
11351
|
+
if (tools2.length === 0) return 0;
|
|
11352
|
+
const schemaText = tools2.map(
|
|
11649
11353
|
({ toolSchema }) => `Tool: ${toolSchema.name}
|
|
11650
11354
|
Description: ${toolSchema.description}
|
|
11651
11355
|
Parameters: ${JSON.stringify(toolSchema.parameters)}`
|
|
@@ -11947,14 +11651,14 @@ var McpManager = class {
|
|
|
11947
11651
|
getTools: async () => client.tools,
|
|
11948
11652
|
callTool: async (name, args) => client.callTool(name, args)
|
|
11949
11653
|
};
|
|
11950
|
-
const
|
|
11654
|
+
const tools2 = await generateMcpTools(mcpData);
|
|
11951
11655
|
this.servers.set(serverConfig.name, {
|
|
11952
11656
|
name: serverConfig.name,
|
|
11953
11657
|
client,
|
|
11954
|
-
tools
|
|
11658
|
+
tools: tools2
|
|
11955
11659
|
});
|
|
11956
11660
|
this.connectionStates.set(serverConfig.name, "connected");
|
|
11957
|
-
logger.debug(`\u2705 Connected to ${serverConfig.name} (${
|
|
11661
|
+
logger.debug(`\u2705 Connected to ${serverConfig.name} (${tools2.length} tools)`);
|
|
11958
11662
|
} catch (error) {
|
|
11959
11663
|
this.connectionStates.set(serverConfig.name, "failed");
|
|
11960
11664
|
logger.debug(`\u274C Failed to connect to ${serverConfig.name}: ${error}`);
|
|
@@ -12839,7 +12543,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
12839
12543
|
// package.json
|
|
12840
12544
|
var package_default = {
|
|
12841
12545
|
name: "@bike4mind/cli",
|
|
12842
|
-
version: "0.2.24-
|
|
12546
|
+
version: "0.2.24-sessions-command-bug-fix.18477+04624b930",
|
|
12843
12547
|
type: "module",
|
|
12844
12548
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
12845
12549
|
license: "UNLICENSED",
|
|
@@ -12947,10 +12651,10 @@ var package_default = {
|
|
|
12947
12651
|
},
|
|
12948
12652
|
devDependencies: {
|
|
12949
12653
|
"@bike4mind/agents": "0.1.0",
|
|
12950
|
-
"@bike4mind/common": "2.47.1-
|
|
12951
|
-
"@bike4mind/mcp": "1.27.1-
|
|
12952
|
-
"@bike4mind/services": "2.45.1-
|
|
12953
|
-
"@bike4mind/utils": "2.3.3-
|
|
12654
|
+
"@bike4mind/common": "2.47.1-sessions-command-bug-fix.18477+04624b930",
|
|
12655
|
+
"@bike4mind/mcp": "1.27.1-sessions-command-bug-fix.18477+04624b930",
|
|
12656
|
+
"@bike4mind/services": "2.45.1-sessions-command-bug-fix.18477+04624b930",
|
|
12657
|
+
"@bike4mind/utils": "2.3.3-sessions-command-bug-fix.18477+04624b930",
|
|
12954
12658
|
"@types/better-sqlite3": "^7.6.13",
|
|
12955
12659
|
"@types/diff": "^5.0.9",
|
|
12956
12660
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -12967,7 +12671,7 @@ var package_default = {
|
|
|
12967
12671
|
optionalDependencies: {
|
|
12968
12672
|
"@vscode/ripgrep": "^1.17.0"
|
|
12969
12673
|
},
|
|
12970
|
-
gitHead: "
|
|
12674
|
+
gitHead: "04624b930f0d41ba258c04002f4047fe0b249a29"
|
|
12971
12675
|
};
|
|
12972
12676
|
|
|
12973
12677
|
// src/config/constants.ts
|
|
@@ -14250,7 +13954,7 @@ function CliApp() {
|
|
|
14250
13954
|
currentAgent: null,
|
|
14251
13955
|
observationQueue: []
|
|
14252
13956
|
};
|
|
14253
|
-
const { tools:
|
|
13957
|
+
const { tools: b4mTools } = generateCliTools(
|
|
14254
13958
|
config.userId,
|
|
14255
13959
|
llm,
|
|
14256
13960
|
modelInfo.id,
|
|
@@ -14260,7 +13964,7 @@ function CliApp() {
|
|
|
14260
13964
|
state.configStore,
|
|
14261
13965
|
apiClient
|
|
14262
13966
|
);
|
|
14263
|
-
console.log(`\u{1F6E0}\uFE0F Loaded ${
|
|
13967
|
+
console.log(`\u{1F6E0}\uFE0F Loaded ${b4mTools.length} B4M tool(s)`);
|
|
14264
13968
|
const mcpManager = new McpManager(config);
|
|
14265
13969
|
await mcpManager.initialize();
|
|
14266
13970
|
const mcpTools = mcpManager.getTools();
|
|
@@ -14301,7 +14005,7 @@ function CliApp() {
|
|
|
14301
14005
|
if (skillTool) {
|
|
14302
14006
|
cliTools.push(skillTool);
|
|
14303
14007
|
}
|
|
14304
|
-
const allTools = [...
|
|
14008
|
+
const allTools = [...b4mTools, ...mcpTools, ...cliTools];
|
|
14305
14009
|
console.log(`\u{1F4C2} Working directory: ${process.cwd()}`);
|
|
14306
14010
|
console.log(`\u{1F916} Subagent delegation enabled (explore, plan, review)`);
|
|
14307
14011
|
if (skillTool) {
|
|
@@ -14311,7 +14015,7 @@ function CliApp() {
|
|
|
14311
14015
|
}
|
|
14312
14016
|
}
|
|
14313
14017
|
logger.debug(
|
|
14314
|
-
`Total tools available to agent: ${allTools.length} (${
|
|
14018
|
+
`Total tools available to agent: ${allTools.length} (${b4mTools.length} B4M + ${mcpTools.length} MCP + ${cliTools.length} CLI)`
|
|
14315
14019
|
);
|
|
14316
14020
|
const projectDir = state.configStore.getProjectConfigDir();
|
|
14317
14021
|
const contextResult = await loadContextFiles(projectDir);
|
|
@@ -14990,13 +14694,17 @@ Custom Commands:
|
|
|
14990
14694
|
console.log("No active session to save");
|
|
14991
14695
|
return;
|
|
14992
14696
|
}
|
|
14697
|
+
if (state.session.messages.length === 0) {
|
|
14698
|
+
console.log("\u274C Cannot save session with no messages");
|
|
14699
|
+
return;
|
|
14700
|
+
}
|
|
14993
14701
|
const sessionName = args.join(" ") || state.session.name;
|
|
14994
14702
|
state.session.name = sessionName;
|
|
14995
14703
|
await state.sessionStore.save(state.session);
|
|
14996
14704
|
console.log(`\u2705 Session saved as "${sessionName}"`);
|
|
14997
14705
|
break;
|
|
14998
14706
|
case "sessions": {
|
|
14999
|
-
const sessions = await state.sessionStore.list();
|
|
14707
|
+
const sessions = await state.sessionStore.list(20);
|
|
15000
14708
|
if (sessions.length === 0) {
|
|
15001
14709
|
console.log("\n\u{1F4DA} No saved sessions found.");
|
|
15002
14710
|
console.log("\u{1F4A1} Use /save <name> to save your current session.\n");
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
findMostSimilarMemento,
|
|
4
4
|
getRelevantMementos
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-FV2VQXYX.js";
|
|
6
|
+
import "./chunk-XFN2ICKP.js";
|
|
7
|
+
import "./chunk-LOIWIBZT.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
findMostSimilarMemento,
|
|
@@ -132,8 +132,8 @@ import {
|
|
|
132
132
|
validateMermaidSyntax,
|
|
133
133
|
warmUpSettingsCache,
|
|
134
134
|
withRetry
|
|
135
|
-
} from "./chunk-
|
|
136
|
-
import "./chunk-
|
|
135
|
+
} from "./chunk-XFN2ICKP.js";
|
|
136
|
+
import "./chunk-LOIWIBZT.js";
|
|
137
137
|
import {
|
|
138
138
|
Logger,
|
|
139
139
|
NotificationDeduplicator,
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
SubtractCreditsSchema,
|
|
4
4
|
subtractCredits
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-JHCQOESZ.js";
|
|
6
|
+
import "./chunk-XFN2ICKP.js";
|
|
7
|
+
import "./chunk-LOIWIBZT.js";
|
|
8
8
|
import "./chunk-OCYRD7D6.js";
|
|
9
9
|
export {
|
|
10
10
|
SubtractCreditsSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.24-
|
|
3
|
+
"version": "0.2.24-sessions-command-bug-fix.18477+04624b930",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -108,10 +108,10 @@
|
|
|
108
108
|
},
|
|
109
109
|
"devDependencies": {
|
|
110
110
|
"@bike4mind/agents": "0.1.0",
|
|
111
|
-
"@bike4mind/common": "2.47.1-
|
|
112
|
-
"@bike4mind/mcp": "1.27.1-
|
|
113
|
-
"@bike4mind/services": "2.45.1-
|
|
114
|
-
"@bike4mind/utils": "2.3.3-
|
|
111
|
+
"@bike4mind/common": "2.47.1-sessions-command-bug-fix.18477+04624b930",
|
|
112
|
+
"@bike4mind/mcp": "1.27.1-sessions-command-bug-fix.18477+04624b930",
|
|
113
|
+
"@bike4mind/services": "2.45.1-sessions-command-bug-fix.18477+04624b930",
|
|
114
|
+
"@bike4mind/utils": "2.3.3-sessions-command-bug-fix.18477+04624b930",
|
|
115
115
|
"@types/better-sqlite3": "^7.6.13",
|
|
116
116
|
"@types/diff": "^5.0.9",
|
|
117
117
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -128,5 +128,5 @@
|
|
|
128
128
|
"optionalDependencies": {
|
|
129
129
|
"@vscode/ripgrep": "^1.17.0"
|
|
130
130
|
},
|
|
131
|
-
"gitHead": "
|
|
131
|
+
"gitHead": "04624b930f0d41ba258c04002f4047fe0b249a29"
|
|
132
132
|
}
|