@probelabs/probe 0.6.0-rc101 → 0.6.0-rc103
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/build/agent/ProbeAgent.js +254 -4
- package/build/agent/index.js +257 -41
- package/build/mcp/index.js +24 -145
- package/build/mcp/index.ts +23 -162
- package/build/tools/system-message.js +7 -1
- package/cjs/agent/ProbeAgent.cjs +202 -11
- package/cjs/index.cjs +214 -23
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +254 -4
- package/src/agent/index.js +50 -18
- package/src/mcp/index.ts +23 -162
- package/src/tools/system-message.js +7 -1
package/build/agent/index.js
CHANGED
|
@@ -1821,7 +1821,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
|
|
|
1821
1821
|
console.error(`[DELEGATE] Using binary at: ${binaryPath}`);
|
|
1822
1822
|
console.error(`[DELEGATE] Command args: ${args.join(" ")}`);
|
|
1823
1823
|
}
|
|
1824
|
-
return new Promise((
|
|
1824
|
+
return new Promise((resolve3, reject) => {
|
|
1825
1825
|
const delegationSpan = tracer ? tracer.createDelegationSpan(sessionId, task) : null;
|
|
1826
1826
|
const process2 = spawn(binaryPath, args, {
|
|
1827
1827
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -1886,7 +1886,7 @@ async function delegate({ task, timeout = 300, debug = false, currentIteration =
|
|
|
1886
1886
|
delegationSpan.end();
|
|
1887
1887
|
}
|
|
1888
1888
|
}
|
|
1889
|
-
|
|
1889
|
+
resolve3(response);
|
|
1890
1890
|
} else {
|
|
1891
1891
|
const errorMessage = stderr.trim() || `Delegate process failed with exit code ${code}`;
|
|
1892
1892
|
if (debug) {
|
|
@@ -2246,13 +2246,19 @@ For GitHub-compatible mermaid diagrams, avoid single quotes and parentheses in n
|
|
|
2246
2246
|
|
|
2247
2247
|
**Rules:**
|
|
2248
2248
|
- NO single quotes in any node labels: 'text' \u2192 "text" or text
|
|
2249
|
-
- NO parentheses in square brackets: [Text (detail)] \u2192 [Text - detail]
|
|
2249
|
+
- NO parentheses in square brackets: [Text (detail)] \u2192 [Text - detail]
|
|
2250
2250
|
- NO complex expressions in diamonds: {a && b} \u2192 {condition}
|
|
2251
|
+
- NO HTML tags in node labels: [<pre>code</pre>] \u2192 ["code block"] or [Code Block]
|
|
2251
2252
|
- USE single quotes for styles and classes: classDef highlight fill:'#ff9999'
|
|
2253
|
+
- CRITICAL: When using quotes in node labels, place them INSIDE the brackets: ["quoted text"], NOT [quoted text"]
|
|
2252
2254
|
|
|
2253
2255
|
**Examples:**
|
|
2254
2256
|
- \u2705 [Load Config] ["Run command"] {Valid?}
|
|
2257
|
+
- \u2705 ["depends_on: [generate-items]"] (correct quote placement)
|
|
2258
|
+
- \u2705 ["Code Block"] (clean text instead of HTML)
|
|
2255
2259
|
- \u274C [Load (config)] [Run 'command'] {isValid('x')}
|
|
2260
|
+
- \u274C [depends_on: [generate-items"] (incorrect quote placement - quote ends inside bracket)
|
|
2261
|
+
- \u274C [<pre>depends_on: [generate-items]</pre>] (HTML tags in node labels)
|
|
2256
2262
|
|
|
2257
2263
|
**Diagram Type Selection:**
|
|
2258
2264
|
|
|
@@ -2510,20 +2516,20 @@ var init_simpleTelemetry = __esm({
|
|
|
2510
2516
|
}
|
|
2511
2517
|
async flush() {
|
|
2512
2518
|
if (this.stream) {
|
|
2513
|
-
return new Promise((
|
|
2514
|
-
this.stream.once("drain",
|
|
2519
|
+
return new Promise((resolve3) => {
|
|
2520
|
+
this.stream.once("drain", resolve3);
|
|
2515
2521
|
if (!this.stream.writableNeedDrain) {
|
|
2516
|
-
|
|
2522
|
+
resolve3();
|
|
2517
2523
|
}
|
|
2518
2524
|
});
|
|
2519
2525
|
}
|
|
2520
2526
|
}
|
|
2521
2527
|
async shutdown() {
|
|
2522
2528
|
if (this.stream) {
|
|
2523
|
-
return new Promise((
|
|
2529
|
+
return new Promise((resolve3) => {
|
|
2524
2530
|
this.stream.end(() => {
|
|
2525
2531
|
console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
|
|
2526
|
-
|
|
2532
|
+
resolve3();
|
|
2527
2533
|
});
|
|
2528
2534
|
});
|
|
2529
2535
|
}
|
|
@@ -2969,7 +2975,7 @@ function createMockProvider() {
|
|
|
2969
2975
|
provider: "mock",
|
|
2970
2976
|
// Mock the doGenerate method used by Vercel AI SDK
|
|
2971
2977
|
doGenerate: async ({ messages, tools: tools2 }) => {
|
|
2972
|
-
await new Promise((
|
|
2978
|
+
await new Promise((resolve3) => setTimeout(resolve3, 10));
|
|
2973
2979
|
return {
|
|
2974
2980
|
text: "This is a mock response for testing",
|
|
2975
2981
|
toolCalls: [],
|
|
@@ -4859,7 +4865,10 @@ import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
|
4859
4865
|
import { streamText } from "ai";
|
|
4860
4866
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
4861
4867
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
4862
|
-
|
|
4868
|
+
import { existsSync as existsSync3 } from "fs";
|
|
4869
|
+
import { readFile, stat } from "fs/promises";
|
|
4870
|
+
import { resolve, isAbsolute } from "path";
|
|
4871
|
+
var MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, SUPPORTED_IMAGE_EXTENSIONS, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
4863
4872
|
var init_ProbeAgent = __esm({
|
|
4864
4873
|
"src/agent/ProbeAgent.js"() {
|
|
4865
4874
|
"use strict";
|
|
@@ -4873,6 +4882,8 @@ var init_ProbeAgent = __esm({
|
|
|
4873
4882
|
init_mcp();
|
|
4874
4883
|
MAX_TOOL_ITERATIONS = parseInt(process.env.MAX_TOOL_ITERATIONS || "30", 10);
|
|
4875
4884
|
MAX_HISTORY_MESSAGES = 100;
|
|
4885
|
+
SUPPORTED_IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "webp", "gif", "bmp", "svg"];
|
|
4886
|
+
MAX_IMAGE_FILE_SIZE = 20 * 1024 * 1024;
|
|
4876
4887
|
ProbeAgent = class {
|
|
4877
4888
|
/**
|
|
4878
4889
|
* Create a new ProbeAgent instance
|
|
@@ -4916,6 +4927,8 @@ var init_ProbeAgent = __esm({
|
|
|
4916
4927
|
}
|
|
4917
4928
|
this.initializeTools();
|
|
4918
4929
|
this.history = [];
|
|
4930
|
+
this.pendingImages = /* @__PURE__ */ new Map();
|
|
4931
|
+
this.currentImages = [];
|
|
4919
4932
|
this.events = new EventEmitter2();
|
|
4920
4933
|
this.enableMcp = !!options.enableMcp || process.env.ENABLE_MCP === "1";
|
|
4921
4934
|
this.mcpConfigPath = options.mcpConfigPath || null;
|
|
@@ -5041,6 +5054,175 @@ var init_ProbeAgent = __esm({
|
|
|
5041
5054
|
console.log(`Using Google API with model: ${this.model}${apiUrl ? ` (URL: ${apiUrl})` : ""}`);
|
|
5042
5055
|
}
|
|
5043
5056
|
}
|
|
5057
|
+
/**
|
|
5058
|
+
* Process assistant response content and detect/load image references
|
|
5059
|
+
* @param {string} content - The assistant's response content
|
|
5060
|
+
* @returns {Promise<void>}
|
|
5061
|
+
*/
|
|
5062
|
+
async processImageReferences(content) {
|
|
5063
|
+
if (!content) return;
|
|
5064
|
+
const extensionsPattern = `(?:${SUPPORTED_IMAGE_EXTENSIONS.join("|")})`;
|
|
5065
|
+
const imagePatterns = [
|
|
5066
|
+
// Direct file path mentions: "./screenshot.png", "/path/to/image.jpg", etc.
|
|
5067
|
+
new RegExp(`(?:\\.?\\.\\/)?[^\\s"'<>\\[\\]]+\\.${extensionsPattern}(?!\\w)`, "gi"),
|
|
5068
|
+
// Contextual mentions: "look at image.png", "the file screenshot.jpg shows"
|
|
5069
|
+
new RegExp(`(?:image|file|screenshot|diagram|photo|picture|graphic)\\s*:?\\s*([^\\s"'<>\\[\\]]+\\.${extensionsPattern})(?!\\w)`, "gi"),
|
|
5070
|
+
// Tool result mentions: often contain file paths
|
|
5071
|
+
new RegExp(`(?:found|saved|created|generated).*?([^\\s"'<>\\[\\]]+\\.${extensionsPattern})(?!\\w)`, "gi")
|
|
5072
|
+
];
|
|
5073
|
+
const foundPaths = /* @__PURE__ */ new Set();
|
|
5074
|
+
for (const pattern of imagePatterns) {
|
|
5075
|
+
let match;
|
|
5076
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
5077
|
+
const imagePath = match[1] || match[0];
|
|
5078
|
+
if (imagePath && imagePath.length > 0) {
|
|
5079
|
+
foundPaths.add(imagePath.trim());
|
|
5080
|
+
}
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
if (foundPaths.size === 0) return;
|
|
5084
|
+
if (this.debug) {
|
|
5085
|
+
console.log(`[DEBUG] Found ${foundPaths.size} potential image references:`, Array.from(foundPaths));
|
|
5086
|
+
}
|
|
5087
|
+
for (const imagePath of foundPaths) {
|
|
5088
|
+
await this.loadImageIfValid(imagePath);
|
|
5089
|
+
}
|
|
5090
|
+
}
|
|
5091
|
+
/**
|
|
5092
|
+
* Load and cache an image if it's valid and accessible
|
|
5093
|
+
* @param {string} imagePath - Path to the image file
|
|
5094
|
+
* @returns {Promise<boolean>} - True if image was loaded successfully
|
|
5095
|
+
*/
|
|
5096
|
+
async loadImageIfValid(imagePath) {
|
|
5097
|
+
try {
|
|
5098
|
+
if (this.pendingImages.has(imagePath)) {
|
|
5099
|
+
if (this.debug) {
|
|
5100
|
+
console.log(`[DEBUG] Image already loaded: ${imagePath}`);
|
|
5101
|
+
}
|
|
5102
|
+
return true;
|
|
5103
|
+
}
|
|
5104
|
+
const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
|
|
5105
|
+
let absolutePath;
|
|
5106
|
+
let isPathAllowed = false;
|
|
5107
|
+
if (isAbsolute(imagePath)) {
|
|
5108
|
+
absolutePath = imagePath;
|
|
5109
|
+
isPathAllowed = allowedDirs.some((dir) => absolutePath.startsWith(resolve(dir)));
|
|
5110
|
+
} else {
|
|
5111
|
+
for (const dir of allowedDirs) {
|
|
5112
|
+
const resolvedPath = resolve(dir, imagePath);
|
|
5113
|
+
if (resolvedPath.startsWith(resolve(dir))) {
|
|
5114
|
+
absolutePath = resolvedPath;
|
|
5115
|
+
isPathAllowed = true;
|
|
5116
|
+
break;
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
}
|
|
5120
|
+
if (!isPathAllowed) {
|
|
5121
|
+
if (this.debug) {
|
|
5122
|
+
console.log(`[DEBUG] Image path outside allowed directories: ${imagePath}`);
|
|
5123
|
+
}
|
|
5124
|
+
return false;
|
|
5125
|
+
}
|
|
5126
|
+
let fileStats;
|
|
5127
|
+
try {
|
|
5128
|
+
fileStats = await stat(absolutePath);
|
|
5129
|
+
} catch (error) {
|
|
5130
|
+
if (this.debug) {
|
|
5131
|
+
console.log(`[DEBUG] Image file not found: ${absolutePath}`);
|
|
5132
|
+
}
|
|
5133
|
+
return false;
|
|
5134
|
+
}
|
|
5135
|
+
if (fileStats.size > MAX_IMAGE_FILE_SIZE) {
|
|
5136
|
+
if (this.debug) {
|
|
5137
|
+
console.log(`[DEBUG] Image file too large: ${absolutePath} (${fileStats.size} bytes, max: ${MAX_IMAGE_FILE_SIZE})`);
|
|
5138
|
+
}
|
|
5139
|
+
return false;
|
|
5140
|
+
}
|
|
5141
|
+
const extension = absolutePath.toLowerCase().split(".").pop();
|
|
5142
|
+
if (!SUPPORTED_IMAGE_EXTENSIONS.includes(extension)) {
|
|
5143
|
+
if (this.debug) {
|
|
5144
|
+
console.log(`[DEBUG] Unsupported image format: ${extension}`);
|
|
5145
|
+
}
|
|
5146
|
+
return false;
|
|
5147
|
+
}
|
|
5148
|
+
const mimeTypes = {
|
|
5149
|
+
"png": "image/png",
|
|
5150
|
+
"jpg": "image/jpeg",
|
|
5151
|
+
"jpeg": "image/jpeg",
|
|
5152
|
+
"webp": "image/webp",
|
|
5153
|
+
"gif": "image/gif",
|
|
5154
|
+
"bmp": "image/bmp",
|
|
5155
|
+
"svg": "image/svg+xml"
|
|
5156
|
+
};
|
|
5157
|
+
const mimeType = mimeTypes[extension];
|
|
5158
|
+
const fileBuffer = await readFile(absolutePath);
|
|
5159
|
+
const base64Data = fileBuffer.toString("base64");
|
|
5160
|
+
const dataUrl = `data:${mimeType};base64,${base64Data}`;
|
|
5161
|
+
this.pendingImages.set(imagePath, dataUrl);
|
|
5162
|
+
if (this.debug) {
|
|
5163
|
+
console.log(`[DEBUG] Successfully loaded image: ${imagePath} (${fileBuffer.length} bytes)`);
|
|
5164
|
+
}
|
|
5165
|
+
return true;
|
|
5166
|
+
} catch (error) {
|
|
5167
|
+
if (this.debug) {
|
|
5168
|
+
console.log(`[DEBUG] Failed to load image ${imagePath}: ${error.message}`);
|
|
5169
|
+
}
|
|
5170
|
+
return false;
|
|
5171
|
+
}
|
|
5172
|
+
}
|
|
5173
|
+
/**
|
|
5174
|
+
* Get all currently loaded images as an array for AI model consumption
|
|
5175
|
+
* @returns {Array<string>} - Array of base64 data URLs
|
|
5176
|
+
*/
|
|
5177
|
+
getCurrentImages() {
|
|
5178
|
+
return Array.from(this.pendingImages.values());
|
|
5179
|
+
}
|
|
5180
|
+
/**
|
|
5181
|
+
* Clear loaded images (useful for new conversations)
|
|
5182
|
+
*/
|
|
5183
|
+
clearLoadedImages() {
|
|
5184
|
+
this.pendingImages.clear();
|
|
5185
|
+
this.currentImages = [];
|
|
5186
|
+
if (this.debug) {
|
|
5187
|
+
console.log("[DEBUG] Cleared all loaded images");
|
|
5188
|
+
}
|
|
5189
|
+
}
|
|
5190
|
+
/**
|
|
5191
|
+
* Prepare messages for AI consumption, adding images to the latest user message if available
|
|
5192
|
+
* @param {Array} messages - Current conversation messages
|
|
5193
|
+
* @returns {Array} - Messages formatted for AI SDK with potential image content
|
|
5194
|
+
*/
|
|
5195
|
+
prepareMessagesWithImages(messages) {
|
|
5196
|
+
const loadedImages = this.getCurrentImages();
|
|
5197
|
+
if (loadedImages.length === 0) {
|
|
5198
|
+
return messages;
|
|
5199
|
+
}
|
|
5200
|
+
const messagesWithImages = [...messages];
|
|
5201
|
+
const lastUserMessageIndex = messagesWithImages.map((m) => m.role).lastIndexOf("user");
|
|
5202
|
+
if (lastUserMessageIndex === -1) {
|
|
5203
|
+
if (this.debug) {
|
|
5204
|
+
console.log("[DEBUG] No user messages found to attach images to");
|
|
5205
|
+
}
|
|
5206
|
+
return messages;
|
|
5207
|
+
}
|
|
5208
|
+
const lastUserMessage = messagesWithImages[lastUserMessageIndex];
|
|
5209
|
+
if (typeof lastUserMessage.content === "string") {
|
|
5210
|
+
messagesWithImages[lastUserMessageIndex] = {
|
|
5211
|
+
...lastUserMessage,
|
|
5212
|
+
content: [
|
|
5213
|
+
{ type: "text", text: lastUserMessage.content },
|
|
5214
|
+
...loadedImages.map((imageData) => ({
|
|
5215
|
+
type: "image",
|
|
5216
|
+
image: imageData
|
|
5217
|
+
}))
|
|
5218
|
+
]
|
|
5219
|
+
};
|
|
5220
|
+
if (this.debug) {
|
|
5221
|
+
console.log(`[DEBUG] Added ${loadedImages.length} images to the latest user message`);
|
|
5222
|
+
}
|
|
5223
|
+
}
|
|
5224
|
+
return messagesWithImages;
|
|
5225
|
+
}
|
|
5044
5226
|
/**
|
|
5045
5227
|
* Initialize mock model for testing
|
|
5046
5228
|
*/
|
|
@@ -5140,7 +5322,7 @@ Examples:
|
|
|
5140
5322
|
</extract>
|
|
5141
5323
|
|
|
5142
5324
|
<attempt_completion>
|
|
5143
|
-
|
|
5325
|
+
The configuration is loaded from src/config.js lines 15-25 which contains the database settings.
|
|
5144
5326
|
</attempt_completion>
|
|
5145
5327
|
|
|
5146
5328
|
# Special Case: Quick Completion
|
|
@@ -5167,7 +5349,7 @@ I need to find code related to error handling in the search module. The most app
|
|
|
5167
5349
|
6. Wait for the tool execution result, which will be provided in the next message (within a <tool_result> block).
|
|
5168
5350
|
7. Analyze the tool result and decide the next step. If more tool calls are needed, repeat steps 2-6.
|
|
5169
5351
|
8. If the task is fully complete and all previous steps were successful, use the \`<attempt_completion>\` tool to provide the final answer. This is the ONLY way to finish the task.
|
|
5170
|
-
9. If you cannot proceed (e.g., missing information, invalid request), explain the issue clearly
|
|
5352
|
+
9. If you cannot proceed (e.g., missing information, invalid request), use \`<attempt_completion>\` to explain the issue clearly with an appropriate message directly inside the tags.
|
|
5171
5353
|
10. If your previous response was already correct and complete, you may use \`<attempt_complete>\` as a shorthand.
|
|
5172
5354
|
|
|
5173
5355
|
Available Tools:
|
|
@@ -5422,9 +5604,10 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
5422
5604
|
let assistantResponseContent = "";
|
|
5423
5605
|
try {
|
|
5424
5606
|
const executeAIRequest = async () => {
|
|
5607
|
+
const messagesForAI = this.prepareMessagesWithImages(currentMessages);
|
|
5425
5608
|
const result = await streamText({
|
|
5426
5609
|
model: this.provider(this.model),
|
|
5427
|
-
messages:
|
|
5610
|
+
messages: messagesForAI,
|
|
5428
5611
|
maxTokens: maxResponseTokens,
|
|
5429
5612
|
temperature: 0.3
|
|
5430
5613
|
});
|
|
@@ -5458,6 +5641,9 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
5458
5641
|
const assistantPreview = createMessagePreview(assistantResponseContent);
|
|
5459
5642
|
console.log(`[DEBUG] Assistant response (${assistantResponseContent.length} chars): ${assistantPreview}`);
|
|
5460
5643
|
}
|
|
5644
|
+
if (assistantResponseContent) {
|
|
5645
|
+
await this.processImageReferences(assistantResponseContent);
|
|
5646
|
+
}
|
|
5461
5647
|
const validTools = [
|
|
5462
5648
|
"search",
|
|
5463
5649
|
"query",
|
|
@@ -5582,12 +5768,17 @@ ${toolResultContent}
|
|
|
5582
5768
|
throw toolError;
|
|
5583
5769
|
}
|
|
5584
5770
|
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
5771
|
+
const toolResultContent = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult, null, 2);
|
|
5772
|
+
const toolResultMessage = `<tool_result>
|
|
5773
|
+
${toolResultContent}
|
|
5774
|
+
</tool_result>`;
|
|
5585
5775
|
currentMessages.push({
|
|
5586
5776
|
role: "user",
|
|
5587
|
-
content:
|
|
5588
|
-
${typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult, null, 2)}
|
|
5589
|
-
</tool_result>`
|
|
5777
|
+
content: toolResultMessage
|
|
5590
5778
|
});
|
|
5779
|
+
if (toolResultContent) {
|
|
5780
|
+
await this.processImageReferences(toolResultContent);
|
|
5781
|
+
}
|
|
5591
5782
|
if (this.debug) {
|
|
5592
5783
|
console.log(`[DEBUG] Tool ${toolName} executed successfully. Result length: ${typeof toolResult === "string" ? toolResult.length : JSON.stringify(toolResult).length}`);
|
|
5593
5784
|
}
|
|
@@ -6084,11 +6275,12 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
6084
6275
|
import {
|
|
6085
6276
|
CallToolRequestSchema,
|
|
6086
6277
|
ErrorCode as ErrorCode2,
|
|
6278
|
+
InitializeRequestSchema,
|
|
6087
6279
|
ListToolsRequestSchema,
|
|
6088
6280
|
McpError
|
|
6089
6281
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
6090
|
-
import { readFileSync as readFileSync2, existsSync as
|
|
6091
|
-
import { resolve } from "path";
|
|
6282
|
+
import { readFileSync as readFileSync2, existsSync as existsSync4 } from "fs";
|
|
6283
|
+
import { resolve as resolve2 } from "path";
|
|
6092
6284
|
|
|
6093
6285
|
// src/agent/acp/server.js
|
|
6094
6286
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -6347,8 +6539,8 @@ var ACPConnection = class extends EventEmitter3 {
|
|
|
6347
6539
|
if (params !== null) {
|
|
6348
6540
|
message.params = params;
|
|
6349
6541
|
}
|
|
6350
|
-
return new Promise((
|
|
6351
|
-
this.pendingRequests.set(id, { resolve:
|
|
6542
|
+
return new Promise((resolve3, reject) => {
|
|
6543
|
+
this.pendingRequests.set(id, { resolve: resolve3, reject });
|
|
6352
6544
|
this.sendMessage(message);
|
|
6353
6545
|
setTimeout(() => {
|
|
6354
6546
|
if (this.pendingRequests.has(id)) {
|
|
@@ -6756,8 +6948,8 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
6756
6948
|
function readInputContent(input) {
|
|
6757
6949
|
if (!input) return null;
|
|
6758
6950
|
try {
|
|
6759
|
-
const resolvedPath =
|
|
6760
|
-
if (
|
|
6951
|
+
const resolvedPath = resolve2(input);
|
|
6952
|
+
if (existsSync4(resolvedPath)) {
|
|
6761
6953
|
return readFileSync2(resolvedPath, "utf-8").trim();
|
|
6762
6954
|
}
|
|
6763
6955
|
} catch (error) {
|
|
@@ -6765,7 +6957,7 @@ function readInputContent(input) {
|
|
|
6765
6957
|
return input;
|
|
6766
6958
|
}
|
|
6767
6959
|
function readFromStdin() {
|
|
6768
|
-
return new Promise((
|
|
6960
|
+
return new Promise((resolve3, reject) => {
|
|
6769
6961
|
let data = "";
|
|
6770
6962
|
let hasReceivedData = false;
|
|
6771
6963
|
let dataChunks = [];
|
|
@@ -6790,7 +6982,7 @@ function readFromStdin() {
|
|
|
6790
6982
|
if (!trimmed && dataChunks.length === 0) {
|
|
6791
6983
|
reject(new Error("No input received from stdin"));
|
|
6792
6984
|
} else {
|
|
6793
|
-
|
|
6985
|
+
resolve3(trimmed);
|
|
6794
6986
|
}
|
|
6795
6987
|
});
|
|
6796
6988
|
process.stdin.on("error", (error) => {
|
|
@@ -6948,7 +7140,7 @@ var ProbeAgentMcpServer = class {
|
|
|
6948
7140
|
constructor() {
|
|
6949
7141
|
this.server = new Server(
|
|
6950
7142
|
{
|
|
6951
|
-
name: "@
|
|
7143
|
+
name: "@probelabs/probe agent",
|
|
6952
7144
|
version: "1.0.0"
|
|
6953
7145
|
},
|
|
6954
7146
|
{
|
|
@@ -6957,6 +7149,7 @@ var ProbeAgentMcpServer = class {
|
|
|
6957
7149
|
}
|
|
6958
7150
|
}
|
|
6959
7151
|
);
|
|
7152
|
+
this.agent = null;
|
|
6960
7153
|
this.setupToolHandlers();
|
|
6961
7154
|
this.server.onerror = (error) => console.error("[MCP Error]", error);
|
|
6962
7155
|
process.on("SIGINT", async () => {
|
|
@@ -6965,6 +7158,18 @@ var ProbeAgentMcpServer = class {
|
|
|
6965
7158
|
});
|
|
6966
7159
|
}
|
|
6967
7160
|
setupToolHandlers() {
|
|
7161
|
+
this.server.setRequestHandler(InitializeRequestSchema, async (request) => {
|
|
7162
|
+
return {
|
|
7163
|
+
protocolVersion: "2024-11-05",
|
|
7164
|
+
capabilities: {
|
|
7165
|
+
tools: {}
|
|
7166
|
+
},
|
|
7167
|
+
serverInfo: {
|
|
7168
|
+
name: "@probelabs/probe agent",
|
|
7169
|
+
version: "1.0.0"
|
|
7170
|
+
}
|
|
7171
|
+
};
|
|
7172
|
+
});
|
|
6968
7173
|
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
6969
7174
|
tools: [
|
|
6970
7175
|
{
|
|
@@ -7056,18 +7261,24 @@ var ProbeAgentMcpServer = class {
|
|
|
7056
7261
|
throw new Error("Schema could not be read");
|
|
7057
7262
|
}
|
|
7058
7263
|
}
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7264
|
+
if (!this.agent) {
|
|
7265
|
+
if (process.env.DEBUG === "1") {
|
|
7266
|
+
console.error("[DEBUG] Initializing AI agent on first MCP tool call");
|
|
7267
|
+
}
|
|
7268
|
+
const agentConfig2 = {
|
|
7269
|
+
path: args.path || process.cwd(),
|
|
7270
|
+
promptType: args.prompt || "code-explorer",
|
|
7271
|
+
customPrompt: systemPrompt,
|
|
7272
|
+
provider: args.provider,
|
|
7273
|
+
model: args.model,
|
|
7274
|
+
allowEdit: !!args.allow_edit,
|
|
7275
|
+
debug: process.env.DEBUG === "1",
|
|
7276
|
+
maxResponseTokens: args.max_response_tokens,
|
|
7277
|
+
disableMermaidValidation: !!args.no_mermaid_validation
|
|
7278
|
+
};
|
|
7279
|
+
this.agent = new ProbeAgent(agentConfig2);
|
|
7280
|
+
}
|
|
7281
|
+
const agent = this.agent;
|
|
7071
7282
|
let result = await agent.answer(query2, [], { schema });
|
|
7072
7283
|
if (schema) {
|
|
7073
7284
|
const schemaPrompt = `Now you need to respond according to this schema:
|
|
@@ -7128,7 +7339,7 @@ Please reformat your previous response to match this schema exactly. Only return
|
|
|
7128
7339
|
} catch (error) {
|
|
7129
7340
|
}
|
|
7130
7341
|
}
|
|
7131
|
-
const tokenUsage = agent.getTokenUsage();
|
|
7342
|
+
const tokenUsage = this.agent.getTokenUsage();
|
|
7132
7343
|
console.error(`Token usage: ${JSON.stringify(tokenUsage)}`);
|
|
7133
7344
|
return {
|
|
7134
7345
|
content: [
|
|
@@ -7253,7 +7464,7 @@ async function main() {
|
|
|
7253
7464
|
process.exit(1);
|
|
7254
7465
|
}
|
|
7255
7466
|
}
|
|
7256
|
-
const
|
|
7467
|
+
const agentConfig2 = {
|
|
7257
7468
|
path: config.path,
|
|
7258
7469
|
promptType: config.prompt,
|
|
7259
7470
|
customPrompt: systemPrompt,
|
|
@@ -7264,7 +7475,7 @@ async function main() {
|
|
|
7264
7475
|
maxResponseTokens: config.maxResponseTokens,
|
|
7265
7476
|
disableMermaidValidation: config.noMermaidValidation
|
|
7266
7477
|
};
|
|
7267
|
-
const agent = new ProbeAgent(
|
|
7478
|
+
const agent = new ProbeAgent(agentConfig2);
|
|
7268
7479
|
let result;
|
|
7269
7480
|
if (appTracer) {
|
|
7270
7481
|
const sessionSpan = appTracer.createSessionSpan({
|
|
@@ -7386,7 +7597,12 @@ Please reformat your previous response to match this schema exactly. Only return
|
|
|
7386
7597
|
}
|
|
7387
7598
|
}
|
|
7388
7599
|
}
|
|
7389
|
-
|
|
7600
|
+
const resultMatch = result.match(/<result>([\s\S]*?)<\/result>/);
|
|
7601
|
+
if (resultMatch) {
|
|
7602
|
+
console.log(resultMatch[1].trim());
|
|
7603
|
+
} else {
|
|
7604
|
+
console.log(result);
|
|
7605
|
+
}
|
|
7390
7606
|
if (config.verbose) {
|
|
7391
7607
|
const tokenUsage = agent.getTokenUsage();
|
|
7392
7608
|
console.error(`
|