@bike4mind/cli 0.2.11-cli-cancel-pending-message.17326 → 0.2.11-cli-todo-list.17329
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/{ImageStore-RQZ7OF7P.js → ImageStore-MMUOUPI2.js} +0 -1
- package/dist/{artifactExtractor-BZNU5FMW.js → artifactExtractor-5XROR32D.js} +0 -1
- package/dist/{chunk-DGAIF2QC.js → chunk-6AYWWNXH.js} +1 -1
- package/dist/{chunk-RA3CZOUX.js → chunk-GLQV2QBP.js} +1 -1
- package/dist/{chunk-SQBLLN7K.js → chunk-M4EAFD3H.js} +1 -1
- package/dist/{chunk-AMDXHL6S.js → chunk-OCYRD7D6.js} +1 -1
- package/dist/{chunk-RBZRTCAY.js → chunk-WENSCUXW.js} +1 -1
- package/dist/{create-4KCG4N2U.js → create-AYJ2FUMX.js} +3 -4
- package/dist/{formatConverter-I7EIUVDY.js → formatConverter-5QEJDW24.js} +0 -1
- package/dist/index.js +411 -267
- package/dist/{llmMarkdownGenerator-TUFLBYA3.js → llmMarkdownGenerator-3VB77TGN.js} +0 -1
- package/dist/{markdownGenerator-2WSEU4QD.js → markdownGenerator-6CDF26SR.js} +0 -1
- package/dist/{mementoService-75KFGFQT.js → mementoService-YHQGUY3M.js} +3 -4
- package/dist/{notificationDeduplicator-UW7D75QS.js → notificationDeduplicator-UTHJHMSZ.js} +1 -2
- package/dist/{src-JZRDAJFC.js → src-ROS3BMWE.js} +2 -3
- package/dist/{src-UHKJ3EHY.js → src-VOMQHSNW.js} +0 -1
- package/dist/{subtractCredits-MOVABDWW.js → subtractCredits-EGQGB7MG.js} +3 -4
- package/dist/{utils-JPMDGUBL.js → utils-JCHWDM4Z.js} +0 -1
- package/package.json +7 -6
- package/dist/chunk-PDX44BCA.js +0 -11
|
@@ -160,7 +160,7 @@ var notifyEventLogsToSlack = async ({ event, stage, slackUrl, throttlingSlackUrl
|
|
|
160
160
|
if (!allowedStages.includes(stage))
|
|
161
161
|
return;
|
|
162
162
|
const logEvents = logData.logEvents;
|
|
163
|
-
const { notificationDeduplicator: notificationDeduplicator2 } = await import("./notificationDeduplicator-
|
|
163
|
+
const { notificationDeduplicator: notificationDeduplicator2 } = await import("./notificationDeduplicator-UTHJHMSZ.js");
|
|
164
164
|
for (const logEvent of logEvents) {
|
|
165
165
|
try {
|
|
166
166
|
let message;
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createFabFile,
|
|
4
4
|
createFabFileSchema
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-GLQV2QBP.js";
|
|
6
|
+
import "./chunk-M4EAFD3H.js";
|
|
7
|
+
import "./chunk-OCYRD7D6.js";
|
|
8
8
|
import "./chunk-WCYNJOOX.js";
|
|
9
|
-
import "./chunk-PDX44BCA.js";
|
|
10
9
|
export {
|
|
11
10
|
createFabFile,
|
|
12
11
|
createFabFileSchema
|
package/dist/index.js
CHANGED
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
getEffectiveApiKey,
|
|
5
5
|
getOpenWeatherKey,
|
|
6
6
|
getSerperKey
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-6AYWWNXH.js";
|
|
8
|
+
import "./chunk-WENSCUXW.js";
|
|
9
|
+
import "./chunk-GLQV2QBP.js";
|
|
10
10
|
import {
|
|
11
11
|
BFLImageService,
|
|
12
12
|
BaseStorage,
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
OpenAIBackend,
|
|
16
16
|
OpenAIImageService,
|
|
17
17
|
XAIImageService
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-M4EAFD3H.js";
|
|
19
19
|
import {
|
|
20
20
|
Logger
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-OCYRD7D6.js";
|
|
22
22
|
import "./chunk-BPFEGDC7.js";
|
|
23
23
|
import {
|
|
24
24
|
AiEvents,
|
|
@@ -74,9 +74,6 @@ import {
|
|
|
74
74
|
b4mLLMTools,
|
|
75
75
|
getMcpProviderMetadata
|
|
76
76
|
} from "./chunk-WCYNJOOX.js";
|
|
77
|
-
import {
|
|
78
|
-
__require
|
|
79
|
-
} from "./chunk-PDX44BCA.js";
|
|
80
77
|
|
|
81
78
|
// src/index.tsx
|
|
82
79
|
import React17, { useState as useState8, useEffect as useEffect3, useCallback, useRef as useRef2 } from "react";
|
|
@@ -3093,6 +3090,21 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3093
3090
|
let finalAnswer = "";
|
|
3094
3091
|
let reachedMaxIterations = false;
|
|
3095
3092
|
while (iterations < maxIterations) {
|
|
3093
|
+
if (options.signal?.aborted) {
|
|
3094
|
+
this.context.logger.info("[ReActAgent] Operation aborted by user");
|
|
3095
|
+
const result2 = {
|
|
3096
|
+
finalAnswer: "Interrupted",
|
|
3097
|
+
steps: this.steps,
|
|
3098
|
+
completionInfo: {
|
|
3099
|
+
totalTokens: this.totalTokens,
|
|
3100
|
+
iterations,
|
|
3101
|
+
toolCalls: this.toolCallCount,
|
|
3102
|
+
reachedMaxIterations: false
|
|
3103
|
+
}
|
|
3104
|
+
};
|
|
3105
|
+
this.emit("complete", result2);
|
|
3106
|
+
return result2;
|
|
3107
|
+
}
|
|
3096
3108
|
iterations++;
|
|
3097
3109
|
this.context.logger.debug(`[ReActAgent] Starting iteration ${iterations}/${maxIterations}`);
|
|
3098
3110
|
let iterationComplete = false;
|
|
@@ -3106,7 +3118,8 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3106
3118
|
stream: false,
|
|
3107
3119
|
tools: this.context.tools,
|
|
3108
3120
|
maxTokens,
|
|
3109
|
-
temperature
|
|
3121
|
+
temperature,
|
|
3122
|
+
abortSignal: options.signal
|
|
3110
3123
|
},
|
|
3111
3124
|
async (texts, completionInfo) => {
|
|
3112
3125
|
for (const text of texts) {
|
|
@@ -3249,6 +3262,9 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3249
3262
|
this.emit("final_answer", finalStep);
|
|
3250
3263
|
}
|
|
3251
3264
|
}
|
|
3265
|
+
if (options.signal?.aborted && !finalAnswer) {
|
|
3266
|
+
finalAnswer = "Interrupted";
|
|
3267
|
+
}
|
|
3252
3268
|
const result = {
|
|
3253
3269
|
finalAnswer,
|
|
3254
3270
|
steps: this.steps,
|
|
@@ -3357,6 +3373,15 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
|
|
|
3357
3373
|
};
|
|
3358
3374
|
|
|
3359
3375
|
// src/core/prompts.ts
|
|
3376
|
+
var TOOL_GREP_SEARCH = "grep_search";
|
|
3377
|
+
var TOOL_GLOB_FILES = "glob_files";
|
|
3378
|
+
var TOOL_FILE_READ = "file_read";
|
|
3379
|
+
var TOOL_EDIT_LOCAL_FILE = "edit_local_file";
|
|
3380
|
+
var TOOL_CREATE_FILE = "create_file";
|
|
3381
|
+
var TOOL_BASH_EXECUTE = "bash_execute";
|
|
3382
|
+
var TOOL_SUBAGENT_DELEGATE = "subagent_delegate";
|
|
3383
|
+
var TOOL_WRITE_TODOS = "write_todos";
|
|
3384
|
+
var EXPLORE_SUBAGENT_TYPE = "explore";
|
|
3360
3385
|
function buildCoreSystemPrompt(contextSection = "") {
|
|
3361
3386
|
return `You are an autonomous AI assistant with access to tools. Your job is to help users by taking action and solving problems proactively.
|
|
3362
3387
|
|
|
@@ -3368,15 +3393,17 @@ CORE BEHAVIOR:
|
|
|
3368
3393
|
|
|
3369
3394
|
FOR SOFTWARE ENGINEERING TASKS:
|
|
3370
3395
|
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
|
|
3371
|
-
1. **Understand:** Think about the user's request and the relevant codebase context. Use '
|
|
3396
|
+
1. **Understand:** Think about the user's request and the relevant codebase context. Use '${TOOL_GREP_SEARCH}' and '${TOOL_GLOB_FILES}' search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use '${TOOL_FILE_READ}' to understand context and validate any assumptions you may have. If you need to read multiple files, you should make multiple parallel calls to '${TOOL_FILE_READ}'.
|
|
3397
|
+
When the task involves **complex refactoring, codebase exploration or system-wide analysis**, your **first and primary action** must be to delegate to the '${EXPLORE_SUBAGENT_TYPE}' agent using the '${TOOL_SUBAGENT_DELEGATE}' tool. Use it to build a comprehensive understanding of the code, its structure, and dependencies. For **simple, targeted searches** (like finding a specific function name, file path, or variable declaration), you should use '${TOOL_GREP_SEARCH}' or '${TOOL_GLOB_FILES}' directly.
|
|
3372
3398
|
2. **Plan:** Build a coherent and grounded (based on the understanding in step 1) plan for how you intend to resolve the user's task. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process. As part of the plan, you should use an iterative development process that includes writing unit tests to verify your changes. Use output logs or debug statements as part of this process to arrive at a solution.
|
|
3373
|
-
|
|
3399
|
+
If '${EXPLORE_SUBAGENT_TYPE}' subagent was used, do not ignore the output of the agent, you must use it as the foundation of your plan. For complex tasks, break them down into smaller, manageable subtasks and use the \`${TOOL_WRITE_TODOS}\` tool to track your progress. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process. As part of the plan, you should use an iterative development process that includes writing unit tests to verify your changes. Use output logs or debug statements as part of this process to arrive at a solution.
|
|
3400
|
+
3. **Implement:** Use the available tools (e.g., '${TOOL_EDIT_LOCAL_FILE}', '${TOOL_CREATE_FILE}', '${TOOL_BASH_EXECUTE}' ...) to act on the plan, strictly adhering to the project's established conventions.
|
|
3374
3401
|
4. **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. When executing test commands, prefer "run once" or "CI" modes to ensure the command terminates after completion.
|
|
3375
3402
|
5. **Verify (Standards):** VERY IMPORTANT: After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project (or obtained from the user). This ensures code quality and adherence to standards.
|
|
3376
3403
|
6. **Finalize:** After all verification passes, consider the task complete. Do not remove or revert any changes or created files (like tests). Await the user's next instruction.
|
|
3377
3404
|
|
|
3378
3405
|
SUBAGENT DELEGATION:
|
|
3379
|
-
- You have access to specialized subagents via the
|
|
3406
|
+
- You have access to specialized subagents via the ${TOOL_SUBAGENT_DELEGATE} tool
|
|
3380
3407
|
- Use subagents for focused exploration, planning, or review tasks:
|
|
3381
3408
|
* explore: Fast read-only codebase search (e.g., "find all auth files", "locate API endpoints")
|
|
3382
3409
|
* plan: Break down complex tasks into actionable steps
|
|
@@ -3392,7 +3419,7 @@ FOR GENERAL TASKS:
|
|
|
3392
3419
|
## Shell tool output token efficiency:
|
|
3393
3420
|
IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
|
|
3394
3421
|
|
|
3395
|
-
- Always prefer command flags that reduce output verbosity when using '
|
|
3422
|
+
- Always prefer command flags that reduce output verbosity when using '${TOOL_BASH_EXECUTE}'.
|
|
3396
3423
|
- Aim to minimize tool output tokens while still capturing necessary information.
|
|
3397
3424
|
- If a command is expected to produce a lot of output, use quiet or silent flags where available and appropriate.
|
|
3398
3425
|
- Always consider the trade-off between output verbosity and the need for information. If a command's full output is essential for understanding the result, avoid overly aggressive quieting that might obscure important details.
|
|
@@ -3402,9 +3429,9 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
|
|
|
3402
3429
|
EXAMPLES:
|
|
3403
3430
|
- "what should I wear in Texas?" \u2192 use weather tool for Texas
|
|
3404
3431
|
- "how about Japan?" \u2192 use weather tool for Japan (applying same question from context)
|
|
3405
|
-
- "enhance README" \u2192
|
|
3406
|
-
- "what packages installed?" \u2192
|
|
3407
|
-
- "find all components using React hooks" \u2192
|
|
3432
|
+
- "enhance README" \u2192 ${TOOL_FILE_READ} \u2192 generate \u2192 ${TOOL_EDIT_LOCAL_FILE}
|
|
3433
|
+
- "what packages installed?" \u2192 ${TOOL_GLOB_FILES} "**/package.json" \u2192 ${TOOL_FILE_READ}
|
|
3434
|
+
- "find all components using React hooks" \u2192 ${TOOL_SUBAGENT_DELEGATE}(task="find all components using React hooks", type="explore")
|
|
3408
3435
|
|
|
3409
3436
|
Remember: Use context from previous messages to understand follow-up questions.${contextSection}`;
|
|
3410
3437
|
}
|
|
@@ -8760,98 +8787,80 @@ var createFileTool = {
|
|
|
8760
8787
|
};
|
|
8761
8788
|
|
|
8762
8789
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/globFiles/index.js
|
|
8763
|
-
import {
|
|
8764
|
-
import {
|
|
8790
|
+
import { glob } from "glob";
|
|
8791
|
+
import { stat } from "fs/promises";
|
|
8765
8792
|
import path9 from "path";
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
if (!includeHidden && entry.name.startsWith(".")) {
|
|
8781
|
-
continue;
|
|
8782
|
-
}
|
|
8783
|
-
const relativePath = basePath ? path9.join(basePath, entry.name) : entry.name;
|
|
8784
|
-
const fullPath = path9.join(dir, entry.name);
|
|
8785
|
-
if (matchGlob(relativePath, pattern)) {
|
|
8786
|
-
matches.push(relativePath);
|
|
8787
|
-
}
|
|
8788
|
-
if (entry.isDirectory() && (pattern.includes("**") || pattern.includes("/"))) {
|
|
8789
|
-
const subMatches = await walkDir(fullPath, pattern, includeHidden, maxResults - matches.length, relativePath);
|
|
8790
|
-
matches.push(...subMatches);
|
|
8791
|
-
}
|
|
8792
|
-
}
|
|
8793
|
-
} catch (error) {
|
|
8794
|
-
}
|
|
8795
|
-
return matches;
|
|
8796
|
-
}
|
|
8797
|
-
async function listFiles(params) {
|
|
8798
|
-
const { pattern, cwd: relativeCwd, includeHidden = false, maxResults = 1e3 } = params;
|
|
8793
|
+
var DEFAULT_IGNORE_PATTERNS2 = [
|
|
8794
|
+
"**/node_modules/**",
|
|
8795
|
+
"**/.git/**",
|
|
8796
|
+
"**/dist/**",
|
|
8797
|
+
"**/build/**",
|
|
8798
|
+
"**/.next/**",
|
|
8799
|
+
"**/coverage/**",
|
|
8800
|
+
"**/.turbo/**",
|
|
8801
|
+
"**/.sst/**",
|
|
8802
|
+
"**/*.min.js",
|
|
8803
|
+
"**/*.min.css"
|
|
8804
|
+
];
|
|
8805
|
+
async function findFiles(params) {
|
|
8806
|
+
const { pattern, dir_path, case_sensitive = true, respect_git_ignore = true } = params;
|
|
8799
8807
|
const baseCwd = process.cwd();
|
|
8800
|
-
const
|
|
8801
|
-
if (!
|
|
8802
|
-
throw new Error(`Access denied: Cannot
|
|
8803
|
-
}
|
|
8804
|
-
const
|
|
8808
|
+
const targetDir = dir_path ? path9.resolve(baseCwd, path9.normalize(dir_path)) : baseCwd;
|
|
8809
|
+
if (!targetDir.startsWith(baseCwd)) {
|
|
8810
|
+
throw new Error(`Access denied: Cannot search outside of current working directory`);
|
|
8811
|
+
}
|
|
8812
|
+
const ignorePatterns = respect_git_ignore ? DEFAULT_IGNORE_PATTERNS2 : [];
|
|
8813
|
+
const matches = await glob(pattern, {
|
|
8814
|
+
cwd: targetDir,
|
|
8815
|
+
dot: false,
|
|
8816
|
+
// Don't match hidden files by default
|
|
8817
|
+
ignore: ignorePatterns,
|
|
8818
|
+
absolute: true,
|
|
8819
|
+
nodir: true,
|
|
8820
|
+
// Only return files, not directories
|
|
8821
|
+
nocase: !case_sensitive,
|
|
8822
|
+
// Case-insensitive if requested
|
|
8823
|
+
maxDepth: 20
|
|
8824
|
+
// Reasonable depth limit
|
|
8825
|
+
});
|
|
8805
8826
|
if (matches.length === 0) {
|
|
8806
|
-
return `No files found matching pattern: ${pattern}`;
|
|
8827
|
+
return `No files found matching pattern: ${pattern}${dir_path ? ` in ${dir_path}` : ""}`;
|
|
8807
8828
|
}
|
|
8808
|
-
const
|
|
8809
|
-
for (const
|
|
8829
|
+
const filesWithStats = [];
|
|
8830
|
+
for (const filePath of matches) {
|
|
8810
8831
|
try {
|
|
8811
|
-
const
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
size: stats.size,
|
|
8816
|
-
isDirectory: stats.isDirectory(),
|
|
8817
|
-
modified: stats.mtime.toISOString()
|
|
8832
|
+
const stats = await stat(filePath);
|
|
8833
|
+
filesWithStats.push({
|
|
8834
|
+
path: filePath,
|
|
8835
|
+
mtime: stats.mtimeMs
|
|
8818
8836
|
});
|
|
8819
|
-
} catch
|
|
8837
|
+
} catch {
|
|
8820
8838
|
continue;
|
|
8821
8839
|
}
|
|
8822
8840
|
}
|
|
8823
|
-
|
|
8824
|
-
const
|
|
8825
|
-
|
|
8826
|
-
const
|
|
8827
|
-
` : ""
|
|
8828
|
-
const
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
return `${summary}${cwdInfo}
|
|
8841
|
+
filesWithStats.sort((a, b) => b.mtime - a.mtime);
|
|
8842
|
+
const MAX_RESULTS = 500;
|
|
8843
|
+
const truncated = filesWithStats.length > MAX_RESULTS;
|
|
8844
|
+
const results = truncated ? filesWithStats.slice(0, MAX_RESULTS) : filesWithStats;
|
|
8845
|
+
const summary = `Found ${filesWithStats.length} file(s)${truncated ? ` (showing first ${MAX_RESULTS})` : ""} matching: ${pattern}`;
|
|
8846
|
+
const dirInfo = dir_path ? `
|
|
8847
|
+
Directory: ${dir_path}` : "";
|
|
8848
|
+
const filesList = results.map((file) => path9.relative(baseCwd, file.path)).join("\n");
|
|
8849
|
+
return `${summary}${dirInfo}
|
|
8850
|
+
|
|
8834
8851
|
${filesList}`;
|
|
8835
8852
|
}
|
|
8836
|
-
function formatBytes(bytes) {
|
|
8837
|
-
if (bytes === 0)
|
|
8838
|
-
return "0 B";
|
|
8839
|
-
const k = 1024;
|
|
8840
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
8841
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
8842
|
-
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
|
|
8843
|
-
}
|
|
8844
8853
|
var globFilesTool = {
|
|
8845
8854
|
name: "glob_files",
|
|
8846
8855
|
implementation: (context) => ({
|
|
8847
8856
|
toolFn: async (value) => {
|
|
8848
8857
|
const params = value;
|
|
8849
|
-
context.logger.info("\u{1F50D} GlobFiles:
|
|
8858
|
+
context.logger.info("\u{1F50D} GlobFiles: Finding files", {
|
|
8850
8859
|
pattern: params.pattern,
|
|
8851
|
-
|
|
8860
|
+
dir_path: params.dir_path || "."
|
|
8852
8861
|
});
|
|
8853
8862
|
try {
|
|
8854
|
-
const result = await
|
|
8863
|
+
const result = await findFiles(params);
|
|
8855
8864
|
context.logger.info("\u2705 GlobFiles: Success");
|
|
8856
8865
|
return result;
|
|
8857
8866
|
} catch (error) {
|
|
@@ -8861,25 +8870,25 @@ var globFilesTool = {
|
|
|
8861
8870
|
},
|
|
8862
8871
|
toolSchema: {
|
|
8863
8872
|
name: "glob_files",
|
|
8864
|
-
description: "
|
|
8873
|
+
description: "Efficiently finds files matching specific glob patterns (e.g., `src/**/*.ts`, `**/*.md`), returning absolute paths sorted by modification time (newest first). Use this to locate files by name or extension when you need to discover or explore files in a project.",
|
|
8865
8874
|
parameters: {
|
|
8866
8875
|
type: "object",
|
|
8867
8876
|
properties: {
|
|
8868
8877
|
pattern: {
|
|
8869
8878
|
type: "string",
|
|
8870
|
-
description: '
|
|
8879
|
+
description: 'The glob pattern to match against file paths. Supports wildcards (*, **), character ranges ([abc]), and brace expansion ({ts,tsx}). Examples: "*.ts" for TypeScript files in current dir, "src/**/*.tsx" for all TSX files in src tree, "**/*.{js,ts}" for all JS/TS files.'
|
|
8871
8880
|
},
|
|
8872
|
-
|
|
8881
|
+
dir_path: {
|
|
8873
8882
|
type: "string",
|
|
8874
|
-
description: "
|
|
8883
|
+
description: "Optional: The absolute path to the directory to search in. If not specified, uses the current working directory. Must be within the current working directory."
|
|
8875
8884
|
},
|
|
8876
|
-
|
|
8885
|
+
case_sensitive: {
|
|
8877
8886
|
type: "boolean",
|
|
8878
|
-
description: "
|
|
8887
|
+
description: "Optional: Whether the pattern matching should be case-sensitive. Defaults to true. Set to false for case-insensitive matching on case-sensitive file systems."
|
|
8879
8888
|
},
|
|
8880
|
-
|
|
8881
|
-
type: "
|
|
8882
|
-
description: "
|
|
8889
|
+
respect_git_ignore: {
|
|
8890
|
+
type: "boolean",
|
|
8891
|
+
description: "Optional: Whether to respect common ignore patterns (node_modules, .git, dist, build, etc.). Defaults to true. Set to false to include all files."
|
|
8883
8892
|
}
|
|
8884
8893
|
},
|
|
8885
8894
|
required: ["pattern"]
|
|
@@ -8889,158 +8898,144 @@ var globFilesTool = {
|
|
|
8889
8898
|
};
|
|
8890
8899
|
|
|
8891
8900
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/grepSearch/index.js
|
|
8892
|
-
import {
|
|
8893
|
-
import {
|
|
8901
|
+
import { globStream } from "glob";
|
|
8902
|
+
import { readFile, stat as stat2 } from "fs/promises";
|
|
8894
8903
|
import path10 from "path";
|
|
8895
8904
|
var MAX_FILE_SIZE3 = 10 * 1024 * 1024;
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8905
|
+
var DEFAULT_IGNORE_PATTERNS3 = [
|
|
8906
|
+
"**/node_modules/**",
|
|
8907
|
+
"**/.git/**",
|
|
8908
|
+
"**/dist/**",
|
|
8909
|
+
"**/build/**",
|
|
8910
|
+
"**/.next/**",
|
|
8911
|
+
"**/coverage/**",
|
|
8912
|
+
"**/*.min.js",
|
|
8913
|
+
"**/*.min.css",
|
|
8914
|
+
"**/package-lock.json",
|
|
8915
|
+
"**/pnpm-lock.yaml",
|
|
8916
|
+
"**/yarn.lock"
|
|
8917
|
+
];
|
|
8918
|
+
async function isBinaryFile2(filePath) {
|
|
8903
8919
|
try {
|
|
8904
|
-
const
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
const fullPath = path10.join(dir, entry.name);
|
|
8914
|
-
if (matchGlob2(relativePath, pattern)) {
|
|
8915
|
-
matches.push(relativePath);
|
|
8916
|
-
}
|
|
8917
|
-
if (entry.isDirectory() && (pattern.includes("**") || pattern.includes("/"))) {
|
|
8918
|
-
const subMatches = await walkDir2(fullPath, pattern, maxResults - matches.length, relativePath);
|
|
8919
|
-
matches.push(...subMatches);
|
|
8920
|
-
}
|
|
8921
|
-
}
|
|
8922
|
-
} catch (error) {
|
|
8920
|
+
const { openSync, readSync, closeSync } = await import("fs");
|
|
8921
|
+
const buffer = Buffer.alloc(8192);
|
|
8922
|
+
const fd = openSync(filePath, "r");
|
|
8923
|
+
const bytesRead = readSync(fd, buffer, 0, 8192, 0);
|
|
8924
|
+
closeSync(fd);
|
|
8925
|
+
const chunk = buffer.slice(0, bytesRead);
|
|
8926
|
+
return chunk.includes(0);
|
|
8927
|
+
} catch {
|
|
8928
|
+
return true;
|
|
8923
8929
|
}
|
|
8924
|
-
|
|
8930
|
+
}
|
|
8931
|
+
function isPathWithinWorkspace(targetPath, baseCwd) {
|
|
8932
|
+
const resolvedTarget = path10.resolve(targetPath);
|
|
8933
|
+
const resolvedBase = path10.resolve(baseCwd);
|
|
8934
|
+
return resolvedTarget.startsWith(resolvedBase);
|
|
8925
8935
|
}
|
|
8926
8936
|
async function searchFiles2(params) {
|
|
8927
|
-
const { pattern,
|
|
8937
|
+
const { pattern, dir_path, include } = params;
|
|
8928
8938
|
const baseCwd = process.cwd();
|
|
8929
|
-
const
|
|
8930
|
-
if (!
|
|
8931
|
-
throw new Error(`
|
|
8939
|
+
const targetDir = dir_path ? path10.resolve(baseCwd, dir_path) : baseCwd;
|
|
8940
|
+
if (!isPathWithinWorkspace(targetDir, baseCwd)) {
|
|
8941
|
+
throw new Error(`Path validation failed: "${dir_path}" resolves outside the allowed workspace directory`);
|
|
8942
|
+
}
|
|
8943
|
+
try {
|
|
8944
|
+
const stats = await stat2(targetDir);
|
|
8945
|
+
if (!stats.isDirectory()) {
|
|
8946
|
+
throw new Error(`Path is not a directory: ${dir_path}`);
|
|
8947
|
+
}
|
|
8948
|
+
} catch (error) {
|
|
8949
|
+
if (error.code === "ENOENT") {
|
|
8950
|
+
throw new Error(`Path does not exist: ${dir_path}`);
|
|
8951
|
+
}
|
|
8952
|
+
throw error;
|
|
8932
8953
|
}
|
|
8933
8954
|
let searchRegex;
|
|
8934
8955
|
try {
|
|
8935
|
-
|
|
8936
|
-
searchRegex = new RegExp(pattern, flags);
|
|
8956
|
+
searchRegex = new RegExp(pattern, "i");
|
|
8937
8957
|
} catch (error) {
|
|
8938
8958
|
throw new Error(`Invalid regex pattern: ${pattern}`);
|
|
8939
8959
|
}
|
|
8940
|
-
const
|
|
8941
|
-
const
|
|
8942
|
-
|
|
8943
|
-
|
|
8960
|
+
const globPattern = include || "**/*";
|
|
8961
|
+
const filesStream = globStream(globPattern, {
|
|
8962
|
+
cwd: targetDir,
|
|
8963
|
+
dot: false,
|
|
8964
|
+
// Skip hidden files
|
|
8965
|
+
ignore: DEFAULT_IGNORE_PATTERNS3,
|
|
8966
|
+
absolute: true,
|
|
8967
|
+
nodir: true
|
|
8968
|
+
// Only match files, not directories
|
|
8969
|
+
});
|
|
8970
|
+
const allMatches = [];
|
|
8971
|
+
let filesSearched = 0;
|
|
8972
|
+
const maxMatches = 500;
|
|
8973
|
+
for await (const filePath of filesStream) {
|
|
8974
|
+
if (allMatches.length >= maxMatches) {
|
|
8975
|
+
break;
|
|
8976
|
+
}
|
|
8977
|
+
const fileAbsPath = filePath;
|
|
8944
8978
|
try {
|
|
8945
|
-
const stats =
|
|
8946
|
-
if (stats.
|
|
8979
|
+
const stats = await stat2(fileAbsPath);
|
|
8980
|
+
if (stats.size > MAX_FILE_SIZE3) {
|
|
8947
8981
|
continue;
|
|
8948
8982
|
}
|
|
8949
|
-
if (isBinaryFile2(
|
|
8983
|
+
if (await isBinaryFile2(fileAbsPath)) {
|
|
8950
8984
|
continue;
|
|
8951
8985
|
}
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
for (const file of filteredFiles) {
|
|
8963
|
-
if (matches.length >= maxResults) {
|
|
8964
|
-
break;
|
|
8965
|
-
}
|
|
8966
|
-
filesSearched++;
|
|
8967
|
-
const fullPath = path10.join(targetCwd, file);
|
|
8968
|
-
try {
|
|
8969
|
-
const content = readFileSync3(fullPath, "utf-8");
|
|
8970
|
-
const lines = content.split("\n");
|
|
8971
|
-
for (let i = 0; i < lines.length; i++) {
|
|
8972
|
-
if (matches.length >= maxResults) {
|
|
8973
|
-
break;
|
|
8974
|
-
}
|
|
8975
|
-
const line = lines[i];
|
|
8976
|
-
if (searchRegex.test(line)) {
|
|
8977
|
-
const match = {
|
|
8978
|
-
file,
|
|
8979
|
-
line: i + 1,
|
|
8980
|
-
// 1-indexed line numbers
|
|
8981
|
-
content: line.trim()
|
|
8982
|
-
};
|
|
8983
|
-
if (contextLines > 0) {
|
|
8984
|
-
const before = [];
|
|
8985
|
-
const after = [];
|
|
8986
|
-
for (let j = Math.max(0, i - contextLines); j < i; j++) {
|
|
8987
|
-
before.push(lines[j]);
|
|
8988
|
-
}
|
|
8989
|
-
for (let j = i + 1; j <= Math.min(lines.length - 1, i + contextLines); j++) {
|
|
8990
|
-
after.push(lines[j]);
|
|
8991
|
-
}
|
|
8992
|
-
match.context = { before, after };
|
|
8993
|
-
}
|
|
8994
|
-
matches.push(match);
|
|
8986
|
+
filesSearched++;
|
|
8987
|
+
const content = await readFile(fileAbsPath, "utf8");
|
|
8988
|
+
const lines = content.split(/\r?\n/);
|
|
8989
|
+
lines.forEach((line, index) => {
|
|
8990
|
+
if (allMatches.length < maxMatches && searchRegex.test(line)) {
|
|
8991
|
+
allMatches.push({
|
|
8992
|
+
filePath: path10.relative(targetDir, fileAbsPath) || path10.basename(fileAbsPath),
|
|
8993
|
+
lineNumber: index + 1,
|
|
8994
|
+
line
|
|
8995
|
+
});
|
|
8995
8996
|
}
|
|
8996
|
-
|
|
8997
|
+
});
|
|
8998
|
+
} catch (readError) {
|
|
8999
|
+
const errCode = readError.code;
|
|
9000
|
+
if (errCode !== "ENOENT" && errCode !== "EACCES") {
|
|
9001
|
+
console.debug(`Could not read ${fileAbsPath}: ${readError.message}`);
|
|
8997
9002
|
}
|
|
8998
|
-
} catch {
|
|
8999
|
-
continue;
|
|
9000
9003
|
}
|
|
9001
9004
|
}
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
+
const searchDirDisplay = dir_path || ".";
|
|
9006
|
+
const filterInfo = include ? ` (filter: "${include}")` : "";
|
|
9007
|
+
if (allMatches.length === 0) {
|
|
9008
|
+
return `No matches found for pattern "${pattern}" in "${searchDirDisplay}"${filterInfo}.
|
|
9009
|
+
Searched ${filesSearched} file(s).`;
|
|
9005
9010
|
}
|
|
9006
|
-
const
|
|
9007
|
-
|
|
9011
|
+
const matchesByFile = allMatches.reduce((acc, match) => {
|
|
9012
|
+
if (!acc[match.filePath]) {
|
|
9013
|
+
acc[match.filePath] = [];
|
|
9014
|
+
}
|
|
9015
|
+
acc[match.filePath].push(match);
|
|
9016
|
+
acc[match.filePath].sort((a, b) => a.lineNumber - b.lineNumber);
|
|
9017
|
+
return acc;
|
|
9018
|
+
}, {});
|
|
9019
|
+
const matchCount = allMatches.length;
|
|
9020
|
+
const matchTerm = matchCount === 1 ? "match" : "matches";
|
|
9021
|
+
const truncated = matchCount >= maxMatches;
|
|
9022
|
+
let result = `Found ${matchCount} ${matchTerm}${truncated ? " (truncated)" : ""} for pattern "${pattern}" in "${searchDirDisplay}"${filterInfo}:
|
|
9008
9023
|
`;
|
|
9009
|
-
|
|
9024
|
+
result += `Searched ${filesSearched} file(s)
|
|
9025
|
+
---
|
|
9010
9026
|
`;
|
|
9011
|
-
const
|
|
9012
|
-
`
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
${match.context.before.map((l) => ` ${l}`).join("\n")}`;
|
|
9022
|
-
}
|
|
9023
|
-
if (match.context.after.length > 0) {
|
|
9024
|
-
result = `${result}
|
|
9025
|
-
Context after:
|
|
9026
|
-
${match.context.after.map((l) => ` ${l}`).join("\n")}`;
|
|
9027
|
-
}
|
|
9028
|
-
}
|
|
9029
|
-
return result;
|
|
9030
|
-
}).join("\n");
|
|
9031
|
-
return `${summary}${patternInfo}${cwdInfo}${matchesList}`;
|
|
9032
|
-
}
|
|
9033
|
-
function isBinaryFile2(filePath) {
|
|
9034
|
-
try {
|
|
9035
|
-
const buffer = Buffer.alloc(8192);
|
|
9036
|
-
const fd = __require("fs").openSync(filePath, "r");
|
|
9037
|
-
const bytesRead = __require("fs").readSync(fd, buffer, 0, 8192, 0);
|
|
9038
|
-
__require("fs").closeSync(fd);
|
|
9039
|
-
const chunk = buffer.slice(0, bytesRead);
|
|
9040
|
-
return chunk.includes(0);
|
|
9041
|
-
} catch {
|
|
9042
|
-
return true;
|
|
9027
|
+
for (const filePath in matchesByFile) {
|
|
9028
|
+
result += `File: ${filePath}
|
|
9029
|
+
`;
|
|
9030
|
+
matchesByFile[filePath].forEach((match) => {
|
|
9031
|
+
const trimmedLine = match.line.trim();
|
|
9032
|
+
const displayLine = trimmedLine.length > 200 ? trimmedLine.slice(0, 200) + "..." : trimmedLine;
|
|
9033
|
+
result += `L${match.lineNumber}: ${displayLine}
|
|
9034
|
+
`;
|
|
9035
|
+
});
|
|
9036
|
+
result += "---\n";
|
|
9043
9037
|
}
|
|
9038
|
+
return result.trim();
|
|
9044
9039
|
}
|
|
9045
9040
|
var grepSearchTool = {
|
|
9046
9041
|
name: "grep_search",
|
|
@@ -9049,8 +9044,8 @@ var grepSearchTool = {
|
|
|
9049
9044
|
const params = value;
|
|
9050
9045
|
context.logger.info("\u{1F50D} GrepSearch: Searching files", {
|
|
9051
9046
|
pattern: params.pattern,
|
|
9052
|
-
|
|
9053
|
-
|
|
9047
|
+
dir_path: params.dir_path || ".",
|
|
9048
|
+
include: params.include || "**/*"
|
|
9054
9049
|
});
|
|
9055
9050
|
try {
|
|
9056
9051
|
const result = await searchFiles2(params);
|
|
@@ -9063,33 +9058,21 @@ var grepSearchTool = {
|
|
|
9063
9058
|
},
|
|
9064
9059
|
toolSchema: {
|
|
9065
9060
|
name: "grep_search",
|
|
9066
|
-
description: "
|
|
9061
|
+
description: "Searches for a regular expression pattern within the content of files in a specified directory (or current working directory). Can filter files by a glob pattern. Returns the lines containing matches, along with their file paths and line numbers.",
|
|
9067
9062
|
parameters: {
|
|
9068
9063
|
type: "object",
|
|
9069
9064
|
properties: {
|
|
9070
9065
|
pattern: {
|
|
9071
9066
|
type: "string",
|
|
9072
|
-
description: "
|
|
9067
|
+
description: "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*')."
|
|
9073
9068
|
},
|
|
9074
|
-
|
|
9069
|
+
dir_path: {
|
|
9075
9070
|
type: "string",
|
|
9076
|
-
description:
|
|
9071
|
+
description: "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory."
|
|
9077
9072
|
},
|
|
9078
|
-
|
|
9073
|
+
include: {
|
|
9079
9074
|
type: "string",
|
|
9080
|
-
description: "
|
|
9081
|
-
},
|
|
9082
|
-
caseSensitive: {
|
|
9083
|
-
type: "boolean",
|
|
9084
|
-
description: "Whether the search should be case-sensitive (default: false)"
|
|
9085
|
-
},
|
|
9086
|
-
maxResults: {
|
|
9087
|
-
type: "number",
|
|
9088
|
-
description: "Maximum number of matches to return (default: 100). Prevents overwhelming output."
|
|
9089
|
-
},
|
|
9090
|
-
contextLines: {
|
|
9091
|
-
type: "number",
|
|
9092
|
-
description: "Number of context lines to show before and after each match (default: 0). Similar to grep -C option."
|
|
9075
|
+
description: "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores)."
|
|
9093
9076
|
}
|
|
9094
9077
|
},
|
|
9095
9078
|
required: ["pattern"]
|
|
@@ -9100,7 +9083,7 @@ var grepSearchTool = {
|
|
|
9100
9083
|
|
|
9101
9084
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/deleteFile/index.js
|
|
9102
9085
|
import { promises as fs10 } from "fs";
|
|
9103
|
-
import { existsSync as existsSync6, statSync as
|
|
9086
|
+
import { existsSync as existsSync6, statSync as statSync5 } from "fs";
|
|
9104
9087
|
import path11 from "path";
|
|
9105
9088
|
async function deleteFile(params) {
|
|
9106
9089
|
const { path: filePath, recursive = false } = params;
|
|
@@ -9113,7 +9096,7 @@ async function deleteFile(params) {
|
|
|
9113
9096
|
if (!existsSync6(resolvedPath)) {
|
|
9114
9097
|
throw new Error(`File or directory not found: ${filePath}`);
|
|
9115
9098
|
}
|
|
9116
|
-
const stats =
|
|
9099
|
+
const stats = statSync5(resolvedPath);
|
|
9117
9100
|
const isDirectory = stats.isDirectory();
|
|
9118
9101
|
const size = stats.size;
|
|
9119
9102
|
if (isDirectory && !recursive) {
|
|
@@ -9134,7 +9117,7 @@ var deleteFileTool = {
|
|
|
9134
9117
|
toolFn: async (value) => {
|
|
9135
9118
|
const params = value;
|
|
9136
9119
|
const resolvedPath = path11.resolve(process.cwd(), path11.normalize(params.path));
|
|
9137
|
-
const isDirectory = existsSync6(resolvedPath) &&
|
|
9120
|
+
const isDirectory = existsSync6(resolvedPath) && statSync5(resolvedPath).isDirectory();
|
|
9138
9121
|
context.logger.info(`\u{1F5D1}\uFE0F DeleteFile: Deleting ${isDirectory ? "directory" : "file"}`, {
|
|
9139
9122
|
path: params.path,
|
|
9140
9123
|
recursive: params.recursive
|
|
@@ -9910,7 +9893,7 @@ var ToolErrorType;
|
|
|
9910
9893
|
|
|
9911
9894
|
// src/utils/diffPreview.ts
|
|
9912
9895
|
import * as Diff from "diff";
|
|
9913
|
-
import { readFile } from "fs/promises";
|
|
9896
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
9914
9897
|
import { existsSync as existsSync8 } from "fs";
|
|
9915
9898
|
async function generateFileDiffPreview(args) {
|
|
9916
9899
|
try {
|
|
@@ -9925,7 +9908,7 @@ ${preview}${hasMore ? `
|
|
|
9925
9908
|
|
|
9926
9909
|
... (${lines2.length - 20} more lines)` : ""}`;
|
|
9927
9910
|
}
|
|
9928
|
-
const currentContent = await
|
|
9911
|
+
const currentContent = await readFile2(args.path, "utf-8");
|
|
9929
9912
|
const patch = Diff.createPatch(
|
|
9930
9913
|
args.path,
|
|
9931
9914
|
currentContent,
|
|
@@ -11301,6 +11284,10 @@ var ServerLlmBackend = class {
|
|
|
11301
11284
|
*/
|
|
11302
11285
|
async complete(model, messages, options, callback) {
|
|
11303
11286
|
logger.debug(`[ServerLlmBackend] Starting complete() with model: ${model}`);
|
|
11287
|
+
if (options.abortSignal?.aborted) {
|
|
11288
|
+
logger.debug("[ServerLlmBackend] Request aborted before start");
|
|
11289
|
+
return;
|
|
11290
|
+
}
|
|
11304
11291
|
return new Promise(async (resolve3, reject) => {
|
|
11305
11292
|
try {
|
|
11306
11293
|
logger.debug("[ServerLlmBackend] Making streaming request...");
|
|
@@ -11401,7 +11388,25 @@ var ServerLlmBackend = class {
|
|
|
11401
11388
|
}
|
|
11402
11389
|
}
|
|
11403
11390
|
});
|
|
11391
|
+
if (options.abortSignal) {
|
|
11392
|
+
const abortHandler = () => {
|
|
11393
|
+
logger.debug("[ServerLlmBackend] Abort signal received, destroying stream");
|
|
11394
|
+
response.data.destroy();
|
|
11395
|
+
resolve3();
|
|
11396
|
+
};
|
|
11397
|
+
if (options.abortSignal.aborted) {
|
|
11398
|
+
abortHandler();
|
|
11399
|
+
return;
|
|
11400
|
+
}
|
|
11401
|
+
options.abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
11402
|
+
response.data.on("close", () => {
|
|
11403
|
+
options.abortSignal?.removeEventListener("abort", abortHandler);
|
|
11404
|
+
});
|
|
11405
|
+
}
|
|
11404
11406
|
response.data.on("data", (chunk) => {
|
|
11407
|
+
if (options.abortSignal?.aborted) {
|
|
11408
|
+
return;
|
|
11409
|
+
}
|
|
11405
11410
|
parser.feed(chunk.toString());
|
|
11406
11411
|
});
|
|
11407
11412
|
response.data.on("end", () => {
|
|
@@ -11413,9 +11418,23 @@ var ServerLlmBackend = class {
|
|
|
11413
11418
|
}
|
|
11414
11419
|
});
|
|
11415
11420
|
response.data.on("error", (error) => {
|
|
11421
|
+
if (options.abortSignal?.aborted) {
|
|
11422
|
+
resolve3();
|
|
11423
|
+
return;
|
|
11424
|
+
}
|
|
11416
11425
|
reject(error);
|
|
11417
11426
|
});
|
|
11418
11427
|
} catch (error) {
|
|
11428
|
+
if (options.abortSignal?.aborted) {
|
|
11429
|
+
logger.debug("[ServerLlmBackend] Request was aborted, resolving gracefully");
|
|
11430
|
+
resolve3();
|
|
11431
|
+
return;
|
|
11432
|
+
}
|
|
11433
|
+
if (isAxiosError(error) && error.code === "ERR_CANCELED") {
|
|
11434
|
+
logger.debug("[ServerLlmBackend] Request was canceled, resolving gracefully");
|
|
11435
|
+
resolve3();
|
|
11436
|
+
return;
|
|
11437
|
+
}
|
|
11419
11438
|
logger.error("LLM completion failed", error);
|
|
11420
11439
|
if (isAxiosError(error)) {
|
|
11421
11440
|
logger.debug(
|
|
@@ -11566,8 +11585,10 @@ var ServerLlmBackend = class {
|
|
|
11566
11585
|
logger.debug(` Body: ${logger.formatBytes(bodySize)}`);
|
|
11567
11586
|
logger.debug(` Preview: ${bodyStr.substring(0, 200)}`);
|
|
11568
11587
|
const response = await axiosInstance.post(this.completionsEndpoint, requestBody, {
|
|
11569
|
-
responseType: "stream"
|
|
11588
|
+
responseType: "stream",
|
|
11570
11589
|
// Auth header is automatically injected by ApiClient interceptor
|
|
11590
|
+
// Pass abort signal to cancel request if user presses ESC
|
|
11591
|
+
signal: options.abortSignal
|
|
11571
11592
|
});
|
|
11572
11593
|
logger.debug(`\u2190 ${response.status} ${response.statusText}`);
|
|
11573
11594
|
return response;
|
|
@@ -11711,7 +11732,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
11711
11732
|
// package.json
|
|
11712
11733
|
var package_default = {
|
|
11713
11734
|
name: "@bike4mind/cli",
|
|
11714
|
-
version: "0.2.11-cli-
|
|
11735
|
+
version: "0.2.11-cli-todo-list.17329+bc504ca29",
|
|
11715
11736
|
type: "module",
|
|
11716
11737
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
11717
11738
|
license: "UNLICENSED",
|
|
@@ -11781,6 +11802,7 @@ var package_default = {
|
|
|
11781
11802
|
"eventsource-parser": "^3.0.6",
|
|
11782
11803
|
"file-type": "^18.7.0",
|
|
11783
11804
|
"fuse.js": "^7.1.0",
|
|
11805
|
+
glob: "^13.0.0",
|
|
11784
11806
|
"gray-matter": "^4.0.3",
|
|
11785
11807
|
ink: "^6.5.1",
|
|
11786
11808
|
"ink-select-input": "^6.2.0",
|
|
@@ -11815,10 +11837,10 @@ var package_default = {
|
|
|
11815
11837
|
},
|
|
11816
11838
|
devDependencies: {
|
|
11817
11839
|
"@bike4mind/agents": "0.1.0",
|
|
11818
|
-
"@bike4mind/common": "2.40.1-cli-
|
|
11819
|
-
"@bike4mind/mcp": "1.20.5-cli-
|
|
11820
|
-
"@bike4mind/services": "2.35.1-cli-
|
|
11821
|
-
"@bike4mind/utils": "2.1.5-cli-
|
|
11840
|
+
"@bike4mind/common": "2.40.1-cli-todo-list.17329+bc504ca29",
|
|
11841
|
+
"@bike4mind/mcp": "1.20.5-cli-todo-list.17329+bc504ca29",
|
|
11842
|
+
"@bike4mind/services": "2.35.1-cli-todo-list.17329+bc504ca29",
|
|
11843
|
+
"@bike4mind/utils": "2.1.5-cli-todo-list.17329+bc504ca29",
|
|
11822
11844
|
"@types/better-sqlite3": "^7.6.13",
|
|
11823
11845
|
"@types/diff": "^5.0.9",
|
|
11824
11846
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -11831,7 +11853,7 @@ var package_default = {
|
|
|
11831
11853
|
typescript: "^5.9.3",
|
|
11832
11854
|
vitest: "^3.2.4"
|
|
11833
11855
|
},
|
|
11834
|
-
gitHead: "
|
|
11856
|
+
gitHead: "bc504ca299975846c55f1c16f05f4e7535ce2fda"
|
|
11835
11857
|
};
|
|
11836
11858
|
|
|
11837
11859
|
// src/config/constants.ts
|
|
@@ -12187,6 +12209,131 @@ function createSubagentDelegateTool(orchestrator, parentSessionId) {
|
|
|
12187
12209
|
};
|
|
12188
12210
|
}
|
|
12189
12211
|
|
|
12212
|
+
// src/tools/writeTodosTool.ts
|
|
12213
|
+
var VALID_STATUSES = ["pending", "in_progress", "completed", "cancelled"];
|
|
12214
|
+
function validateTodos(todos) {
|
|
12215
|
+
if (!Array.isArray(todos)) {
|
|
12216
|
+
throw new Error("write_todos: todos must be an array");
|
|
12217
|
+
}
|
|
12218
|
+
if (todos.length === 0) {
|
|
12219
|
+
throw new Error("write_todos: todos array cannot be empty");
|
|
12220
|
+
}
|
|
12221
|
+
let inProgressCount = 0;
|
|
12222
|
+
const validatedTodos = todos.map((item, index) => {
|
|
12223
|
+
if (!item || typeof item !== "object") {
|
|
12224
|
+
throw new Error(`write_todos: item at index ${index} must be an object`);
|
|
12225
|
+
}
|
|
12226
|
+
const { description, status } = item;
|
|
12227
|
+
if (typeof description !== "string" || description.trim() === "") {
|
|
12228
|
+
throw new Error(`write_todos: item at index ${index} must have a non-empty description`);
|
|
12229
|
+
}
|
|
12230
|
+
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
12231
|
+
throw new Error(
|
|
12232
|
+
`write_todos: item at index ${index} has invalid status "${status}". Must be one of: ${VALID_STATUSES.join(", ")}`
|
|
12233
|
+
);
|
|
12234
|
+
}
|
|
12235
|
+
if (status === "in_progress") {
|
|
12236
|
+
inProgressCount++;
|
|
12237
|
+
}
|
|
12238
|
+
return {
|
|
12239
|
+
description: description.trim(),
|
|
12240
|
+
status
|
|
12241
|
+
};
|
|
12242
|
+
});
|
|
12243
|
+
if (inProgressCount > 1) {
|
|
12244
|
+
throw new Error(`write_todos: only one task can be 'in_progress' at a time, but found ${inProgressCount}`);
|
|
12245
|
+
}
|
|
12246
|
+
return validatedTodos;
|
|
12247
|
+
}
|
|
12248
|
+
function formatTodosOutput(todos) {
|
|
12249
|
+
const statusEmoji = {
|
|
12250
|
+
pending: "\u2B1C",
|
|
12251
|
+
in_progress: "\u{1F504}",
|
|
12252
|
+
completed: "\u2705",
|
|
12253
|
+
cancelled: "\u274C"
|
|
12254
|
+
};
|
|
12255
|
+
const lines = todos.map((todo, index) => {
|
|
12256
|
+
const emoji = statusEmoji[todo.status];
|
|
12257
|
+
return `${index + 1}. ${emoji} [${todo.status}] ${todo.description}`;
|
|
12258
|
+
});
|
|
12259
|
+
return lines.join("\n");
|
|
12260
|
+
}
|
|
12261
|
+
function createWriteTodosTool(todoStore) {
|
|
12262
|
+
return {
|
|
12263
|
+
toolFn: async (args) => {
|
|
12264
|
+
const params = args;
|
|
12265
|
+
const validatedTodos = validateTodos(params.todos);
|
|
12266
|
+
todoStore.todos = validatedTodos;
|
|
12267
|
+
if (todoStore.onUpdate) {
|
|
12268
|
+
todoStore.onUpdate(validatedTodos);
|
|
12269
|
+
}
|
|
12270
|
+
const output = formatTodosOutput(validatedTodos);
|
|
12271
|
+
return `Todo list updated successfully:
|
|
12272
|
+
|
|
12273
|
+
${output}`;
|
|
12274
|
+
},
|
|
12275
|
+
toolSchema: {
|
|
12276
|
+
name: "write_todos",
|
|
12277
|
+
description: `Create or update a list of subtasks for complex multi-step requests.
|
|
12278
|
+
|
|
12279
|
+
**When to use this tool:**
|
|
12280
|
+
- When handling complex requests that require multiple steps
|
|
12281
|
+
- To break down a large task into smaller, manageable subtasks
|
|
12282
|
+
- To track progress through a multi-step workflow
|
|
12283
|
+
|
|
12284
|
+
**Important guidelines:**
|
|
12285
|
+
- Call this tool early when receiving complex requests
|
|
12286
|
+
- Update the list immediately when starting, completing, or cancelling tasks
|
|
12287
|
+
- Only ONE task should be 'in_progress' at a time
|
|
12288
|
+
- Never batch updates - update as soon as state changes
|
|
12289
|
+
|
|
12290
|
+
**Status values:**
|
|
12291
|
+
- pending: Task not yet started
|
|
12292
|
+
- in_progress: Currently working on this task (only ONE allowed)
|
|
12293
|
+
- completed: Task finished successfully
|
|
12294
|
+
- cancelled: Task will not be completed
|
|
12295
|
+
|
|
12296
|
+
**Example:**
|
|
12297
|
+
If asked to "create a new React component with tests", break it down:
|
|
12298
|
+
1. Create component file \u2192 in_progress
|
|
12299
|
+
2. Add component logic \u2192 pending
|
|
12300
|
+
3. Create test file \u2192 pending
|
|
12301
|
+
4. Write unit tests \u2192 pending`,
|
|
12302
|
+
parameters: {
|
|
12303
|
+
type: "object",
|
|
12304
|
+
properties: {
|
|
12305
|
+
todos: {
|
|
12306
|
+
type: "array",
|
|
12307
|
+
description: "Complete list of todo items. This replaces any existing list. Each item needs a description and status.",
|
|
12308
|
+
items: {
|
|
12309
|
+
type: "object",
|
|
12310
|
+
properties: {
|
|
12311
|
+
description: {
|
|
12312
|
+
type: "string",
|
|
12313
|
+
description: "Clear, concise description of the task"
|
|
12314
|
+
},
|
|
12315
|
+
status: {
|
|
12316
|
+
type: "string",
|
|
12317
|
+
enum: ["pending", "in_progress", "completed", "cancelled"],
|
|
12318
|
+
description: "Current status of the task. Only ONE task can be 'in_progress' at a time."
|
|
12319
|
+
}
|
|
12320
|
+
},
|
|
12321
|
+
required: ["description", "status"]
|
|
12322
|
+
}
|
|
12323
|
+
}
|
|
12324
|
+
},
|
|
12325
|
+
required: ["todos"]
|
|
12326
|
+
}
|
|
12327
|
+
}
|
|
12328
|
+
};
|
|
12329
|
+
}
|
|
12330
|
+
function createTodoStore(onUpdate) {
|
|
12331
|
+
return {
|
|
12332
|
+
todos: [],
|
|
12333
|
+
onUpdate
|
|
12334
|
+
};
|
|
12335
|
+
}
|
|
12336
|
+
|
|
12190
12337
|
// src/index.tsx
|
|
12191
12338
|
process.removeAllListeners("warning");
|
|
12192
12339
|
process.on("warning", (warning) => {
|
|
@@ -12270,7 +12417,7 @@ function CliApp() {
|
|
|
12270
12417
|
logger.debug("[ABORT] ESC pressed - aborting current operation...");
|
|
12271
12418
|
state.abortController.abort();
|
|
12272
12419
|
setState((prev) => ({ ...prev, abortController: null }));
|
|
12273
|
-
|
|
12420
|
+
useCliStore.getState().setIsThinking(false);
|
|
12274
12421
|
}
|
|
12275
12422
|
return;
|
|
12276
12423
|
}
|
|
@@ -12471,7 +12618,9 @@ function CliApp() {
|
|
|
12471
12618
|
subagentConfigs
|
|
12472
12619
|
});
|
|
12473
12620
|
const subagentDelegateTool = createSubagentDelegateTool(orchestrator, newSession.id);
|
|
12474
|
-
const
|
|
12621
|
+
const todoStore = createTodoStore();
|
|
12622
|
+
const writeTodosTool = createWriteTodosTool(todoStore);
|
|
12623
|
+
const allTools = [...b4mTools, ...mcpTools, subagentDelegateTool, writeTodosTool];
|
|
12475
12624
|
console.log(`\u{1F916} Subagent delegation enabled (explore, plan, review)`);
|
|
12476
12625
|
const projectDir = state.configStore.getProjectConfigDir();
|
|
12477
12626
|
const contextResult = await loadContextFiles(projectDir);
|
|
@@ -12536,13 +12685,16 @@ ${contextResult.mergedContent}` : "";
|
|
|
12536
12685
|
}
|
|
12537
12686
|
};
|
|
12538
12687
|
agent.on("thought", stepHandler);
|
|
12688
|
+
agent.on("observation", stepHandler);
|
|
12539
12689
|
agent.on("action", stepHandler);
|
|
12540
12690
|
orchestrator.setBeforeRunCallback((subagent, _subagentType) => {
|
|
12541
12691
|
subagent.on("thought", stepHandler);
|
|
12692
|
+
subagent.on("observation", stepHandler);
|
|
12542
12693
|
subagent.on("action", stepHandler);
|
|
12543
12694
|
});
|
|
12544
12695
|
orchestrator.setAfterRunCallback((subagent, _subagentType) => {
|
|
12545
12696
|
subagent.off("thought", stepHandler);
|
|
12697
|
+
subagent.off("observation", stepHandler);
|
|
12546
12698
|
subagent.off("action", stepHandler);
|
|
12547
12699
|
});
|
|
12548
12700
|
setState((prev) => ({
|
|
@@ -12653,10 +12805,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
12653
12805
|
previousMessages: previousMessages.length > 0 ? previousMessages : void 0,
|
|
12654
12806
|
signal: abortController.signal
|
|
12655
12807
|
});
|
|
12656
|
-
if (abortController.signal.aborted) {
|
|
12657
|
-
logger.debug("[ABORT] Custom command was cancelled, discarding result");
|
|
12658
|
-
return;
|
|
12659
|
-
}
|
|
12660
12808
|
const permissionDenied = result.finalAnswer.startsWith("Permission denied for tool");
|
|
12661
12809
|
if (permissionDenied) {
|
|
12662
12810
|
console.log("\n\u26A0\uFE0F Action denied by user\n");
|
|
@@ -12829,10 +12977,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
12829
12977
|
previousMessages: previousMessages.length > 0 ? previousMessages : void 0,
|
|
12830
12978
|
signal: abortController.signal
|
|
12831
12979
|
});
|
|
12832
|
-
if (abortController.signal.aborted) {
|
|
12833
|
-
logger.debug("[ABORT] Operation was cancelled, discarding result");
|
|
12834
|
-
return;
|
|
12835
|
-
}
|
|
12836
12980
|
const permissionDenied = result.finalAnswer.startsWith("Permission denied for tool");
|
|
12837
12981
|
if (permissionDenied) {
|
|
12838
12982
|
console.log("\n\u26A0\uFE0F Action denied by user\n");
|
|
@@ -12956,7 +13100,7 @@ ${output}` : output.trim() || "(no output)",
|
|
|
12956
13100
|
if (!imageStore) {
|
|
12957
13101
|
if (!imageStoreInitPromise.current) {
|
|
12958
13102
|
imageStoreInitPromise.current = (async () => {
|
|
12959
|
-
const { ImageStore: ImageStoreClass } = await import("./ImageStore-
|
|
13103
|
+
const { ImageStore: ImageStoreClass } = await import("./ImageStore-MMUOUPI2.js");
|
|
12960
13104
|
const newImageStore = new ImageStoreClass();
|
|
12961
13105
|
setState((prev) => ({
|
|
12962
13106
|
...prev,
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
findMostSimilarMemento,
|
|
4
4
|
getRelevantMementos
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-6AYWWNXH.js";
|
|
6
|
+
import "./chunk-M4EAFD3H.js";
|
|
7
|
+
import "./chunk-OCYRD7D6.js";
|
|
8
8
|
import "./chunk-WCYNJOOX.js";
|
|
9
|
-
import "./chunk-PDX44BCA.js";
|
|
10
9
|
export {
|
|
11
10
|
findMostSimilarMemento,
|
|
12
11
|
getRelevantMementos
|
|
@@ -120,7 +120,7 @@ import {
|
|
|
120
120
|
validateMermaidSyntax,
|
|
121
121
|
warmUpSettingsCache,
|
|
122
122
|
withRetry
|
|
123
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-M4EAFD3H.js";
|
|
124
124
|
import {
|
|
125
125
|
Logger,
|
|
126
126
|
NotificationDeduplicator,
|
|
@@ -128,9 +128,8 @@ import {
|
|
|
128
128
|
notifyEventLogsToSlack,
|
|
129
129
|
postLowCreditsNotificationToSlack,
|
|
130
130
|
postMessageToSlack
|
|
131
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-OCYRD7D6.js";
|
|
132
132
|
import "./chunk-WCYNJOOX.js";
|
|
133
|
-
import "./chunk-PDX44BCA.js";
|
|
134
133
|
export {
|
|
135
134
|
AWSBackend,
|
|
136
135
|
AdminSettingsCache,
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
SubtractCreditsSchema,
|
|
4
4
|
subtractCredits
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-WENSCUXW.js";
|
|
6
|
+
import "./chunk-M4EAFD3H.js";
|
|
7
|
+
import "./chunk-OCYRD7D6.js";
|
|
8
8
|
import "./chunk-WCYNJOOX.js";
|
|
9
|
-
import "./chunk-PDX44BCA.js";
|
|
10
9
|
export {
|
|
11
10
|
SubtractCreditsSchema,
|
|
12
11
|
subtractCredits
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.11-cli-
|
|
3
|
+
"version": "0.2.11-cli-todo-list.17329+bc504ca29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"eventsource-parser": "^3.0.6",
|
|
71
71
|
"file-type": "^18.7.0",
|
|
72
72
|
"fuse.js": "^7.1.0",
|
|
73
|
+
"glob": "^13.0.0",
|
|
73
74
|
"gray-matter": "^4.0.3",
|
|
74
75
|
"ink": "^6.5.1",
|
|
75
76
|
"ink-select-input": "^6.2.0",
|
|
@@ -104,10 +105,10 @@
|
|
|
104
105
|
},
|
|
105
106
|
"devDependencies": {
|
|
106
107
|
"@bike4mind/agents": "0.1.0",
|
|
107
|
-
"@bike4mind/common": "2.40.1-cli-
|
|
108
|
-
"@bike4mind/mcp": "1.20.5-cli-
|
|
109
|
-
"@bike4mind/services": "2.35.1-cli-
|
|
110
|
-
"@bike4mind/utils": "2.1.5-cli-
|
|
108
|
+
"@bike4mind/common": "2.40.1-cli-todo-list.17329+bc504ca29",
|
|
109
|
+
"@bike4mind/mcp": "1.20.5-cli-todo-list.17329+bc504ca29",
|
|
110
|
+
"@bike4mind/services": "2.35.1-cli-todo-list.17329+bc504ca29",
|
|
111
|
+
"@bike4mind/utils": "2.1.5-cli-todo-list.17329+bc504ca29",
|
|
111
112
|
"@types/better-sqlite3": "^7.6.13",
|
|
112
113
|
"@types/diff": "^5.0.9",
|
|
113
114
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -120,5 +121,5 @@
|
|
|
120
121
|
"typescript": "^5.9.3",
|
|
121
122
|
"vitest": "^3.2.4"
|
|
122
123
|
},
|
|
123
|
-
"gitHead": "
|
|
124
|
+
"gitHead": "bc504ca299975846c55f1c16f05f4e7535ce2fda"
|
|
124
125
|
}
|
package/dist/chunk-PDX44BCA.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
__require
|
|
11
|
-
};
|