@bike4mind/cli 0.2.12-cli-todo-list.17408 → 0.2.12-feat-secops-secrets.17399
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 -21
- package/dist/{ImageStore-MMUOUPI2.js → ImageStore-RQZ7OF7P.js} +1 -0
- package/dist/{artifactExtractor-URGQJDMT.js → artifactExtractor-F2VLARCK.js} +1 -0
- package/dist/{chunk-OCYRD7D6.js → chunk-AMDXHL6S.js} +1 -1
- package/dist/{chunk-INYINU6X.js → chunk-BU5TP3BH.js} +1 -1
- package/dist/{chunk-JXROCVSM.js → chunk-ID4NS6KF.js} +1 -1
- package/dist/chunk-PDX44BCA.js +11 -0
- package/dist/{chunk-7N7AZPLK.js → chunk-RJFNIMVH.js} +1 -1
- package/dist/{chunk-XM52K32A.js → chunk-ZHCX7BLB.js} +1 -1
- package/dist/{create-IGUAAYLC.js → create-MXBWYABO.js} +4 -3
- package/dist/{formatConverter-5QEJDW24.js → formatConverter-I7EIUVDY.js} +1 -0
- package/dist/index.js +302 -558
- package/dist/{llmMarkdownGenerator-QLIULZ4H.js → llmMarkdownGenerator-AVPOXVE5.js} +1 -0
- package/dist/{markdownGenerator-WE5PLZRI.js → markdownGenerator-FBXMTP3B.js} +1 -0
- package/dist/{mementoService-OGW5IEJX.js → mementoService-4WLVEWPZ.js} +4 -3
- package/dist/{notificationDeduplicator-UTHJHMSZ.js → notificationDeduplicator-UW7D75QS.js} +2 -1
- package/dist/{src-7JPWO5SS.js → src-SYE7WXBJ.js} +1 -0
- package/dist/{src-557ODV2Y.js → src-YU4VN5YG.js} +3 -2
- package/dist/{subtractCredits-QSGEUH6U.js → subtractCredits-FGISXF2D.js} +4 -3
- package/dist/{utils-JCHWDM4Z.js → utils-JPMDGUBL.js} +1 -0
- package/package.json +7 -9
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-ZHCX7BLB.js";
|
|
8
|
+
import "./chunk-ID4NS6KF.js";
|
|
9
|
+
import "./chunk-RJFNIMVH.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-BU5TP3BH.js";
|
|
19
19
|
import {
|
|
20
20
|
Logger
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-AMDXHL6S.js";
|
|
22
22
|
import "./chunk-BPFEGDC7.js";
|
|
23
23
|
import {
|
|
24
24
|
AiEvents,
|
|
@@ -74,6 +74,9 @@ import {
|
|
|
74
74
|
b4mLLMTools,
|
|
75
75
|
getMcpProviderMetadata
|
|
76
76
|
} from "./chunk-OHR7UCTC.js";
|
|
77
|
+
import {
|
|
78
|
+
__require
|
|
79
|
+
} from "./chunk-PDX44BCA.js";
|
|
77
80
|
|
|
78
81
|
// src/index.tsx
|
|
79
82
|
import React17, { useState as useState8, useEffect as useEffect3, useCallback, useRef as useRef2 } from "react";
|
|
@@ -179,11 +182,11 @@ function CustomTextInput({
|
|
|
179
182
|
setCursorOffset(Math.min(value.length, cursorOffset + 1));
|
|
180
183
|
return;
|
|
181
184
|
}
|
|
182
|
-
if (!key.ctrl && !key.meta && input.length
|
|
185
|
+
if (!key.ctrl && !key.meta && input.length === 1) {
|
|
183
186
|
const sanitizedInput = input === "\r" ? "\n" : input;
|
|
184
187
|
const newValue = value.slice(0, cursorOffset) + sanitizedInput + value.slice(cursorOffset);
|
|
185
188
|
onChange(newValue);
|
|
186
|
-
setCursorOffset(cursorOffset +
|
|
189
|
+
setCursorOffset(cursorOffset + 1);
|
|
187
190
|
}
|
|
188
191
|
},
|
|
189
192
|
{ isActive: !disabled }
|
|
@@ -710,7 +713,7 @@ var ImageInputDetector = class {
|
|
|
710
713
|
if (!this.looksLikeFilePath(input)) return null;
|
|
711
714
|
let filepath = input.trim();
|
|
712
715
|
filepath = filepath.replace(/^["']|["']$/g, "");
|
|
713
|
-
filepath = filepath.replace(
|
|
716
|
+
filepath = filepath.replace(/\\\s/g, " ");
|
|
714
717
|
if (!existsSync(filepath)) return null;
|
|
715
718
|
const stats = statSync2(filepath);
|
|
716
719
|
if (!stats.isFile()) return null;
|
|
@@ -737,15 +740,7 @@ var ImageInputDetector = class {
|
|
|
737
740
|
*/
|
|
738
741
|
static looksLikeFilePath(input) {
|
|
739
742
|
const trimmed = input.trim();
|
|
740
|
-
if (trimmed.startsWith("/")) {
|
|
741
|
-
const hasMultipleSegments = trimmed.indexOf("/", 1) !== -1;
|
|
742
|
-
const hasImageExtension = this.SUPPORTED_EXTENSIONS.some((ext) => trimmed.toLowerCase().endsWith(ext));
|
|
743
|
-
if (hasMultipleSegments || hasImageExtension) {
|
|
744
|
-
return true;
|
|
745
|
-
}
|
|
746
|
-
return false;
|
|
747
|
-
}
|
|
748
|
-
if (trimmed.match(/^[a-zA-Z]:\\/)) {
|
|
743
|
+
if (trimmed.startsWith("/") || trimmed.match(/^[a-zA-Z]:\\/)) {
|
|
749
744
|
return true;
|
|
750
745
|
}
|
|
751
746
|
if (trimmed.startsWith("~")) {
|
|
@@ -774,16 +769,6 @@ var ImageInputDetector = class {
|
|
|
774
769
|
};
|
|
775
770
|
|
|
776
771
|
// src/components/InputPrompt.tsx
|
|
777
|
-
function looksLikeFilePath(input) {
|
|
778
|
-
const trimmed = input.trim();
|
|
779
|
-
if (trimmed.startsWith("/")) {
|
|
780
|
-
const hasMultipleSegments = trimmed.indexOf("/", 1) !== -1;
|
|
781
|
-
if (hasMultipleSegments) return true;
|
|
782
|
-
}
|
|
783
|
-
if (trimmed.startsWith("~")) return true;
|
|
784
|
-
if (trimmed.match(/^[a-zA-Z]:\\/)) return true;
|
|
785
|
-
return false;
|
|
786
|
-
}
|
|
787
772
|
function findAtTrigger(value) {
|
|
788
773
|
for (let i = value.length - 1; i >= 0; i--) {
|
|
789
774
|
if (value[i] === "@") {
|
|
@@ -827,7 +812,7 @@ function InputPrompt({
|
|
|
827
812
|
useEffect(() => {
|
|
828
813
|
onBashModeChange?.(isBashMode);
|
|
829
814
|
}, [isBashMode, onBashModeChange]);
|
|
830
|
-
const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active
|
|
815
|
+
const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active;
|
|
831
816
|
const commandQuery = shouldShowCommandAutocomplete ? value.slice(1) : "";
|
|
832
817
|
const filteredCommands = useMemo(() => {
|
|
833
818
|
if (!shouldShowCommandAutocomplete) return [];
|
|
@@ -1373,7 +1358,7 @@ function isNameSuffix(value) {
|
|
|
1373
1358
|
|
|
1374
1359
|
// src/utils/processFileReferences.ts
|
|
1375
1360
|
var FILE_REFERENCE_REGEX = /(?:^|\s)@([^\s@]+)/g;
|
|
1376
|
-
function
|
|
1361
|
+
function looksLikeFilePath(ref) {
|
|
1377
1362
|
if (ref.includes("/") || ref.includes(path2.sep)) {
|
|
1378
1363
|
return true;
|
|
1379
1364
|
}
|
|
@@ -1396,7 +1381,7 @@ function extractFileReferences(message) {
|
|
|
1396
1381
|
let match;
|
|
1397
1382
|
while ((match = FILE_REFERENCE_REGEX.exec(message)) !== null) {
|
|
1398
1383
|
const ref = match[1];
|
|
1399
|
-
if (
|
|
1384
|
+
if (looksLikeFilePath(ref)) {
|
|
1400
1385
|
references.push(ref);
|
|
1401
1386
|
}
|
|
1402
1387
|
}
|
|
@@ -3108,21 +3093,6 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3108
3093
|
let finalAnswer = "";
|
|
3109
3094
|
let reachedMaxIterations = false;
|
|
3110
3095
|
while (iterations < maxIterations) {
|
|
3111
|
-
if (options.signal?.aborted) {
|
|
3112
|
-
this.context.logger.info("[ReActAgent] Operation aborted by user");
|
|
3113
|
-
const result2 = {
|
|
3114
|
-
finalAnswer: "Interrupted",
|
|
3115
|
-
steps: this.steps,
|
|
3116
|
-
completionInfo: {
|
|
3117
|
-
totalTokens: this.totalTokens,
|
|
3118
|
-
iterations,
|
|
3119
|
-
toolCalls: this.toolCallCount,
|
|
3120
|
-
reachedMaxIterations: false
|
|
3121
|
-
}
|
|
3122
|
-
};
|
|
3123
|
-
this.emit("complete", result2);
|
|
3124
|
-
return result2;
|
|
3125
|
-
}
|
|
3126
3096
|
iterations++;
|
|
3127
3097
|
this.context.logger.debug(`[ReActAgent] Starting iteration ${iterations}/${maxIterations}`);
|
|
3128
3098
|
let iterationComplete = false;
|
|
@@ -3136,8 +3106,7 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3136
3106
|
stream: false,
|
|
3137
3107
|
tools: this.context.tools,
|
|
3138
3108
|
maxTokens,
|
|
3139
|
-
temperature
|
|
3140
|
-
abortSignal: options.signal
|
|
3109
|
+
temperature
|
|
3141
3110
|
},
|
|
3142
3111
|
async (texts, completionInfo) => {
|
|
3143
3112
|
for (const text of texts) {
|
|
@@ -3280,9 +3249,6 @@ ${options.context}` : this.getSystemPrompt()
|
|
|
3280
3249
|
this.emit("final_answer", finalStep);
|
|
3281
3250
|
}
|
|
3282
3251
|
}
|
|
3283
|
-
if (options.signal?.aborted && !finalAnswer) {
|
|
3284
|
-
finalAnswer = "Interrupted";
|
|
3285
|
-
}
|
|
3286
3252
|
const result = {
|
|
3287
3253
|
finalAnswer,
|
|
3288
3254
|
steps: this.steps,
|
|
@@ -3390,70 +3356,6 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
|
|
|
3390
3356
|
}
|
|
3391
3357
|
};
|
|
3392
3358
|
|
|
3393
|
-
// src/core/prompts.ts
|
|
3394
|
-
var TOOL_GREP_SEARCH = "grep_search";
|
|
3395
|
-
var TOOL_GLOB_FILES = "glob_files";
|
|
3396
|
-
var TOOL_FILE_READ = "file_read";
|
|
3397
|
-
var TOOL_EDIT_LOCAL_FILE = "edit_local_file";
|
|
3398
|
-
var TOOL_CREATE_FILE = "create_file";
|
|
3399
|
-
var TOOL_BASH_EXECUTE = "bash_execute";
|
|
3400
|
-
var TOOL_SUBAGENT_DELEGATE = "subagent_delegate";
|
|
3401
|
-
var TOOL_WRITE_TODOS = "write_todos";
|
|
3402
|
-
var EXPLORE_SUBAGENT_TYPE = "explore";
|
|
3403
|
-
function buildCoreSystemPrompt(contextSection = "") {
|
|
3404
|
-
return `You are an autonomous AI assistant with access to tools. Your job is to help users by taking action and solving problems proactively.
|
|
3405
|
-
|
|
3406
|
-
CORE BEHAVIOR:
|
|
3407
|
-
- Be proactive: Take action instead of asking for permission or clarification
|
|
3408
|
-
- Make smart assumptions: If unclear, choose the most reasonable interpretation
|
|
3409
|
-
- Use conversation history: Reference previous exchanges to understand context
|
|
3410
|
-
- Complete tasks fully: Don't just show what to do - actually do it
|
|
3411
|
-
|
|
3412
|
-
FOR SOFTWARE ENGINEERING TASKS:
|
|
3413
|
-
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
|
|
3414
|
-
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}'.
|
|
3415
|
-
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.
|
|
3416
|
-
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.
|
|
3417
|
-
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.
|
|
3418
|
-
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.
|
|
3419
|
-
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.
|
|
3420
|
-
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.
|
|
3421
|
-
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.
|
|
3422
|
-
|
|
3423
|
-
SUBAGENT DELEGATION:
|
|
3424
|
-
- You have access to specialized subagents via the ${TOOL_SUBAGENT_DELEGATE} tool
|
|
3425
|
-
- Use subagents for focused exploration, planning, or review tasks:
|
|
3426
|
-
* explore: Fast read-only codebase search (e.g., "find all auth files", "locate API endpoints")
|
|
3427
|
-
* plan: Break down complex tasks into actionable steps
|
|
3428
|
-
* review: Analyze code quality and identify issues
|
|
3429
|
-
- Subagents keep the main conversation clean and run faster with optimized models
|
|
3430
|
-
- Delegate when you need to search extensively or analyze code structure
|
|
3431
|
-
|
|
3432
|
-
FOR GENERAL TASKS:
|
|
3433
|
-
- Use available tools to get information (weather, web search, calculations, etc.)
|
|
3434
|
-
- When user asks follow-up questions, use conversation context to understand what they're referring to
|
|
3435
|
-
- If user asks "how about X?" after a previous question, apply the same question type to X
|
|
3436
|
-
|
|
3437
|
-
## Shell tool output token efficiency:
|
|
3438
|
-
IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
|
|
3439
|
-
|
|
3440
|
-
- Always prefer command flags that reduce output verbosity when using '${TOOL_BASH_EXECUTE}'.
|
|
3441
|
-
- Aim to minimize tool output tokens while still capturing necessary information.
|
|
3442
|
-
- If a command is expected to produce a lot of output, use quiet or silent flags where available and appropriate.
|
|
3443
|
-
- 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.
|
|
3444
|
-
- If a command does not have quiet/silent flags or for commands with potentially long output that may not be useful, redirect stdout and stderr to temp files in the project's temporary directory. For example: 'command > <temp_dir>/out.log 2> <temp_dir>/err.log'.
|
|
3445
|
-
- After the command runs, inspect the temp files (e.g. '<temp_dir>/out.log' and '<temp_dir>/err.log') using commands like 'grep', 'tail', 'head', ... (or platform equivalents). Remove the temp files when done.
|
|
3446
|
-
|
|
3447
|
-
EXAMPLES:
|
|
3448
|
-
- "what should I wear in Texas?" \u2192 use weather tool for Texas
|
|
3449
|
-
- "how about Japan?" \u2192 use weather tool for Japan (applying same question from context)
|
|
3450
|
-
- "enhance README" \u2192 ${TOOL_FILE_READ} \u2192 generate \u2192 ${TOOL_EDIT_LOCAL_FILE}
|
|
3451
|
-
- "what packages installed?" \u2192 ${TOOL_GLOB_FILES} "**/package.json" \u2192 ${TOOL_FILE_READ}
|
|
3452
|
-
- "find all components using React hooks" \u2192 ${TOOL_SUBAGENT_DELEGATE}(task="find all components using React hooks", type="explore")
|
|
3453
|
-
|
|
3454
|
-
Remember: Use context from previous messages to understand follow-up questions.${contextSection}`;
|
|
3455
|
-
}
|
|
3456
|
-
|
|
3457
3359
|
// ../../b4m-core/packages/services/dist/src/referService/generateCodes.js
|
|
3458
3360
|
import { randomBytes } from "crypto";
|
|
3459
3361
|
import range from "lodash/range.js";
|
|
@@ -8805,80 +8707,98 @@ var createFileTool = {
|
|
|
8805
8707
|
};
|
|
8806
8708
|
|
|
8807
8709
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/globFiles/index.js
|
|
8808
|
-
import {
|
|
8809
|
-
import {
|
|
8710
|
+
import { readdir } from "fs/promises";
|
|
8711
|
+
import { statSync as statSync5 } from "fs";
|
|
8810
8712
|
import path9 from "path";
|
|
8811
|
-
|
|
8812
|
-
"
|
|
8813
|
-
"
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8713
|
+
function matchGlob(filePath, pattern) {
|
|
8714
|
+
let regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, ".").replace(/\{([^}]+)\}/g, (_, options) => `(${options.split(",").join("|")})`).replace(/\[([^\]]+)\]/g, "[$1]");
|
|
8715
|
+
regexPattern = regexPattern.replace(/\{\{GLOBSTAR\}\}\//g, "(.*/)?").replace(/\/\{\{GLOBSTAR\}\}/g, "(/.*)?").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
8716
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
8717
|
+
return regex.test(filePath);
|
|
8718
|
+
}
|
|
8719
|
+
async function walkDir(dir, pattern, includeHidden, maxResults, basePath = "") {
|
|
8720
|
+
const matches = [];
|
|
8721
|
+
try {
|
|
8722
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
8723
|
+
for (const entry of entries) {
|
|
8724
|
+
if (matches.length >= maxResults) {
|
|
8725
|
+
break;
|
|
8726
|
+
}
|
|
8727
|
+
if (!includeHidden && entry.name.startsWith(".")) {
|
|
8728
|
+
continue;
|
|
8729
|
+
}
|
|
8730
|
+
const relativePath = basePath ? path9.join(basePath, entry.name) : entry.name;
|
|
8731
|
+
const fullPath = path9.join(dir, entry.name);
|
|
8732
|
+
if (matchGlob(relativePath, pattern)) {
|
|
8733
|
+
matches.push(relativePath);
|
|
8734
|
+
}
|
|
8735
|
+
if (entry.isDirectory() && (pattern.includes("**") || pattern.includes("/"))) {
|
|
8736
|
+
const subMatches = await walkDir(fullPath, pattern, includeHidden, maxResults - matches.length, relativePath);
|
|
8737
|
+
matches.push(...subMatches);
|
|
8738
|
+
}
|
|
8739
|
+
}
|
|
8740
|
+
} catch (error) {
|
|
8741
|
+
}
|
|
8742
|
+
return matches;
|
|
8743
|
+
}
|
|
8744
|
+
async function listFiles(params) {
|
|
8745
|
+
const { pattern, cwd: relativeCwd, includeHidden = false, maxResults = 1e3 } = params;
|
|
8825
8746
|
const baseCwd = process.cwd();
|
|
8826
|
-
const
|
|
8827
|
-
if (!
|
|
8828
|
-
throw new Error(`Access denied: Cannot
|
|
8829
|
-
}
|
|
8830
|
-
const
|
|
8831
|
-
const matches = await glob(pattern, {
|
|
8832
|
-
cwd: targetDir,
|
|
8833
|
-
dot: false,
|
|
8834
|
-
// Don't match hidden files by default
|
|
8835
|
-
ignore: ignorePatterns,
|
|
8836
|
-
absolute: true,
|
|
8837
|
-
nodir: true,
|
|
8838
|
-
// Only return files, not directories
|
|
8839
|
-
nocase: !case_sensitive,
|
|
8840
|
-
// Case-insensitive if requested
|
|
8841
|
-
maxDepth: 20
|
|
8842
|
-
// Reasonable depth limit
|
|
8843
|
-
});
|
|
8747
|
+
const targetCwd = relativeCwd ? path9.resolve(baseCwd, path9.normalize(relativeCwd)) : baseCwd;
|
|
8748
|
+
if (!targetCwd.startsWith(baseCwd)) {
|
|
8749
|
+
throw new Error(`Access denied: Cannot list files outside of current working directory`);
|
|
8750
|
+
}
|
|
8751
|
+
const matches = await walkDir(targetCwd, pattern, includeHidden, maxResults);
|
|
8844
8752
|
if (matches.length === 0) {
|
|
8845
|
-
return `No files found matching pattern: ${pattern}
|
|
8753
|
+
return `No files found matching pattern: ${pattern}`;
|
|
8846
8754
|
}
|
|
8847
|
-
const
|
|
8848
|
-
for (const
|
|
8755
|
+
const filesInfo = [];
|
|
8756
|
+
for (const match of matches) {
|
|
8849
8757
|
try {
|
|
8850
|
-
const
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8758
|
+
const fullPath = path9.join(targetCwd, match);
|
|
8759
|
+
const stats = statSync5(fullPath);
|
|
8760
|
+
filesInfo.push({
|
|
8761
|
+
path: match,
|
|
8762
|
+
size: stats.size,
|
|
8763
|
+
isDirectory: stats.isDirectory(),
|
|
8764
|
+
modified: stats.mtime.toISOString()
|
|
8854
8765
|
});
|
|
8855
|
-
} catch {
|
|
8766
|
+
} catch (error) {
|
|
8856
8767
|
continue;
|
|
8857
8768
|
}
|
|
8858
8769
|
}
|
|
8859
|
-
|
|
8860
|
-
const
|
|
8861
|
-
|
|
8862
|
-
const
|
|
8863
|
-
|
|
8864
|
-
const
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8770
|
+
const truncated = matches.length >= maxResults;
|
|
8771
|
+
const summary = `Found ${filesInfo.length} file(s)${truncated ? ` (truncated to ${maxResults})` : ""} matching: ${pattern}
|
|
8772
|
+
`;
|
|
8773
|
+
const cwdInfo = relativeCwd ? `Directory: ${relativeCwd}
|
|
8774
|
+
` : "";
|
|
8775
|
+
const filesList = filesInfo.map((file) => {
|
|
8776
|
+
const typeIcon = file.isDirectory ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
8777
|
+
const sizeStr = file.isDirectory ? "" : ` (${formatBytes(file.size)})`;
|
|
8778
|
+
return `${typeIcon} ${file.path}${sizeStr}`;
|
|
8779
|
+
}).join("\n");
|
|
8780
|
+
return `${summary}${cwdInfo}
|
|
8869
8781
|
${filesList}`;
|
|
8870
8782
|
}
|
|
8783
|
+
function formatBytes(bytes) {
|
|
8784
|
+
if (bytes === 0)
|
|
8785
|
+
return "0 B";
|
|
8786
|
+
const k = 1024;
|
|
8787
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
8788
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
8789
|
+
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
|
|
8790
|
+
}
|
|
8871
8791
|
var globFilesTool = {
|
|
8872
8792
|
name: "glob_files",
|
|
8873
8793
|
implementation: (context) => ({
|
|
8874
8794
|
toolFn: async (value) => {
|
|
8875
8795
|
const params = value;
|
|
8876
|
-
context.logger.info("\u{1F50D} GlobFiles:
|
|
8796
|
+
context.logger.info("\u{1F50D} GlobFiles: Listing files", {
|
|
8877
8797
|
pattern: params.pattern,
|
|
8878
|
-
|
|
8798
|
+
cwd: params.cwd || "."
|
|
8879
8799
|
});
|
|
8880
8800
|
try {
|
|
8881
|
-
const result = await
|
|
8801
|
+
const result = await listFiles(params);
|
|
8882
8802
|
context.logger.info("\u2705 GlobFiles: Success");
|
|
8883
8803
|
return result;
|
|
8884
8804
|
} catch (error) {
|
|
@@ -8888,25 +8808,25 @@ var globFilesTool = {
|
|
|
8888
8808
|
},
|
|
8889
8809
|
toolSchema: {
|
|
8890
8810
|
name: "glob_files",
|
|
8891
|
-
description: "
|
|
8811
|
+
description: "List files and directories matching a glob pattern. Supports wildcards like *, **, ?, and character ranges. Restricted to current working directory for security.",
|
|
8892
8812
|
parameters: {
|
|
8893
8813
|
type: "object",
|
|
8894
8814
|
properties: {
|
|
8895
8815
|
pattern: {
|
|
8896
8816
|
type: "string",
|
|
8897
|
-
description: '
|
|
8817
|
+
description: 'Glob pattern to match files (e.g., "*.ts", "src/**/*.tsx", "test/*.{js,ts}"). Use ** for recursive directory search.'
|
|
8898
8818
|
},
|
|
8899
|
-
|
|
8819
|
+
cwd: {
|
|
8900
8820
|
type: "string",
|
|
8901
|
-
description: "
|
|
8821
|
+
description: "Directory to search in, relative to current working directory (optional). Defaults to current directory."
|
|
8902
8822
|
},
|
|
8903
|
-
|
|
8823
|
+
includeHidden: {
|
|
8904
8824
|
type: "boolean",
|
|
8905
|
-
description: "
|
|
8825
|
+
description: "Include hidden files and directories (starting with .). Defaults to false."
|
|
8906
8826
|
},
|
|
8907
|
-
|
|
8908
|
-
type: "
|
|
8909
|
-
description: "
|
|
8827
|
+
maxResults: {
|
|
8828
|
+
type: "number",
|
|
8829
|
+
description: "Maximum number of results to return (default: 1000). Prevents overwhelming output."
|
|
8910
8830
|
}
|
|
8911
8831
|
},
|
|
8912
8832
|
required: ["pattern"]
|
|
@@ -8916,144 +8836,158 @@ var globFilesTool = {
|
|
|
8916
8836
|
};
|
|
8917
8837
|
|
|
8918
8838
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/grepSearch/index.js
|
|
8919
|
-
import {
|
|
8920
|
-
import {
|
|
8839
|
+
import { readdir as readdir2 } from "fs/promises";
|
|
8840
|
+
import { readFileSync as readFileSync3, statSync as statSync6 } from "fs";
|
|
8921
8841
|
import path10 from "path";
|
|
8922
8842
|
var MAX_FILE_SIZE3 = 10 * 1024 * 1024;
|
|
8923
|
-
|
|
8924
|
-
"
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
"**/*.min.js",
|
|
8931
|
-
"**/*.min.css",
|
|
8932
|
-
"**/package-lock.json",
|
|
8933
|
-
"**/pnpm-lock.yaml",
|
|
8934
|
-
"**/yarn.lock"
|
|
8935
|
-
];
|
|
8936
|
-
async function isBinaryFile2(filePath) {
|
|
8843
|
+
function matchGlob2(filePath, pattern) {
|
|
8844
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*").replace(/\?/g, ".").replace(/\{([^}]+)\}/g, (_, options) => `(${options.split(",").join("|")})`).replace(/\[([^\]]+)\]/g, "[$1]");
|
|
8845
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
8846
|
+
return regex.test(filePath);
|
|
8847
|
+
}
|
|
8848
|
+
async function walkDir2(dir, pattern, maxResults, basePath = "") {
|
|
8849
|
+
const matches = [];
|
|
8937
8850
|
try {
|
|
8938
|
-
const
|
|
8939
|
-
const
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8851
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
8852
|
+
for (const entry of entries) {
|
|
8853
|
+
if (matches.length >= maxResults) {
|
|
8854
|
+
break;
|
|
8855
|
+
}
|
|
8856
|
+
if (entry.name.startsWith(".")) {
|
|
8857
|
+
continue;
|
|
8858
|
+
}
|
|
8859
|
+
const relativePath = basePath ? path10.join(basePath, entry.name) : entry.name;
|
|
8860
|
+
const fullPath = path10.join(dir, entry.name);
|
|
8861
|
+
if (matchGlob2(relativePath, pattern)) {
|
|
8862
|
+
matches.push(relativePath);
|
|
8863
|
+
}
|
|
8864
|
+
if (entry.isDirectory() && (pattern.includes("**") || pattern.includes("/"))) {
|
|
8865
|
+
const subMatches = await walkDir2(fullPath, pattern, maxResults - matches.length, relativePath);
|
|
8866
|
+
matches.push(...subMatches);
|
|
8867
|
+
}
|
|
8868
|
+
}
|
|
8869
|
+
} catch (error) {
|
|
8947
8870
|
}
|
|
8948
|
-
|
|
8949
|
-
function isPathWithinWorkspace(targetPath, baseCwd) {
|
|
8950
|
-
const resolvedTarget = path10.resolve(targetPath);
|
|
8951
|
-
const resolvedBase = path10.resolve(baseCwd);
|
|
8952
|
-
return resolvedTarget.startsWith(resolvedBase);
|
|
8871
|
+
return matches;
|
|
8953
8872
|
}
|
|
8954
8873
|
async function searchFiles2(params) {
|
|
8955
|
-
const { pattern,
|
|
8874
|
+
const { pattern, filePattern = "**/*", cwd: relativeCwd, caseSensitive = false, maxResults = 100, contextLines = 0 } = params;
|
|
8956
8875
|
const baseCwd = process.cwd();
|
|
8957
|
-
const
|
|
8958
|
-
if (!
|
|
8959
|
-
throw new Error(`
|
|
8960
|
-
}
|
|
8961
|
-
try {
|
|
8962
|
-
const stats = await stat2(targetDir);
|
|
8963
|
-
if (!stats.isDirectory()) {
|
|
8964
|
-
throw new Error(`Path is not a directory: ${dir_path}`);
|
|
8965
|
-
}
|
|
8966
|
-
} catch (error) {
|
|
8967
|
-
if (error.code === "ENOENT") {
|
|
8968
|
-
throw new Error(`Path does not exist: ${dir_path}`);
|
|
8969
|
-
}
|
|
8970
|
-
throw error;
|
|
8876
|
+
const targetCwd = relativeCwd ? path10.resolve(baseCwd, path10.normalize(relativeCwd)) : baseCwd;
|
|
8877
|
+
if (!targetCwd.startsWith(baseCwd)) {
|
|
8878
|
+
throw new Error(`Access denied: Cannot search files outside of current working directory`);
|
|
8971
8879
|
}
|
|
8972
8880
|
let searchRegex;
|
|
8973
8881
|
try {
|
|
8974
|
-
|
|
8882
|
+
const flags = caseSensitive ? "g" : "gi";
|
|
8883
|
+
searchRegex = new RegExp(pattern, flags);
|
|
8975
8884
|
} catch (error) {
|
|
8976
8885
|
throw new Error(`Invalid regex pattern: ${pattern}`);
|
|
8977
8886
|
}
|
|
8978
|
-
const
|
|
8979
|
-
const
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
// Skip hidden files
|
|
8983
|
-
ignore: DEFAULT_IGNORE_PATTERNS3,
|
|
8984
|
-
absolute: true,
|
|
8985
|
-
nodir: true
|
|
8986
|
-
// Only match files, not directories
|
|
8987
|
-
});
|
|
8988
|
-
const allMatches = [];
|
|
8989
|
-
let filesSearched = 0;
|
|
8990
|
-
const maxMatches = 500;
|
|
8991
|
-
for await (const filePath of filesStream) {
|
|
8992
|
-
if (allMatches.length >= maxMatches) {
|
|
8993
|
-
break;
|
|
8994
|
-
}
|
|
8995
|
-
const fileAbsPath = filePath;
|
|
8887
|
+
const filesToSearch = await walkDir2(targetCwd, filePattern, 1e4);
|
|
8888
|
+
const filteredFiles = [];
|
|
8889
|
+
for (const match of filesToSearch) {
|
|
8890
|
+
const fullPath = path10.join(targetCwd, match);
|
|
8996
8891
|
try {
|
|
8997
|
-
const stats =
|
|
8998
|
-
if (stats.size > MAX_FILE_SIZE3) {
|
|
8892
|
+
const stats = statSync6(fullPath);
|
|
8893
|
+
if (stats.isDirectory() || stats.size > MAX_FILE_SIZE3) {
|
|
8999
8894
|
continue;
|
|
9000
8895
|
}
|
|
9001
|
-
if (
|
|
8896
|
+
if (isBinaryFile2(fullPath)) {
|
|
9002
8897
|
continue;
|
|
9003
8898
|
}
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
8899
|
+
filteredFiles.push(match);
|
|
8900
|
+
} catch {
|
|
8901
|
+
continue;
|
|
8902
|
+
}
|
|
8903
|
+
}
|
|
8904
|
+
if (filteredFiles.length === 0) {
|
|
8905
|
+
return `No files found matching pattern: ${filePattern}`;
|
|
8906
|
+
}
|
|
8907
|
+
const matches = [];
|
|
8908
|
+
let filesSearched = 0;
|
|
8909
|
+
for (const file of filteredFiles) {
|
|
8910
|
+
if (matches.length >= maxResults) {
|
|
8911
|
+
break;
|
|
8912
|
+
}
|
|
8913
|
+
filesSearched++;
|
|
8914
|
+
const fullPath = path10.join(targetCwd, file);
|
|
8915
|
+
try {
|
|
8916
|
+
const content = readFileSync3(fullPath, "utf-8");
|
|
8917
|
+
const lines = content.split("\n");
|
|
8918
|
+
for (let i = 0; i < lines.length; i++) {
|
|
8919
|
+
if (matches.length >= maxResults) {
|
|
8920
|
+
break;
|
|
9014
8921
|
}
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
8922
|
+
const line = lines[i];
|
|
8923
|
+
if (searchRegex.test(line)) {
|
|
8924
|
+
const match = {
|
|
8925
|
+
file,
|
|
8926
|
+
line: i + 1,
|
|
8927
|
+
// 1-indexed line numbers
|
|
8928
|
+
content: line.trim()
|
|
8929
|
+
};
|
|
8930
|
+
if (contextLines > 0) {
|
|
8931
|
+
const before = [];
|
|
8932
|
+
const after = [];
|
|
8933
|
+
for (let j = Math.max(0, i - contextLines); j < i; j++) {
|
|
8934
|
+
before.push(lines[j]);
|
|
8935
|
+
}
|
|
8936
|
+
for (let j = i + 1; j <= Math.min(lines.length - 1, i + contextLines); j++) {
|
|
8937
|
+
after.push(lines[j]);
|
|
8938
|
+
}
|
|
8939
|
+
match.context = { before, after };
|
|
8940
|
+
}
|
|
8941
|
+
matches.push(match);
|
|
8942
|
+
}
|
|
8943
|
+
searchRegex.lastIndex = 0;
|
|
9020
8944
|
}
|
|
8945
|
+
} catch {
|
|
8946
|
+
continue;
|
|
9021
8947
|
}
|
|
9022
8948
|
}
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
return `No matches found for pattern "${pattern}" in "${searchDirDisplay}"${filterInfo}.
|
|
9027
|
-
Searched ${filesSearched} file(s).`;
|
|
8949
|
+
if (matches.length === 0) {
|
|
8950
|
+
return `No matches found for pattern: ${pattern}
|
|
8951
|
+
Searched ${filesSearched} file(s)`;
|
|
9028
8952
|
}
|
|
9029
|
-
const
|
|
9030
|
-
|
|
9031
|
-
acc[match.filePath] = [];
|
|
9032
|
-
}
|
|
9033
|
-
acc[match.filePath].push(match);
|
|
9034
|
-
acc[match.filePath].sort((a, b) => a.lineNumber - b.lineNumber);
|
|
9035
|
-
return acc;
|
|
9036
|
-
}, {});
|
|
9037
|
-
const matchCount = allMatches.length;
|
|
9038
|
-
const matchTerm = matchCount === 1 ? "match" : "matches";
|
|
9039
|
-
const truncated = matchCount >= maxMatches;
|
|
9040
|
-
let result = `Found ${matchCount} ${matchTerm}${truncated ? " (truncated)" : ""} for pattern "${pattern}" in "${searchDirDisplay}"${filterInfo}:
|
|
8953
|
+
const truncated = matches.length >= maxResults;
|
|
8954
|
+
const summary = `Found ${matches.length} match(es)${truncated ? ` (truncated to ${maxResults})` : ""} in ${filesSearched} file(s)
|
|
9041
8955
|
`;
|
|
9042
|
-
|
|
9043
|
-
---
|
|
8956
|
+
const patternInfo = `Pattern: ${pattern}${caseSensitive ? "" : " (case-insensitive)"}
|
|
9044
8957
|
`;
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
8958
|
+
const cwdInfo = relativeCwd ? `Directory: ${relativeCwd}
|
|
8959
|
+
` : "";
|
|
8960
|
+
const matchesList = matches.map((match) => {
|
|
8961
|
+
let result = `
|
|
8962
|
+
\u{1F4C4} ${match.file}:${match.line}
|
|
8963
|
+
${match.content}`;
|
|
8964
|
+
if (match.context) {
|
|
8965
|
+
if (match.context.before.length > 0) {
|
|
8966
|
+
result = `${result}
|
|
8967
|
+
Context before:
|
|
8968
|
+
${match.context.before.map((l) => ` ${l}`).join("\n")}`;
|
|
8969
|
+
}
|
|
8970
|
+
if (match.context.after.length > 0) {
|
|
8971
|
+
result = `${result}
|
|
8972
|
+
Context after:
|
|
8973
|
+
${match.context.after.map((l) => ` ${l}`).join("\n")}`;
|
|
8974
|
+
}
|
|
8975
|
+
}
|
|
8976
|
+
return result;
|
|
8977
|
+
}).join("\n");
|
|
8978
|
+
return `${summary}${patternInfo}${cwdInfo}${matchesList}`;
|
|
8979
|
+
}
|
|
8980
|
+
function isBinaryFile2(filePath) {
|
|
8981
|
+
try {
|
|
8982
|
+
const buffer = Buffer.alloc(8192);
|
|
8983
|
+
const fd = __require("fs").openSync(filePath, "r");
|
|
8984
|
+
const bytesRead = __require("fs").readSync(fd, buffer, 0, 8192, 0);
|
|
8985
|
+
__require("fs").closeSync(fd);
|
|
8986
|
+
const chunk = buffer.slice(0, bytesRead);
|
|
8987
|
+
return chunk.includes(0);
|
|
8988
|
+
} catch {
|
|
8989
|
+
return true;
|
|
9055
8990
|
}
|
|
9056
|
-
return result.trim();
|
|
9057
8991
|
}
|
|
9058
8992
|
var grepSearchTool = {
|
|
9059
8993
|
name: "grep_search",
|
|
@@ -9062,8 +8996,8 @@ var grepSearchTool = {
|
|
|
9062
8996
|
const params = value;
|
|
9063
8997
|
context.logger.info("\u{1F50D} GrepSearch: Searching files", {
|
|
9064
8998
|
pattern: params.pattern,
|
|
9065
|
-
|
|
9066
|
-
|
|
8999
|
+
filePattern: params.filePattern || "**/*",
|
|
9000
|
+
cwd: params.cwd || "."
|
|
9067
9001
|
});
|
|
9068
9002
|
try {
|
|
9069
9003
|
const result = await searchFiles2(params);
|
|
@@ -9076,21 +9010,33 @@ var grepSearchTool = {
|
|
|
9076
9010
|
},
|
|
9077
9011
|
toolSchema: {
|
|
9078
9012
|
name: "grep_search",
|
|
9079
|
-
description: "
|
|
9013
|
+
description: "Search for a regex pattern in file contents. Similar to grep command. Searches text files only, excluding binary files. Restricted to current working directory for security.",
|
|
9080
9014
|
parameters: {
|
|
9081
9015
|
type: "object",
|
|
9082
9016
|
properties: {
|
|
9083
9017
|
pattern: {
|
|
9084
9018
|
type: "string",
|
|
9085
|
-
description: "
|
|
9019
|
+
description: "Regular expression pattern to search for in file contents"
|
|
9086
9020
|
},
|
|
9087
|
-
|
|
9021
|
+
filePattern: {
|
|
9088
9022
|
type: "string",
|
|
9089
|
-
description:
|
|
9023
|
+
description: 'Glob pattern to filter which files to search (optional, default: "**/*"). Example: "src/**/*.ts" to search only TypeScript files in src directory.'
|
|
9090
9024
|
},
|
|
9091
|
-
|
|
9025
|
+
cwd: {
|
|
9092
9026
|
type: "string",
|
|
9093
|
-
description: "
|
|
9027
|
+
description: "Directory to search in, relative to current working directory (optional). Defaults to current directory."
|
|
9028
|
+
},
|
|
9029
|
+
caseSensitive: {
|
|
9030
|
+
type: "boolean",
|
|
9031
|
+
description: "Whether the search should be case-sensitive (default: false)"
|
|
9032
|
+
},
|
|
9033
|
+
maxResults: {
|
|
9034
|
+
type: "number",
|
|
9035
|
+
description: "Maximum number of matches to return (default: 100). Prevents overwhelming output."
|
|
9036
|
+
},
|
|
9037
|
+
contextLines: {
|
|
9038
|
+
type: "number",
|
|
9039
|
+
description: "Number of context lines to show before and after each match (default: 0). Similar to grep -C option."
|
|
9094
9040
|
}
|
|
9095
9041
|
},
|
|
9096
9042
|
required: ["pattern"]
|
|
@@ -9101,7 +9047,7 @@ var grepSearchTool = {
|
|
|
9101
9047
|
|
|
9102
9048
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/deleteFile/index.js
|
|
9103
9049
|
import { promises as fs10 } from "fs";
|
|
9104
|
-
import { existsSync as existsSync6, statSync as
|
|
9050
|
+
import { existsSync as existsSync6, statSync as statSync7 } from "fs";
|
|
9105
9051
|
import path11 from "path";
|
|
9106
9052
|
async function deleteFile(params) {
|
|
9107
9053
|
const { path: filePath, recursive = false } = params;
|
|
@@ -9114,7 +9060,7 @@ async function deleteFile(params) {
|
|
|
9114
9060
|
if (!existsSync6(resolvedPath)) {
|
|
9115
9061
|
throw new Error(`File or directory not found: ${filePath}`);
|
|
9116
9062
|
}
|
|
9117
|
-
const stats =
|
|
9063
|
+
const stats = statSync7(resolvedPath);
|
|
9118
9064
|
const isDirectory = stats.isDirectory();
|
|
9119
9065
|
const size = stats.size;
|
|
9120
9066
|
if (isDirectory && !recursive) {
|
|
@@ -9135,7 +9081,7 @@ var deleteFileTool = {
|
|
|
9135
9081
|
toolFn: async (value) => {
|
|
9136
9082
|
const params = value;
|
|
9137
9083
|
const resolvedPath = path11.resolve(process.cwd(), path11.normalize(params.path));
|
|
9138
|
-
const isDirectory = existsSync6(resolvedPath) &&
|
|
9084
|
+
const isDirectory = existsSync6(resolvedPath) && statSync7(resolvedPath).isDirectory();
|
|
9139
9085
|
context.logger.info(`\u{1F5D1}\uFE0F DeleteFile: Deleting ${isDirectory ? "directory" : "file"}`, {
|
|
9140
9086
|
path: params.path,
|
|
9141
9087
|
recursive: params.recursive
|
|
@@ -9911,7 +9857,7 @@ var ToolErrorType;
|
|
|
9911
9857
|
|
|
9912
9858
|
// src/utils/diffPreview.ts
|
|
9913
9859
|
import * as Diff from "diff";
|
|
9914
|
-
import { readFile
|
|
9860
|
+
import { readFile } from "fs/promises";
|
|
9915
9861
|
import { existsSync as existsSync8 } from "fs";
|
|
9916
9862
|
async function generateFileDiffPreview(args) {
|
|
9917
9863
|
try {
|
|
@@ -9926,7 +9872,7 @@ ${preview}${hasMore ? `
|
|
|
9926
9872
|
|
|
9927
9873
|
... (${lines2.length - 20} more lines)` : ""}`;
|
|
9928
9874
|
}
|
|
9929
|
-
const currentContent = await
|
|
9875
|
+
const currentContent = await readFile(args.path, "utf-8");
|
|
9930
9876
|
const patch = Diff.createPatch(
|
|
9931
9877
|
args.path,
|
|
9932
9878
|
currentContent,
|
|
@@ -11302,10 +11248,6 @@ var ServerLlmBackend = class {
|
|
|
11302
11248
|
*/
|
|
11303
11249
|
async complete(model, messages, options, callback) {
|
|
11304
11250
|
logger.debug(`[ServerLlmBackend] Starting complete() with model: ${model}`);
|
|
11305
|
-
if (options.abortSignal?.aborted) {
|
|
11306
|
-
logger.debug("[ServerLlmBackend] Request aborted before start");
|
|
11307
|
-
return;
|
|
11308
|
-
}
|
|
11309
11251
|
return new Promise(async (resolve3, reject) => {
|
|
11310
11252
|
try {
|
|
11311
11253
|
logger.debug("[ServerLlmBackend] Making streaming request...");
|
|
@@ -11406,25 +11348,7 @@ var ServerLlmBackend = class {
|
|
|
11406
11348
|
}
|
|
11407
11349
|
}
|
|
11408
11350
|
});
|
|
11409
|
-
if (options.abortSignal) {
|
|
11410
|
-
const abortHandler = () => {
|
|
11411
|
-
logger.debug("[ServerLlmBackend] Abort signal received, destroying stream");
|
|
11412
|
-
response.data.destroy();
|
|
11413
|
-
resolve3();
|
|
11414
|
-
};
|
|
11415
|
-
if (options.abortSignal.aborted) {
|
|
11416
|
-
abortHandler();
|
|
11417
|
-
return;
|
|
11418
|
-
}
|
|
11419
|
-
options.abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
11420
|
-
response.data.on("close", () => {
|
|
11421
|
-
options.abortSignal?.removeEventListener("abort", abortHandler);
|
|
11422
|
-
});
|
|
11423
|
-
}
|
|
11424
11351
|
response.data.on("data", (chunk) => {
|
|
11425
|
-
if (options.abortSignal?.aborted) {
|
|
11426
|
-
return;
|
|
11427
|
-
}
|
|
11428
11352
|
parser.feed(chunk.toString());
|
|
11429
11353
|
});
|
|
11430
11354
|
response.data.on("end", () => {
|
|
@@ -11436,23 +11360,9 @@ var ServerLlmBackend = class {
|
|
|
11436
11360
|
}
|
|
11437
11361
|
});
|
|
11438
11362
|
response.data.on("error", (error) => {
|
|
11439
|
-
if (options.abortSignal?.aborted) {
|
|
11440
|
-
resolve3();
|
|
11441
|
-
return;
|
|
11442
|
-
}
|
|
11443
11363
|
reject(error);
|
|
11444
11364
|
});
|
|
11445
11365
|
} catch (error) {
|
|
11446
|
-
if (options.abortSignal?.aborted) {
|
|
11447
|
-
logger.debug("[ServerLlmBackend] Request was aborted, resolving gracefully");
|
|
11448
|
-
resolve3();
|
|
11449
|
-
return;
|
|
11450
|
-
}
|
|
11451
|
-
if (isAxiosError(error) && error.code === "ERR_CANCELED") {
|
|
11452
|
-
logger.debug("[ServerLlmBackend] Request was canceled, resolving gracefully");
|
|
11453
|
-
resolve3();
|
|
11454
|
-
return;
|
|
11455
|
-
}
|
|
11456
11366
|
logger.error("LLM completion failed", error);
|
|
11457
11367
|
if (isAxiosError(error)) {
|
|
11458
11368
|
logger.debug(
|
|
@@ -11603,10 +11513,8 @@ var ServerLlmBackend = class {
|
|
|
11603
11513
|
logger.debug(` Body: ${logger.formatBytes(bodySize)}`);
|
|
11604
11514
|
logger.debug(` Preview: ${bodyStr.substring(0, 200)}`);
|
|
11605
11515
|
const response = await axiosInstance.post(this.completionsEndpoint, requestBody, {
|
|
11606
|
-
responseType: "stream"
|
|
11516
|
+
responseType: "stream"
|
|
11607
11517
|
// Auth header is automatically injected by ApiClient interceptor
|
|
11608
|
-
// Pass abort signal to cancel request if user presses ESC
|
|
11609
|
-
signal: options.abortSignal
|
|
11610
11518
|
});
|
|
11611
11519
|
logger.debug(`\u2190 ${response.status} ${response.statusText}`);
|
|
11612
11520
|
return response;
|
|
@@ -11750,7 +11658,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
11750
11658
|
// package.json
|
|
11751
11659
|
var package_default = {
|
|
11752
11660
|
name: "@bike4mind/cli",
|
|
11753
|
-
version: "0.2.12-
|
|
11661
|
+
version: "0.2.12-feat-secops-secrets.17399+ae2b8a0b6",
|
|
11754
11662
|
type: "module",
|
|
11755
11663
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
11756
11664
|
license: "UNLICENSED",
|
|
@@ -11787,8 +11695,7 @@ var package_default = {
|
|
|
11787
11695
|
test: "vitest run",
|
|
11788
11696
|
"test:watch": "vitest",
|
|
11789
11697
|
start: "node dist/index.js",
|
|
11790
|
-
prepublishOnly: "pnpm build"
|
|
11791
|
-
postinstall: `node -e "try { require('better-sqlite3') } catch(e) { if(e.message.includes('bindings')) { console.log('\\n\u26A0\uFE0F Rebuilding better-sqlite3 native bindings...'); require('child_process').execSync('pnpm rebuild better-sqlite3', {stdio:'inherit'}) } }"`
|
|
11698
|
+
prepublishOnly: "pnpm build"
|
|
11792
11699
|
},
|
|
11793
11700
|
dependencies: {
|
|
11794
11701
|
"@anthropic-ai/sdk": "^0.22.0",
|
|
@@ -11821,7 +11728,6 @@ var package_default = {
|
|
|
11821
11728
|
"eventsource-parser": "^3.0.6",
|
|
11822
11729
|
"file-type": "^18.7.0",
|
|
11823
11730
|
"fuse.js": "^7.1.0",
|
|
11824
|
-
glob: "^13.0.0",
|
|
11825
11731
|
"gray-matter": "^4.0.3",
|
|
11826
11732
|
ink: "^6.5.1",
|
|
11827
11733
|
"ink-select-input": "^6.2.0",
|
|
@@ -11856,10 +11762,10 @@ var package_default = {
|
|
|
11856
11762
|
},
|
|
11857
11763
|
devDependencies: {
|
|
11858
11764
|
"@bike4mind/agents": "0.1.0",
|
|
11859
|
-
"@bike4mind/common": "2.41.1-
|
|
11860
|
-
"@bike4mind/mcp": "1.21.1-
|
|
11861
|
-
"@bike4mind/services": "2.36.1-
|
|
11862
|
-
"@bike4mind/utils": "2.1.6-
|
|
11765
|
+
"@bike4mind/common": "2.41.1-feat-secops-secrets.17399+ae2b8a0b6",
|
|
11766
|
+
"@bike4mind/mcp": "1.21.1-feat-secops-secrets.17399+ae2b8a0b6",
|
|
11767
|
+
"@bike4mind/services": "2.36.1-feat-secops-secrets.17399+ae2b8a0b6",
|
|
11768
|
+
"@bike4mind/utils": "2.1.6-feat-secops-secrets.17399+ae2b8a0b6",
|
|
11863
11769
|
"@types/better-sqlite3": "^7.6.13",
|
|
11864
11770
|
"@types/diff": "^5.0.9",
|
|
11865
11771
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -11872,7 +11778,7 @@ var package_default = {
|
|
|
11872
11778
|
typescript: "^5.9.3",
|
|
11873
11779
|
vitest: "^3.2.4"
|
|
11874
11780
|
},
|
|
11875
|
-
gitHead: "
|
|
11781
|
+
gitHead: "ae2b8a0b668497b8b3d94c6e055ce1565fde45b3"
|
|
11876
11782
|
};
|
|
11877
11783
|
|
|
11878
11784
|
// src/config/constants.ts
|
|
@@ -12228,131 +12134,6 @@ function createSubagentDelegateTool(orchestrator, parentSessionId) {
|
|
|
12228
12134
|
};
|
|
12229
12135
|
}
|
|
12230
12136
|
|
|
12231
|
-
// src/tools/writeTodosTool.ts
|
|
12232
|
-
var VALID_STATUSES = ["pending", "in_progress", "completed", "cancelled"];
|
|
12233
|
-
function validateTodos(todos) {
|
|
12234
|
-
if (!Array.isArray(todos)) {
|
|
12235
|
-
throw new Error("write_todos: todos must be an array");
|
|
12236
|
-
}
|
|
12237
|
-
if (todos.length === 0) {
|
|
12238
|
-
throw new Error("write_todos: todos array cannot be empty");
|
|
12239
|
-
}
|
|
12240
|
-
let inProgressCount = 0;
|
|
12241
|
-
const validatedTodos = todos.map((item, index) => {
|
|
12242
|
-
if (!item || typeof item !== "object") {
|
|
12243
|
-
throw new Error(`write_todos: item at index ${index} must be an object`);
|
|
12244
|
-
}
|
|
12245
|
-
const { description, status } = item;
|
|
12246
|
-
if (typeof description !== "string" || description.trim() === "") {
|
|
12247
|
-
throw new Error(`write_todos: item at index ${index} must have a non-empty description`);
|
|
12248
|
-
}
|
|
12249
|
-
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
12250
|
-
throw new Error(
|
|
12251
|
-
`write_todos: item at index ${index} has invalid status "${status}". Must be one of: ${VALID_STATUSES.join(", ")}`
|
|
12252
|
-
);
|
|
12253
|
-
}
|
|
12254
|
-
if (status === "in_progress") {
|
|
12255
|
-
inProgressCount++;
|
|
12256
|
-
}
|
|
12257
|
-
return {
|
|
12258
|
-
description: description.trim(),
|
|
12259
|
-
status
|
|
12260
|
-
};
|
|
12261
|
-
});
|
|
12262
|
-
if (inProgressCount > 1) {
|
|
12263
|
-
throw new Error(`write_todos: only one task can be 'in_progress' at a time, but found ${inProgressCount}`);
|
|
12264
|
-
}
|
|
12265
|
-
return validatedTodos;
|
|
12266
|
-
}
|
|
12267
|
-
function formatTodosOutput(todos) {
|
|
12268
|
-
const statusEmoji = {
|
|
12269
|
-
pending: "\u2B1C",
|
|
12270
|
-
in_progress: "\u{1F504}",
|
|
12271
|
-
completed: "\u2705",
|
|
12272
|
-
cancelled: "\u274C"
|
|
12273
|
-
};
|
|
12274
|
-
const lines = todos.map((todo, index) => {
|
|
12275
|
-
const emoji = statusEmoji[todo.status];
|
|
12276
|
-
return `${index + 1}. ${emoji} [${todo.status}] ${todo.description}`;
|
|
12277
|
-
});
|
|
12278
|
-
return lines.join("\n");
|
|
12279
|
-
}
|
|
12280
|
-
function createWriteTodosTool(todoStore) {
|
|
12281
|
-
return {
|
|
12282
|
-
toolFn: async (args) => {
|
|
12283
|
-
const params = args;
|
|
12284
|
-
const validatedTodos = validateTodos(params.todos);
|
|
12285
|
-
todoStore.todos = validatedTodos;
|
|
12286
|
-
if (todoStore.onUpdate) {
|
|
12287
|
-
todoStore.onUpdate(validatedTodos);
|
|
12288
|
-
}
|
|
12289
|
-
const output = formatTodosOutput(validatedTodos);
|
|
12290
|
-
return `Todo list updated successfully:
|
|
12291
|
-
|
|
12292
|
-
${output}`;
|
|
12293
|
-
},
|
|
12294
|
-
toolSchema: {
|
|
12295
|
-
name: "write_todos",
|
|
12296
|
-
description: `Create or update a list of subtasks for complex multi-step requests.
|
|
12297
|
-
|
|
12298
|
-
**When to use this tool:**
|
|
12299
|
-
- When handling complex requests that require multiple steps
|
|
12300
|
-
- To break down a large task into smaller, manageable subtasks
|
|
12301
|
-
- To track progress through a multi-step workflow
|
|
12302
|
-
|
|
12303
|
-
**Important guidelines:**
|
|
12304
|
-
- Call this tool early when receiving complex requests
|
|
12305
|
-
- Update the list immediately when starting, completing, or cancelling tasks
|
|
12306
|
-
- Only ONE task should be 'in_progress' at a time
|
|
12307
|
-
- Never batch updates - update as soon as state changes
|
|
12308
|
-
|
|
12309
|
-
**Status values:**
|
|
12310
|
-
- pending: Task not yet started
|
|
12311
|
-
- in_progress: Currently working on this task (only ONE allowed)
|
|
12312
|
-
- completed: Task finished successfully
|
|
12313
|
-
- cancelled: Task will not be completed
|
|
12314
|
-
|
|
12315
|
-
**Example:**
|
|
12316
|
-
If asked to "create a new React component with tests", break it down:
|
|
12317
|
-
1. Create component file \u2192 in_progress
|
|
12318
|
-
2. Add component logic \u2192 pending
|
|
12319
|
-
3. Create test file \u2192 pending
|
|
12320
|
-
4. Write unit tests \u2192 pending`,
|
|
12321
|
-
parameters: {
|
|
12322
|
-
type: "object",
|
|
12323
|
-
properties: {
|
|
12324
|
-
todos: {
|
|
12325
|
-
type: "array",
|
|
12326
|
-
description: "Complete list of todo items. This replaces any existing list. Each item needs a description and status.",
|
|
12327
|
-
items: {
|
|
12328
|
-
type: "object",
|
|
12329
|
-
properties: {
|
|
12330
|
-
description: {
|
|
12331
|
-
type: "string",
|
|
12332
|
-
description: "Clear, concise description of the task"
|
|
12333
|
-
},
|
|
12334
|
-
status: {
|
|
12335
|
-
type: "string",
|
|
12336
|
-
enum: ["pending", "in_progress", "completed", "cancelled"],
|
|
12337
|
-
description: "Current status of the task. Only ONE task can be 'in_progress' at a time."
|
|
12338
|
-
}
|
|
12339
|
-
},
|
|
12340
|
-
required: ["description", "status"]
|
|
12341
|
-
}
|
|
12342
|
-
}
|
|
12343
|
-
},
|
|
12344
|
-
required: ["todos"]
|
|
12345
|
-
}
|
|
12346
|
-
}
|
|
12347
|
-
};
|
|
12348
|
-
}
|
|
12349
|
-
function createTodoStore(onUpdate) {
|
|
12350
|
-
return {
|
|
12351
|
-
todos: [],
|
|
12352
|
-
onUpdate
|
|
12353
|
-
};
|
|
12354
|
-
}
|
|
12355
|
-
|
|
12356
12137
|
// src/index.tsx
|
|
12357
12138
|
process.removeAllListeners("warning");
|
|
12358
12139
|
process.on("warning", (warning) => {
|
|
@@ -12384,8 +12165,7 @@ function CliApp() {
|
|
|
12384
12165
|
trustLocationSelector: null,
|
|
12385
12166
|
rewindSelector: null,
|
|
12386
12167
|
sessionSelector: null,
|
|
12387
|
-
orchestrator: null
|
|
12388
|
-
abortController: null
|
|
12168
|
+
orchestrator: null
|
|
12389
12169
|
});
|
|
12390
12170
|
const [isInitialized, setIsInitialized] = useState8(false);
|
|
12391
12171
|
const [initError, setInitError] = useState8(null);
|
|
@@ -12431,15 +12211,6 @@ function CliApp() {
|
|
|
12431
12211
|
}, 100);
|
|
12432
12212
|
}, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore]);
|
|
12433
12213
|
useInput6((input, key) => {
|
|
12434
|
-
if (key.escape) {
|
|
12435
|
-
if (state.abortController) {
|
|
12436
|
-
logger.debug("[ABORT] ESC pressed - aborting current operation...");
|
|
12437
|
-
state.abortController.abort();
|
|
12438
|
-
setState((prev) => ({ ...prev, abortController: null }));
|
|
12439
|
-
useCliStore.getState().setIsThinking(false);
|
|
12440
|
-
}
|
|
12441
|
-
return;
|
|
12442
|
-
}
|
|
12443
12214
|
if (key.ctrl && input === "c") {
|
|
12444
12215
|
const now = Date.now();
|
|
12445
12216
|
if (exitTimestamp && now - exitTimestamp < EXIT_TIMEOUT_MS) {
|
|
@@ -12637,9 +12408,7 @@ function CliApp() {
|
|
|
12637
12408
|
subagentConfigs
|
|
12638
12409
|
});
|
|
12639
12410
|
const subagentDelegateTool = createSubagentDelegateTool(orchestrator, newSession.id);
|
|
12640
|
-
const
|
|
12641
|
-
const writeTodosTool = createWriteTodosTool(todoStore);
|
|
12642
|
-
const allTools = [...b4mTools, ...mcpTools, subagentDelegateTool, writeTodosTool];
|
|
12411
|
+
const allTools = [...b4mTools, ...mcpTools, subagentDelegateTool];
|
|
12643
12412
|
console.log(`\u{1F916} Subagent delegation enabled (explore, plan, review)`);
|
|
12644
12413
|
const projectDir = state.configStore.getProjectConfigDir();
|
|
12645
12414
|
const contextResult = await loadContextFiles(projectDir);
|
|
@@ -12659,7 +12428,46 @@ function CliApp() {
|
|
|
12659
12428
|
Follow these project-specific instructions:
|
|
12660
12429
|
|
|
12661
12430
|
${contextResult.mergedContent}` : "";
|
|
12662
|
-
const cliSystemPrompt =
|
|
12431
|
+
const cliSystemPrompt = `You are an autonomous AI assistant with access to tools. Your job is to help users by taking action and solving problems proactively.
|
|
12432
|
+
|
|
12433
|
+
CORE BEHAVIOR:
|
|
12434
|
+
- Be proactive: Take action instead of asking for permission or clarification
|
|
12435
|
+
- Make smart assumptions: If unclear, choose the most reasonable interpretation
|
|
12436
|
+
- Use conversation history: Reference previous exchanges to understand context
|
|
12437
|
+
- Complete tasks fully: Don't just show what to do - actually do it
|
|
12438
|
+
|
|
12439
|
+
FOR CODING TASKS:
|
|
12440
|
+
- You have file system access (file_read, create_file, glob_files, grep_search, delete_file)
|
|
12441
|
+
- When user says "enhance", "update", "fix", "improve" a file:
|
|
12442
|
+
* Use file_read to get current content
|
|
12443
|
+
* Generate the improved version
|
|
12444
|
+
* Use create_file to write it back
|
|
12445
|
+
* Don't just show suggestions - make the changes
|
|
12446
|
+
- When searching for code: Use grep_search or glob_files to find relevant files
|
|
12447
|
+
- Permission system will ask for approval before any file writes
|
|
12448
|
+
|
|
12449
|
+
SUBAGENT DELEGATION:
|
|
12450
|
+
- You have access to specialized subagents via the subagent_delegate tool
|
|
12451
|
+
- Use subagents for focused exploration, planning, or review tasks:
|
|
12452
|
+
* explore: Fast read-only codebase search (e.g., "find all auth files", "locate API endpoints")
|
|
12453
|
+
* plan: Break down complex tasks into actionable steps
|
|
12454
|
+
* review: Analyze code quality and identify issues
|
|
12455
|
+
- Subagents keep the main conversation clean and run faster with optimized models
|
|
12456
|
+
- Delegate when you need to search extensively or analyze code structure
|
|
12457
|
+
|
|
12458
|
+
FOR GENERAL TASKS:
|
|
12459
|
+
- Use available tools to get information (weather, web search, calculations, etc.)
|
|
12460
|
+
- When user asks follow-up questions, use conversation context to understand what they're referring to
|
|
12461
|
+
- If user asks "how about X?" after a previous question, apply the same question type to X
|
|
12462
|
+
|
|
12463
|
+
EXAMPLES:
|
|
12464
|
+
- "what should I wear in Texas?" \u2192 use weather tool for Texas
|
|
12465
|
+
- "how about Japan?" \u2192 use weather tool for Japan (applying same question from context)
|
|
12466
|
+
- "enhance README" \u2192 file_read \u2192 generate \u2192 create_file
|
|
12467
|
+
- "what packages installed?" \u2192 glob_files "**/package.json" \u2192 file_read
|
|
12468
|
+
- "find all components using React hooks" \u2192 subagent_delegate(task="find all components using React hooks", type="explore")
|
|
12469
|
+
|
|
12470
|
+
Remember: Use context from previous messages to understand follow-up questions.${contextSection}`;
|
|
12663
12471
|
const maxIterations = config.preferences.maxIterations === null ? 999999 : config.preferences.maxIterations;
|
|
12664
12472
|
const agent = new ReActAgent({
|
|
12665
12473
|
userId: config.userId,
|
|
@@ -12704,16 +12512,13 @@ ${contextResult.mergedContent}` : "";
|
|
|
12704
12512
|
}
|
|
12705
12513
|
};
|
|
12706
12514
|
agent.on("thought", stepHandler);
|
|
12707
|
-
agent.on("observation", stepHandler);
|
|
12708
12515
|
agent.on("action", stepHandler);
|
|
12709
12516
|
orchestrator.setBeforeRunCallback((subagent, _subagentType) => {
|
|
12710
12517
|
subagent.on("thought", stepHandler);
|
|
12711
|
-
subagent.on("observation", stepHandler);
|
|
12712
12518
|
subagent.on("action", stepHandler);
|
|
12713
12519
|
});
|
|
12714
12520
|
orchestrator.setAfterRunCallback((subagent, _subagentType) => {
|
|
12715
12521
|
subagent.off("thought", stepHandler);
|
|
12716
|
-
subagent.off("observation", stepHandler);
|
|
12717
12522
|
subagent.off("action", stepHandler);
|
|
12718
12523
|
});
|
|
12719
12524
|
setState((prev) => ({
|
|
@@ -12760,8 +12565,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
12760
12565
|
return;
|
|
12761
12566
|
}
|
|
12762
12567
|
useCliStore.getState().setIsThinking(true);
|
|
12763
|
-
const abortController = new AbortController();
|
|
12764
|
-
setState((prev) => ({ ...prev, abortController }));
|
|
12765
12568
|
const currentSteps = [];
|
|
12766
12569
|
const stepHandler = (step) => {
|
|
12767
12570
|
currentSteps.push(step);
|
|
@@ -12821,8 +12624,7 @@ ${contextResult.mergedContent}` : "";
|
|
|
12821
12624
|
content: msg.content
|
|
12822
12625
|
}));
|
|
12823
12626
|
const result = await state.agent.run(messageContent, {
|
|
12824
|
-
previousMessages: previousMessages.length > 0 ? previousMessages : void 0
|
|
12825
|
-
signal: abortController.signal
|
|
12627
|
+
previousMessages: previousMessages.length > 0 ? previousMessages : void 0
|
|
12826
12628
|
});
|
|
12827
12629
|
const permissionDenied = result.finalAnswer.startsWith("Permission denied for tool");
|
|
12828
12630
|
if (permissionDenied) {
|
|
@@ -12867,33 +12669,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
12867
12669
|
useCliStore.getState().setIsThinking(false);
|
|
12868
12670
|
} catch (error) {
|
|
12869
12671
|
useCliStore.getState().setIsThinking(false);
|
|
12870
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
12871
|
-
logger.debug("[ABORT] Custom command aborted by user");
|
|
12872
|
-
const currentSession2 = useCliStore.getState().session;
|
|
12873
|
-
if (currentSession2) {
|
|
12874
|
-
const messages2 = [...currentSession2.messages];
|
|
12875
|
-
const lastMessage2 = messages2[messages2.length - 1];
|
|
12876
|
-
if (lastMessage2 && lastMessage2.role === "assistant") {
|
|
12877
|
-
messages2[messages2.length - 1] = {
|
|
12878
|
-
...lastMessage2,
|
|
12879
|
-
content: "\u26A0\uFE0F Operation cancelled by user",
|
|
12880
|
-
metadata: {
|
|
12881
|
-
...lastMessage2.metadata,
|
|
12882
|
-
cancelled: true
|
|
12883
|
-
}
|
|
12884
|
-
};
|
|
12885
|
-
}
|
|
12886
|
-
const sessionWithCancel = {
|
|
12887
|
-
...currentSession2,
|
|
12888
|
-
messages: messages2,
|
|
12889
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12890
|
-
};
|
|
12891
|
-
setState((prev) => ({ ...prev, session: sessionWithCancel }));
|
|
12892
|
-
setStoreSession(sessionWithCancel);
|
|
12893
|
-
await state.sessionStore.save(sessionWithCancel);
|
|
12894
|
-
}
|
|
12895
|
-
return;
|
|
12896
|
-
}
|
|
12897
12672
|
if (error?.message?.includes("Permission denied")) {
|
|
12898
12673
|
console.log("\n\u26A0\uFE0F Action blocked by permission settings");
|
|
12899
12674
|
const currentSession2 = useCliStore.getState().session;
|
|
@@ -12934,7 +12709,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
12934
12709
|
setState((prev) => ({ ...prev, session: sessionWithError }));
|
|
12935
12710
|
setStoreSession(sessionWithError);
|
|
12936
12711
|
} finally {
|
|
12937
|
-
setState((prev) => ({ ...prev, abortController: null }));
|
|
12938
12712
|
state.agent.off("thought", stepHandler);
|
|
12939
12713
|
state.agent.off("action", stepHandler);
|
|
12940
12714
|
}
|
|
@@ -12954,8 +12728,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
12954
12728
|
return;
|
|
12955
12729
|
}
|
|
12956
12730
|
useCliStore.getState().setIsThinking(true);
|
|
12957
|
-
const abortController = new AbortController();
|
|
12958
|
-
setState((prev) => ({ ...prev, abortController }));
|
|
12959
12731
|
try {
|
|
12960
12732
|
let messageContent = message;
|
|
12961
12733
|
let userMessageContent = message;
|
|
@@ -12993,8 +12765,7 @@ ${contextResult.mergedContent}` : "";
|
|
|
12993
12765
|
content: msg.content
|
|
12994
12766
|
}));
|
|
12995
12767
|
const result = await state.agent.run(messageContent, {
|
|
12996
|
-
previousMessages: previousMessages.length > 0 ? previousMessages : void 0
|
|
12997
|
-
signal: abortController.signal
|
|
12768
|
+
previousMessages: previousMessages.length > 0 ? previousMessages : void 0
|
|
12998
12769
|
});
|
|
12999
12770
|
const permissionDenied = result.finalAnswer.startsWith("Permission denied for tool");
|
|
13000
12771
|
if (permissionDenied) {
|
|
@@ -13034,30 +12805,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
13034
12805
|
await state.sessionStore.save(updatedSession);
|
|
13035
12806
|
} catch (error) {
|
|
13036
12807
|
useCliStore.getState().clearPendingMessages();
|
|
13037
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
13038
|
-
logger.debug("[ABORT] Operation aborted by user");
|
|
13039
|
-
const currentSession = useCliStore.getState().session;
|
|
13040
|
-
if (currentSession) {
|
|
13041
|
-
const cancelMessage = {
|
|
13042
|
-
id: uuidv410(),
|
|
13043
|
-
role: "assistant",
|
|
13044
|
-
content: "\u26A0\uFE0F Operation cancelled by user",
|
|
13045
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13046
|
-
metadata: {
|
|
13047
|
-
cancelled: true
|
|
13048
|
-
}
|
|
13049
|
-
};
|
|
13050
|
-
const sessionWithCancel = {
|
|
13051
|
-
...currentSession,
|
|
13052
|
-
messages: [...currentSession.messages, cancelMessage],
|
|
13053
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13054
|
-
};
|
|
13055
|
-
setState((prev) => ({ ...prev, session: sessionWithCancel }));
|
|
13056
|
-
setStoreSession(sessionWithCancel);
|
|
13057
|
-
await state.sessionStore.save(sessionWithCancel);
|
|
13058
|
-
}
|
|
13059
|
-
return;
|
|
13060
|
-
}
|
|
13061
12808
|
if (error instanceof Error) {
|
|
13062
12809
|
if (error.message.includes("Authentication failed") || error.message.includes("Authentication expired")) {
|
|
13063
12810
|
console.log("\n\u274C Authentication failed");
|
|
@@ -13066,9 +12813,6 @@ ${contextResult.mergedContent}` : "";
|
|
|
13066
12813
|
}
|
|
13067
12814
|
}
|
|
13068
12815
|
console.error("Error processing message:", error);
|
|
13069
|
-
} finally {
|
|
13070
|
-
setState((prev) => ({ ...prev, abortController: null }));
|
|
13071
|
-
useCliStore.getState().setIsThinking(false);
|
|
13072
12816
|
}
|
|
13073
12817
|
};
|
|
13074
12818
|
const handleBashCommand = useCallback(
|
|
@@ -13119,7 +12863,7 @@ ${output}` : output.trim() || "(no output)",
|
|
|
13119
12863
|
if (!imageStore) {
|
|
13120
12864
|
if (!imageStoreInitPromise.current) {
|
|
13121
12865
|
imageStoreInitPromise.current = (async () => {
|
|
13122
|
-
const { ImageStore: ImageStoreClass } = await import("./ImageStore-
|
|
12866
|
+
const { ImageStore: ImageStoreClass } = await import("./ImageStore-RQZ7OF7P.js");
|
|
13123
12867
|
const newImageStore = new ImageStoreClass();
|
|
13124
12868
|
setState((prev) => ({
|
|
13125
12869
|
...prev,
|