@probelabs/probe 0.6.0-rc167 → 0.6.0-rc169
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.d.ts +7 -1
- package/build/agent/ProbeAgent.js +353 -32
- package/build/agent/engines/codex.js +347 -0
- package/build/agent/engines/enhanced-claude-code.js +3 -42
- package/build/agent/index.js +1036 -81
- package/build/agent/mcp/built-in-server.js +334 -8
- package/build/agent/shared/Session.js +53 -0
- package/build/agent/shared/prompts.js +129 -0
- package/build/agent/tools.js +26 -9
- package/cjs/agent/ProbeAgent.cjs +1074 -92
- package/cjs/index.cjs +1083 -101
- package/index.d.ts +7 -1
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +7 -1
- package/src/agent/ProbeAgent.js +353 -32
- package/src/agent/engines/codex.js +347 -0
- package/src/agent/engines/enhanced-claude-code.js +3 -42
- package/src/agent/mcp/built-in-server.js +334 -8
- package/src/agent/shared/Session.js +53 -0
- package/src/agent/shared/prompts.js +129 -0
- package/src/agent/tools.js +26 -9
package/build/agent/index.js
CHANGED
|
@@ -8296,8 +8296,8 @@ var init_vercel = __esm({
|
|
|
8296
8296
|
const { writeFileSync: writeFileSync2, unlinkSync } = await import("fs");
|
|
8297
8297
|
const { join: join3 } = await import("path");
|
|
8298
8298
|
const { tmpdir } = await import("os");
|
|
8299
|
-
const { randomUUID:
|
|
8300
|
-
tempFilePath = join3(tmpdir(), `probe-extract-${
|
|
8299
|
+
const { randomUUID: randomUUID8 } = await import("crypto");
|
|
8300
|
+
tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID8()}.txt`);
|
|
8301
8301
|
writeFileSync2(tempFilePath, input_content);
|
|
8302
8302
|
if (debug) {
|
|
8303
8303
|
console.error(`Created temporary file for input content: ${tempFilePath}`);
|
|
@@ -17550,17 +17550,30 @@ var init_xmlParsingUtils = __esm({
|
|
|
17550
17550
|
// src/agent/tools.js
|
|
17551
17551
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
17552
17552
|
function createTools(configOptions) {
|
|
17553
|
-
const tools2 = {
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17559
|
-
|
|
17553
|
+
const tools2 = {};
|
|
17554
|
+
const isToolAllowed = configOptions.isToolAllowed || ((toolName) => {
|
|
17555
|
+
if (!configOptions.allowedTools) return true;
|
|
17556
|
+
return configOptions.allowedTools.isEnabled(toolName);
|
|
17557
|
+
});
|
|
17558
|
+
if (isToolAllowed("search")) {
|
|
17559
|
+
tools2.searchTool = searchTool(configOptions);
|
|
17560
|
+
}
|
|
17561
|
+
if (isToolAllowed("query")) {
|
|
17562
|
+
tools2.queryTool = queryTool(configOptions);
|
|
17563
|
+
}
|
|
17564
|
+
if (isToolAllowed("extract")) {
|
|
17565
|
+
tools2.extractTool = extractTool(configOptions);
|
|
17566
|
+
}
|
|
17567
|
+
if (configOptions.enableDelegate && isToolAllowed("delegate")) {
|
|
17568
|
+
tools2.delegateTool = delegateTool(configOptions);
|
|
17569
|
+
}
|
|
17570
|
+
if (configOptions.enableBash && isToolAllowed("bash")) {
|
|
17560
17571
|
tools2.bashTool = bashTool(configOptions);
|
|
17561
17572
|
}
|
|
17562
|
-
if (configOptions.allowEdit) {
|
|
17573
|
+
if (configOptions.allowEdit && isToolAllowed("edit")) {
|
|
17563
17574
|
tools2.editTool = editTool(configOptions);
|
|
17575
|
+
}
|
|
17576
|
+
if (configOptions.allowEdit && isToolAllowed("create")) {
|
|
17564
17577
|
tools2.createTool = createTool(configOptions);
|
|
17565
17578
|
}
|
|
17566
17579
|
return tools2;
|
|
@@ -55844,6 +55857,126 @@ Provide only the corrected Mermaid diagram within a mermaid code block. Do not a
|
|
|
55844
55857
|
}
|
|
55845
55858
|
});
|
|
55846
55859
|
|
|
55860
|
+
// src/agent/shared/prompts.js
|
|
55861
|
+
var predefinedPrompts;
|
|
55862
|
+
var init_prompts = __esm({
|
|
55863
|
+
"src/agent/shared/prompts.js"() {
|
|
55864
|
+
"use strict";
|
|
55865
|
+
predefinedPrompts = {
|
|
55866
|
+
"code-explorer": `You are ProbeChat Code Explorer - an AI assistant focused on reading and explaining code using Probe's semantic search capabilities.
|
|
55867
|
+
|
|
55868
|
+
Your primary role is to explore codebases, understand code structure, and provide clear explanations. You should:
|
|
55869
|
+
|
|
55870
|
+
1. Use the 'search' tool to find relevant code snippets across the codebase
|
|
55871
|
+
2. Use the 'query' tool to locate specific symbols, functions, or classes
|
|
55872
|
+
3. Use the 'extract' tool to get full context for files or specific code blocks
|
|
55873
|
+
4. Explain code behavior, architecture patterns, and relationships between components
|
|
55874
|
+
5. Provide concise summaries with key insights highlighted
|
|
55875
|
+
|
|
55876
|
+
When exploring code:
|
|
55877
|
+
- Start with targeted searches to find relevant areas
|
|
55878
|
+
- Extract full context when you need to understand implementation details
|
|
55879
|
+
- Trace function calls and data flow to understand how components interact
|
|
55880
|
+
- Focus on "why" and "how" rather than just describing what the code does
|
|
55881
|
+
|
|
55882
|
+
You should NOT:
|
|
55883
|
+
- Make changes to the codebase (read-only access)
|
|
55884
|
+
- Execute or run code
|
|
55885
|
+
- Make assumptions without verifying through search/query/extract`,
|
|
55886
|
+
"architect": `You are ProbeChat Architect - a senior software architect specialized in analyzing and designing software systems.
|
|
55887
|
+
|
|
55888
|
+
Your role is to:
|
|
55889
|
+
|
|
55890
|
+
1. Analyze existing codebases to understand architecture patterns and design decisions
|
|
55891
|
+
2. Identify architectural issues, technical debt, and improvement opportunities
|
|
55892
|
+
3. Propose refactoring strategies and architectural changes
|
|
55893
|
+
4. Design new features that fit well with existing architecture
|
|
55894
|
+
5. Create high-level architecture diagrams and documentation
|
|
55895
|
+
|
|
55896
|
+
When analyzing architecture:
|
|
55897
|
+
- Use search/query/extract to understand component boundaries and dependencies
|
|
55898
|
+
- Identify layers, modules, and their responsibilities
|
|
55899
|
+
- Look for patterns like MVC, microservices, event-driven, etc.
|
|
55900
|
+
- Assess coupling, cohesion, and separation of concerns
|
|
55901
|
+
- Consider scalability, maintainability, and testability
|
|
55902
|
+
|
|
55903
|
+
When proposing changes:
|
|
55904
|
+
- Provide clear rationale backed by architectural principles
|
|
55905
|
+
- Consider migration paths and backwards compatibility
|
|
55906
|
+
- Identify risks and tradeoffs
|
|
55907
|
+
- Suggest incremental implementation steps`,
|
|
55908
|
+
"code-review": `You are ProbeChat Code Reviewer - a meticulous code reviewer focused on quality, best practices, and maintainability.
|
|
55909
|
+
|
|
55910
|
+
Your role is to:
|
|
55911
|
+
|
|
55912
|
+
1. Review code changes for correctness, clarity, and best practices
|
|
55913
|
+
2. Identify bugs, security issues, and performance problems
|
|
55914
|
+
3. Suggest improvements for readability and maintainability
|
|
55915
|
+
4. Ensure consistency with project conventions and patterns
|
|
55916
|
+
5. Verify test coverage and edge case handling
|
|
55917
|
+
|
|
55918
|
+
When reviewing code:
|
|
55919
|
+
- Use search to find similar patterns in the codebase for consistency
|
|
55920
|
+
- Look for common issues: null checks, error handling, resource leaks
|
|
55921
|
+
- Check for security vulnerabilities: injection, XSS, etc.
|
|
55922
|
+
- Assess complexity and suggest simplifications
|
|
55923
|
+
- Verify naming conventions and code organization
|
|
55924
|
+
|
|
55925
|
+
Provide constructive feedback:
|
|
55926
|
+
- Start with what's good about the code
|
|
55927
|
+
- Be specific about issues with examples
|
|
55928
|
+
- Suggest concrete improvements with code snippets
|
|
55929
|
+
- Prioritize critical issues over style preferences
|
|
55930
|
+
- Explain the "why" behind your suggestions`,
|
|
55931
|
+
"engineer": `You are a senior engineer who helps implement features and fix bugs.
|
|
55932
|
+
|
|
55933
|
+
Your role is to:
|
|
55934
|
+
|
|
55935
|
+
1. Implement new features following project conventions
|
|
55936
|
+
2. Fix bugs by understanding root causes
|
|
55937
|
+
3. Refactor code to improve quality
|
|
55938
|
+
4. Write clear, maintainable code
|
|
55939
|
+
5. Add appropriate tests and documentation
|
|
55940
|
+
|
|
55941
|
+
When implementing:
|
|
55942
|
+
- Use search/query to understand existing patterns
|
|
55943
|
+
- Follow the project's coding style and conventions
|
|
55944
|
+
- Consider edge cases and error handling
|
|
55945
|
+
- Write self-documenting code with clear names
|
|
55946
|
+
- Add comments for complex logic
|
|
55947
|
+
|
|
55948
|
+
You have access to:
|
|
55949
|
+
- search: Find relevant code patterns
|
|
55950
|
+
- query: Locate specific symbols/functions
|
|
55951
|
+
- extract: Get full file context
|
|
55952
|
+
- implement: Create or modify files (use carefully)
|
|
55953
|
+
- delegate: Break down complex tasks`,
|
|
55954
|
+
"support": `You are ProbeChat Support - a helpful assistant focused on answering questions about codebases.
|
|
55955
|
+
|
|
55956
|
+
Your role is to:
|
|
55957
|
+
|
|
55958
|
+
1. Answer questions about how code works
|
|
55959
|
+
2. Help users locate specific functionality
|
|
55960
|
+
3. Explain error messages and debugging approaches
|
|
55961
|
+
4. Guide users to relevant documentation
|
|
55962
|
+
5. Provide examples and usage patterns
|
|
55963
|
+
|
|
55964
|
+
When helping users:
|
|
55965
|
+
- Ask clarifying questions if the request is ambiguous
|
|
55966
|
+
- Use search/query to find relevant code quickly
|
|
55967
|
+
- Provide clear, step-by-step explanations
|
|
55968
|
+
- Include code examples when helpful
|
|
55969
|
+
- Point to relevant files and line numbers
|
|
55970
|
+
|
|
55971
|
+
You should be:
|
|
55972
|
+
- Patient and encouraging
|
|
55973
|
+
- Clear and concise
|
|
55974
|
+
- Thorough but not overwhelming
|
|
55975
|
+
- Honest about limitations (say "I don't know" when appropriate)`
|
|
55976
|
+
};
|
|
55977
|
+
}
|
|
55978
|
+
});
|
|
55979
|
+
|
|
55847
55980
|
// src/agent/mcp/config.js
|
|
55848
55981
|
import { readFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
55849
55982
|
import { join as join2, dirname as dirname3 } from "path";
|
|
@@ -57383,15 +57516,60 @@ var init_contextCompactor = __esm({
|
|
|
57383
57516
|
// src/agent/mcp/built-in-server.js
|
|
57384
57517
|
import { createServer } from "http";
|
|
57385
57518
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
57519
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
57386
57520
|
import { Server as MCPServer } from "@modelcontextprotocol/sdk/server/index.js";
|
|
57521
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
57522
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
57387
57523
|
import {
|
|
57388
57524
|
CallToolRequestSchema,
|
|
57389
|
-
ListToolsRequestSchema
|
|
57525
|
+
ListToolsRequestSchema,
|
|
57526
|
+
isInitializeRequest
|
|
57390
57527
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
57391
|
-
var BuiltInMCPServer;
|
|
57528
|
+
var InMemoryEventStore, BuiltInMCPServer;
|
|
57392
57529
|
var init_built_in_server = __esm({
|
|
57393
57530
|
"src/agent/mcp/built-in-server.js"() {
|
|
57394
57531
|
"use strict";
|
|
57532
|
+
InMemoryEventStore = class {
|
|
57533
|
+
constructor() {
|
|
57534
|
+
this.events = /* @__PURE__ */ new Map();
|
|
57535
|
+
}
|
|
57536
|
+
generateEventId(streamId) {
|
|
57537
|
+
return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
|
|
57538
|
+
}
|
|
57539
|
+
getStreamIdFromEventId(eventId) {
|
|
57540
|
+
const parts = eventId.split("_");
|
|
57541
|
+
return parts.length > 0 ? parts[0] : "";
|
|
57542
|
+
}
|
|
57543
|
+
async storeEvent(streamId, message) {
|
|
57544
|
+
const eventId = this.generateEventId(streamId);
|
|
57545
|
+
this.events.set(eventId, { streamId, message });
|
|
57546
|
+
return eventId;
|
|
57547
|
+
}
|
|
57548
|
+
async replayEventsAfter(lastEventId, { send }) {
|
|
57549
|
+
if (!lastEventId || !this.events.has(lastEventId)) {
|
|
57550
|
+
return "";
|
|
57551
|
+
}
|
|
57552
|
+
const streamId = this.getStreamIdFromEventId(lastEventId);
|
|
57553
|
+
if (!streamId) {
|
|
57554
|
+
return "";
|
|
57555
|
+
}
|
|
57556
|
+
let foundLastEvent = false;
|
|
57557
|
+
const sortedEvents = [...this.events.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
57558
|
+
for (const [eventId, { streamId: eventStreamId, message }] of sortedEvents) {
|
|
57559
|
+
if (eventStreamId !== streamId) {
|
|
57560
|
+
continue;
|
|
57561
|
+
}
|
|
57562
|
+
if (eventId === lastEventId) {
|
|
57563
|
+
foundLastEvent = true;
|
|
57564
|
+
continue;
|
|
57565
|
+
}
|
|
57566
|
+
if (foundLastEvent) {
|
|
57567
|
+
await send(eventId, message);
|
|
57568
|
+
}
|
|
57569
|
+
}
|
|
57570
|
+
return streamId;
|
|
57571
|
+
}
|
|
57572
|
+
};
|
|
57395
57573
|
BuiltInMCPServer = class extends EventEmitter3 {
|
|
57396
57574
|
constructor(agent, options = {}) {
|
|
57397
57575
|
super();
|
|
@@ -57400,6 +57578,8 @@ var init_built_in_server = __esm({
|
|
|
57400
57578
|
this.host = options.host || "127.0.0.1";
|
|
57401
57579
|
this.httpServer = null;
|
|
57402
57580
|
this.mcpServer = null;
|
|
57581
|
+
this.sseTransports = /* @__PURE__ */ new Map();
|
|
57582
|
+
this.streamableTransports = /* @__PURE__ */ new Map();
|
|
57403
57583
|
this.connections = /* @__PURE__ */ new Set();
|
|
57404
57584
|
this.debug = options.debug || false;
|
|
57405
57585
|
}
|
|
@@ -57421,11 +57601,13 @@ var init_built_in_server = __esm({
|
|
|
57421
57601
|
});
|
|
57422
57602
|
this.registerHandlers();
|
|
57423
57603
|
return new Promise((resolve6, reject2) => {
|
|
57424
|
-
this.httpServer.listen(this.port, this.host, () => {
|
|
57604
|
+
this.httpServer.listen(this.port, this.host, async () => {
|
|
57425
57605
|
const address = this.httpServer.address();
|
|
57426
57606
|
this.port = address.port;
|
|
57427
57607
|
if (this.debug) {
|
|
57428
57608
|
console.log(`[MCP] Built-in server started at http://${this.host}:${this.port}`);
|
|
57609
|
+
console.log(`[MCP] SSE endpoint: http://${this.host}:${this.port}/sse`);
|
|
57610
|
+
console.log(`[MCP] Messages endpoint: http://${this.host}:${this.port}/messages`);
|
|
57429
57611
|
}
|
|
57430
57612
|
this.emit("ready", { host: this.host, port: this.port });
|
|
57431
57613
|
resolve6({ host: this.host, port: this.port });
|
|
@@ -57438,6 +57620,9 @@ var init_built_in_server = __esm({
|
|
|
57438
57620
|
*/
|
|
57439
57621
|
handleRequest(req, res) {
|
|
57440
57622
|
const { method, url } = req;
|
|
57623
|
+
if (this.debug) {
|
|
57624
|
+
console.log(`[MCP] Request: ${method} ${url}`);
|
|
57625
|
+
}
|
|
57441
57626
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
57442
57627
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
57443
57628
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
@@ -57447,15 +57632,22 @@ var init_built_in_server = __esm({
|
|
|
57447
57632
|
return;
|
|
57448
57633
|
}
|
|
57449
57634
|
if (url === "/sse" && method === "GET") {
|
|
57450
|
-
this.
|
|
57635
|
+
if (this.debug) {
|
|
57636
|
+
console.log("[MCP] Routing to handleSSEConnection");
|
|
57637
|
+
}
|
|
57638
|
+
this.handleSSEConnection(req, res);
|
|
57639
|
+
return;
|
|
57640
|
+
}
|
|
57641
|
+
if (url.startsWith("/messages") && method === "POST") {
|
|
57642
|
+
this.handleSSEMessage(req, res);
|
|
57451
57643
|
return;
|
|
57452
57644
|
}
|
|
57453
57645
|
if (url === "/rpc" && method === "POST") {
|
|
57454
57646
|
this.handleJSONRPC(req, res);
|
|
57455
57647
|
return;
|
|
57456
57648
|
}
|
|
57457
|
-
if (url === "/mcp"
|
|
57458
|
-
this.
|
|
57649
|
+
if (url === "/mcp") {
|
|
57650
|
+
this.handleStreamableHTTP(req, res);
|
|
57459
57651
|
return;
|
|
57460
57652
|
}
|
|
57461
57653
|
if (url === "/health") {
|
|
@@ -57471,7 +57663,190 @@ var init_built_in_server = __esm({
|
|
|
57471
57663
|
res.end("Not Found");
|
|
57472
57664
|
}
|
|
57473
57665
|
/**
|
|
57474
|
-
* Handle
|
|
57666
|
+
* Handle SSE connection (GET /sse) - creates new transport
|
|
57667
|
+
*/
|
|
57668
|
+
async handleSSEConnection(req, res) {
|
|
57669
|
+
if (this.debug) {
|
|
57670
|
+
console.log("[MCP] New SSE connection request");
|
|
57671
|
+
}
|
|
57672
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
57673
|
+
this.sseTransports.set(transport.sessionId, transport);
|
|
57674
|
+
res.on("close", () => {
|
|
57675
|
+
if (this.debug) {
|
|
57676
|
+
console.log("[MCP] SSE connection closed, sessionId:", transport.sessionId);
|
|
57677
|
+
}
|
|
57678
|
+
this.sseTransports.delete(transport.sessionId);
|
|
57679
|
+
});
|
|
57680
|
+
try {
|
|
57681
|
+
await this.mcpServer.connect(transport);
|
|
57682
|
+
if (this.debug) {
|
|
57683
|
+
console.log("[MCP] MCP server connected to SSE transport, sessionId:", transport.sessionId);
|
|
57684
|
+
}
|
|
57685
|
+
} catch (error) {
|
|
57686
|
+
if (this.debug) {
|
|
57687
|
+
console.error("[MCP] Error connecting MCP server to transport:", error);
|
|
57688
|
+
}
|
|
57689
|
+
this.sseTransports.delete(transport.sessionId);
|
|
57690
|
+
}
|
|
57691
|
+
}
|
|
57692
|
+
/**
|
|
57693
|
+
* Handle SSE message (POST /messages?sessionId=...) - routes to existing transport
|
|
57694
|
+
*/
|
|
57695
|
+
async handleSSEMessage(req, res) {
|
|
57696
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
57697
|
+
const sessionId = url.searchParams.get("sessionId");
|
|
57698
|
+
if (!sessionId) {
|
|
57699
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
57700
|
+
res.end(JSON.stringify({
|
|
57701
|
+
jsonrpc: "2.0",
|
|
57702
|
+
error: {
|
|
57703
|
+
code: -32e3,
|
|
57704
|
+
message: "Bad Request: sessionId query parameter is required"
|
|
57705
|
+
},
|
|
57706
|
+
id: null
|
|
57707
|
+
}));
|
|
57708
|
+
return;
|
|
57709
|
+
}
|
|
57710
|
+
const transport = this.sseTransports.get(sessionId);
|
|
57711
|
+
if (!transport) {
|
|
57712
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
57713
|
+
res.end(JSON.stringify({
|
|
57714
|
+
jsonrpc: "2.0",
|
|
57715
|
+
error: {
|
|
57716
|
+
code: -32e3,
|
|
57717
|
+
message: `Bad Request: No transport found for sessionId: ${sessionId}`
|
|
57718
|
+
},
|
|
57719
|
+
id: null
|
|
57720
|
+
}));
|
|
57721
|
+
return;
|
|
57722
|
+
}
|
|
57723
|
+
let body = "";
|
|
57724
|
+
req.on("data", (chunk) => {
|
|
57725
|
+
body += chunk.toString();
|
|
57726
|
+
});
|
|
57727
|
+
req.on("end", async () => {
|
|
57728
|
+
try {
|
|
57729
|
+
const message = JSON.parse(body);
|
|
57730
|
+
await transport.handlePostMessage(req, res, message);
|
|
57731
|
+
} catch (error) {
|
|
57732
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
57733
|
+
res.end(JSON.stringify({
|
|
57734
|
+
jsonrpc: "2.0",
|
|
57735
|
+
error: {
|
|
57736
|
+
code: -32603,
|
|
57737
|
+
message: "Internal error",
|
|
57738
|
+
data: error.message
|
|
57739
|
+
},
|
|
57740
|
+
id: null
|
|
57741
|
+
}));
|
|
57742
|
+
}
|
|
57743
|
+
});
|
|
57744
|
+
}
|
|
57745
|
+
/**
|
|
57746
|
+
* Handle Streamable HTTP protocol (GET/POST/DELETE on /mcp)
|
|
57747
|
+
*/
|
|
57748
|
+
async handleStreamableHTTP(req, res) {
|
|
57749
|
+
const { method } = req;
|
|
57750
|
+
if (this.debug) {
|
|
57751
|
+
console.log(`[MCP] Streamable HTTP ${method} request`);
|
|
57752
|
+
}
|
|
57753
|
+
try {
|
|
57754
|
+
let body = null;
|
|
57755
|
+
if (method === "POST") {
|
|
57756
|
+
body = await this.parseRequestBody(req);
|
|
57757
|
+
}
|
|
57758
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
57759
|
+
let transport;
|
|
57760
|
+
if (sessionId && this.streamableTransports.has(sessionId)) {
|
|
57761
|
+
transport = this.streamableTransports.get(sessionId);
|
|
57762
|
+
if (this.debug) {
|
|
57763
|
+
console.log(`[MCP] Reusing existing transport for session: ${sessionId}`);
|
|
57764
|
+
}
|
|
57765
|
+
} else if (!sessionId && method === "POST" && body && isInitializeRequest(body)) {
|
|
57766
|
+
if (this.debug) {
|
|
57767
|
+
console.log("[MCP] Creating new Streamable HTTP transport for initialization");
|
|
57768
|
+
}
|
|
57769
|
+
const eventStore = new InMemoryEventStore();
|
|
57770
|
+
transport = new StreamableHTTPServerTransport({
|
|
57771
|
+
sessionIdGenerator: () => randomUUID4(),
|
|
57772
|
+
eventStore,
|
|
57773
|
+
// Enable resumability
|
|
57774
|
+
onsessioninitialized: (newSessionId) => {
|
|
57775
|
+
if (this.debug) {
|
|
57776
|
+
console.log(`[MCP] Streamable HTTP session initialized: ${newSessionId}`);
|
|
57777
|
+
}
|
|
57778
|
+
this.streamableTransports.set(newSessionId, transport);
|
|
57779
|
+
},
|
|
57780
|
+
onsessionclosed: (closedSessionId) => {
|
|
57781
|
+
if (this.debug) {
|
|
57782
|
+
console.log(`[MCP] Streamable HTTP session closed: ${closedSessionId}`);
|
|
57783
|
+
}
|
|
57784
|
+
this.streamableTransports.delete(closedSessionId);
|
|
57785
|
+
}
|
|
57786
|
+
});
|
|
57787
|
+
transport.onclose = () => {
|
|
57788
|
+
const sid = transport.sessionId;
|
|
57789
|
+
if (sid && this.streamableTransports.has(sid)) {
|
|
57790
|
+
if (this.debug) {
|
|
57791
|
+
console.log(`[MCP] Transport closed for session ${sid}`);
|
|
57792
|
+
}
|
|
57793
|
+
this.streamableTransports.delete(sid);
|
|
57794
|
+
}
|
|
57795
|
+
};
|
|
57796
|
+
await this.mcpServer.connect(transport);
|
|
57797
|
+
} else {
|
|
57798
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
57799
|
+
res.end(JSON.stringify({
|
|
57800
|
+
jsonrpc: "2.0",
|
|
57801
|
+
error: {
|
|
57802
|
+
code: -32e3,
|
|
57803
|
+
message: "Bad Request: No valid session ID provided or not an initialization request"
|
|
57804
|
+
},
|
|
57805
|
+
id: null
|
|
57806
|
+
}));
|
|
57807
|
+
return;
|
|
57808
|
+
}
|
|
57809
|
+
await transport.handleRequest(req, res, body);
|
|
57810
|
+
} catch (error) {
|
|
57811
|
+
if (this.debug) {
|
|
57812
|
+
console.error("[MCP] Error handling Streamable HTTP request:", error);
|
|
57813
|
+
}
|
|
57814
|
+
if (!res.headersSent) {
|
|
57815
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
57816
|
+
res.end(JSON.stringify({
|
|
57817
|
+
jsonrpc: "2.0",
|
|
57818
|
+
error: {
|
|
57819
|
+
code: -32603,
|
|
57820
|
+
message: "Internal server error",
|
|
57821
|
+
data: error.message
|
|
57822
|
+
},
|
|
57823
|
+
id: null
|
|
57824
|
+
}));
|
|
57825
|
+
}
|
|
57826
|
+
}
|
|
57827
|
+
}
|
|
57828
|
+
/**
|
|
57829
|
+
* Parse request body as JSON
|
|
57830
|
+
*/
|
|
57831
|
+
async parseRequestBody(req) {
|
|
57832
|
+
return new Promise((resolve6, reject2) => {
|
|
57833
|
+
let body = "";
|
|
57834
|
+
req.on("data", (chunk) => {
|
|
57835
|
+
body += chunk.toString();
|
|
57836
|
+
});
|
|
57837
|
+
req.on("end", () => {
|
|
57838
|
+
try {
|
|
57839
|
+
const parsed = body ? JSON.parse(body) : null;
|
|
57840
|
+
resolve6(parsed);
|
|
57841
|
+
} catch (error) {
|
|
57842
|
+
reject2(error);
|
|
57843
|
+
}
|
|
57844
|
+
});
|
|
57845
|
+
req.on("error", reject2);
|
|
57846
|
+
});
|
|
57847
|
+
}
|
|
57848
|
+
/**
|
|
57849
|
+
* Handle Server-Sent Events connection (DEPRECATED - use handleSSEConnection instead)
|
|
57475
57850
|
*/
|
|
57476
57851
|
handleSSE(req, res) {
|
|
57477
57852
|
res.writeHead(200, {
|
|
@@ -57738,6 +58113,32 @@ data: ${JSON.stringify(data)}
|
|
|
57738
58113
|
* Stop the server
|
|
57739
58114
|
*/
|
|
57740
58115
|
async stop() {
|
|
58116
|
+
for (const [sessionId, transport] of this.streamableTransports.entries()) {
|
|
58117
|
+
try {
|
|
58118
|
+
await transport.close();
|
|
58119
|
+
if (this.debug) {
|
|
58120
|
+
console.log(`[MCP] Closed Streamable HTTP transport for session: ${sessionId}`);
|
|
58121
|
+
}
|
|
58122
|
+
} catch (error) {
|
|
58123
|
+
if (this.debug) {
|
|
58124
|
+
console.error(`[MCP] Error closing Streamable HTTP transport ${sessionId}:`, error);
|
|
58125
|
+
}
|
|
58126
|
+
}
|
|
58127
|
+
}
|
|
58128
|
+
this.streamableTransports.clear();
|
|
58129
|
+
for (const [sessionId, transport] of this.sseTransports.entries()) {
|
|
58130
|
+
try {
|
|
58131
|
+
await transport.close();
|
|
58132
|
+
if (this.debug) {
|
|
58133
|
+
console.log(`[MCP] Closed SSE transport for session: ${sessionId}`);
|
|
58134
|
+
}
|
|
58135
|
+
} catch (error) {
|
|
58136
|
+
if (this.debug) {
|
|
58137
|
+
console.error(`[MCP] Error closing SSE transport ${sessionId}:`, error);
|
|
58138
|
+
}
|
|
58139
|
+
}
|
|
58140
|
+
}
|
|
58141
|
+
this.sseTransports.clear();
|
|
57741
58142
|
for (const connection of this.connections) {
|
|
57742
58143
|
connection.end();
|
|
57743
58144
|
}
|
|
@@ -57769,6 +58170,59 @@ data: ${JSON.stringify(data)}
|
|
|
57769
58170
|
}
|
|
57770
58171
|
});
|
|
57771
58172
|
|
|
58173
|
+
// src/agent/shared/Session.js
|
|
58174
|
+
var Session;
|
|
58175
|
+
var init_Session = __esm({
|
|
58176
|
+
"src/agent/shared/Session.js"() {
|
|
58177
|
+
"use strict";
|
|
58178
|
+
Session = class {
|
|
58179
|
+
constructor(id, debug = false) {
|
|
58180
|
+
this.id = id;
|
|
58181
|
+
this.conversationId = null;
|
|
58182
|
+
this.messageCount = 0;
|
|
58183
|
+
this.debug = debug;
|
|
58184
|
+
}
|
|
58185
|
+
/**
|
|
58186
|
+
* Set the conversation ID for session resumption
|
|
58187
|
+
* @param {string} conversationId - Provider's conversation/thread ID
|
|
58188
|
+
*/
|
|
58189
|
+
setConversationId(conversationId) {
|
|
58190
|
+
this.conversationId = conversationId;
|
|
58191
|
+
if (this.debug) {
|
|
58192
|
+
console.log(`[Session ${this.id}] Conversation ID: ${conversationId}`);
|
|
58193
|
+
}
|
|
58194
|
+
}
|
|
58195
|
+
/**
|
|
58196
|
+
* Increment the message count
|
|
58197
|
+
*/
|
|
58198
|
+
incrementMessageCount() {
|
|
58199
|
+
this.messageCount++;
|
|
58200
|
+
}
|
|
58201
|
+
/**
|
|
58202
|
+
* Get session info as plain object
|
|
58203
|
+
* @returns {Object} Session information
|
|
58204
|
+
*/
|
|
58205
|
+
getInfo() {
|
|
58206
|
+
return {
|
|
58207
|
+
id: this.id,
|
|
58208
|
+
conversationId: this.conversationId,
|
|
58209
|
+
messageCount: this.messageCount
|
|
58210
|
+
};
|
|
58211
|
+
}
|
|
58212
|
+
/**
|
|
58213
|
+
* Get resume arguments for CLI commands (used by Claude Code)
|
|
58214
|
+
* @returns {Array<string>} CLI arguments for resuming conversation
|
|
58215
|
+
*/
|
|
58216
|
+
getResumeArgs() {
|
|
58217
|
+
if (this.conversationId && this.messageCount > 0) {
|
|
58218
|
+
return ["--resume", this.conversationId];
|
|
58219
|
+
}
|
|
58220
|
+
return [];
|
|
58221
|
+
}
|
|
58222
|
+
};
|
|
58223
|
+
}
|
|
58224
|
+
});
|
|
58225
|
+
|
|
57772
58226
|
// src/agent/engines/enhanced-claude-code.js
|
|
57773
58227
|
var enhanced_claude_code_exports = {};
|
|
57774
58228
|
__export(enhanced_claude_code_exports, {
|
|
@@ -57782,7 +58236,7 @@ import os3 from "os";
|
|
|
57782
58236
|
import { EventEmitter as EventEmitter4 } from "events";
|
|
57783
58237
|
async function createEnhancedClaudeCLIEngine(options = {}) {
|
|
57784
58238
|
const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools } = options;
|
|
57785
|
-
const session = new
|
|
58239
|
+
const session = new Session(
|
|
57786
58240
|
sessionId || randomBytes(8).toString("hex"),
|
|
57787
58241
|
debug
|
|
57788
58242
|
);
|
|
@@ -57993,11 +58447,7 @@ ${opts.schema}`;
|
|
|
57993
58447
|
* Get session info
|
|
57994
58448
|
*/
|
|
57995
58449
|
getSession() {
|
|
57996
|
-
return
|
|
57997
|
-
id: session.id,
|
|
57998
|
-
conversationId: session.conversationId,
|
|
57999
|
-
messageCount: session.messageCount
|
|
58000
|
-
};
|
|
58450
|
+
return session.getInfo();
|
|
58001
58451
|
},
|
|
58002
58452
|
/**
|
|
58003
58453
|
* Clean up - MUST be called to stop MCP server and clean resources
|
|
@@ -58178,40 +58628,285 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
|
|
|
58178
58628
|
}
|
|
58179
58629
|
return systemPrompt || "";
|
|
58180
58630
|
}
|
|
58181
|
-
var ClaudeSession;
|
|
58182
58631
|
var init_enhanced_claude_code = __esm({
|
|
58183
58632
|
"src/agent/engines/enhanced-claude-code.js"() {
|
|
58184
58633
|
"use strict";
|
|
58185
58634
|
init_built_in_server();
|
|
58186
|
-
|
|
58187
|
-
|
|
58188
|
-
|
|
58189
|
-
|
|
58190
|
-
|
|
58191
|
-
|
|
58635
|
+
init_Session();
|
|
58636
|
+
}
|
|
58637
|
+
});
|
|
58638
|
+
|
|
58639
|
+
// src/agent/engines/codex.js
|
|
58640
|
+
var codex_exports = {};
|
|
58641
|
+
__export(codex_exports, {
|
|
58642
|
+
createCodexEngine: () => createCodexEngine
|
|
58643
|
+
});
|
|
58644
|
+
import { spawn as spawn4 } from "child_process";
|
|
58645
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
58646
|
+
import { createInterface } from "readline";
|
|
58647
|
+
async function createCodexEngine(options = {}) {
|
|
58648
|
+
const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, model } = options;
|
|
58649
|
+
const session = new Session(
|
|
58650
|
+
sessionId || randomBytes2(8).toString("hex"),
|
|
58651
|
+
debug
|
|
58652
|
+
);
|
|
58653
|
+
let mcpServer = null;
|
|
58654
|
+
let mcpServerUrl = null;
|
|
58655
|
+
let mcpServerName = null;
|
|
58656
|
+
if (agent) {
|
|
58657
|
+
mcpServer = new BuiltInMCPServer(agent, {
|
|
58658
|
+
port: 0,
|
|
58659
|
+
host: "127.0.0.1",
|
|
58660
|
+
debug
|
|
58661
|
+
});
|
|
58662
|
+
const { host, port } = await mcpServer.start();
|
|
58663
|
+
mcpServerUrl = `http://${host}:${port}/mcp`;
|
|
58664
|
+
mcpServerName = `probe_${session.id}`;
|
|
58665
|
+
if (debug) {
|
|
58666
|
+
console.log("[DEBUG] Built-in Probe MCP server started");
|
|
58667
|
+
console.log("[DEBUG] Probe MCP URL:", mcpServerUrl);
|
|
58668
|
+
}
|
|
58669
|
+
}
|
|
58670
|
+
if (debug) {
|
|
58671
|
+
console.log("[DEBUG] Starting Codex MCP server...");
|
|
58672
|
+
}
|
|
58673
|
+
const codexProcess = spawn4("codex", ["mcp-server"], {
|
|
58674
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
58675
|
+
});
|
|
58676
|
+
let requestId = 0;
|
|
58677
|
+
const pendingRequests = /* @__PURE__ */ new Map();
|
|
58678
|
+
const eventHandlers = /* @__PURE__ */ new Map();
|
|
58679
|
+
const stdoutReader = createInterface({
|
|
58680
|
+
input: codexProcess.stdout,
|
|
58681
|
+
crlfDelay: Infinity
|
|
58682
|
+
});
|
|
58683
|
+
stdoutReader.on("line", (line) => {
|
|
58684
|
+
try {
|
|
58685
|
+
const message = JSON.parse(line);
|
|
58686
|
+
if (debug) {
|
|
58687
|
+
if (message.method === "codex/event") {
|
|
58688
|
+
console.log(`[DEBUG] Codex event: ${message.params?.msg?.type}`);
|
|
58689
|
+
}
|
|
58192
58690
|
}
|
|
58193
|
-
|
|
58194
|
-
|
|
58195
|
-
|
|
58196
|
-
|
|
58197
|
-
|
|
58198
|
-
|
|
58199
|
-
|
|
58691
|
+
if (message.id !== void 0 && pendingRequests.has(message.id)) {
|
|
58692
|
+
const { resolve: resolve6, reject: reject2 } = pendingRequests.get(message.id);
|
|
58693
|
+
pendingRequests.delete(message.id);
|
|
58694
|
+
if (message.error) {
|
|
58695
|
+
reject2(new Error(message.error.message || JSON.stringify(message.error)));
|
|
58696
|
+
} else {
|
|
58697
|
+
resolve6(message.result);
|
|
58200
58698
|
}
|
|
58201
58699
|
}
|
|
58202
|
-
|
|
58203
|
-
|
|
58204
|
-
|
|
58205
|
-
|
|
58206
|
-
if (this.conversationId && this.messageCount > 0) {
|
|
58207
|
-
return ["--resume", this.conversationId];
|
|
58700
|
+
if (message.method === "codex/event" && message.params) {
|
|
58701
|
+
const requestId2 = message.params._meta?.requestId;
|
|
58702
|
+
if (requestId2 !== void 0 && eventHandlers.has(requestId2)) {
|
|
58703
|
+
eventHandlers.get(requestId2)(message.params);
|
|
58208
58704
|
}
|
|
58209
|
-
return [];
|
|
58210
58705
|
}
|
|
58211
|
-
|
|
58212
|
-
|
|
58706
|
+
} catch (e) {
|
|
58707
|
+
if (debug) {
|
|
58708
|
+
console.error("[DEBUG] Failed to parse message:", line);
|
|
58213
58709
|
}
|
|
58214
|
-
}
|
|
58710
|
+
}
|
|
58711
|
+
});
|
|
58712
|
+
if (debug) {
|
|
58713
|
+
codexProcess.stderr.on("data", (data) => {
|
|
58714
|
+
console.error("[CODEX STDERR]", data.toString());
|
|
58715
|
+
});
|
|
58716
|
+
}
|
|
58717
|
+
function sendRequest(method, params = {}) {
|
|
58718
|
+
return new Promise((resolve6, reject2) => {
|
|
58719
|
+
const id = ++requestId;
|
|
58720
|
+
const request = {
|
|
58721
|
+
jsonrpc: "2.0",
|
|
58722
|
+
id,
|
|
58723
|
+
method,
|
|
58724
|
+
params
|
|
58725
|
+
};
|
|
58726
|
+
pendingRequests.set(id, { resolve: resolve6, reject: reject2 });
|
|
58727
|
+
setTimeout(() => {
|
|
58728
|
+
if (pendingRequests.has(id)) {
|
|
58729
|
+
pendingRequests.delete(id);
|
|
58730
|
+
reject2(new Error(`Request ${method} timed out after 10 minutes`));
|
|
58731
|
+
}
|
|
58732
|
+
}, 6e5);
|
|
58733
|
+
codexProcess.stdin.write(JSON.stringify(request) + "\n");
|
|
58734
|
+
});
|
|
58735
|
+
}
|
|
58736
|
+
await sendRequest("initialize", {
|
|
58737
|
+
protocolVersion: "2024-11-05",
|
|
58738
|
+
capabilities: { tools: {} },
|
|
58739
|
+
clientInfo: {
|
|
58740
|
+
name: "probe-codex-client",
|
|
58741
|
+
version: "1.0.0"
|
|
58742
|
+
}
|
|
58743
|
+
});
|
|
58744
|
+
if (debug) {
|
|
58745
|
+
console.log("[DEBUG] Connected to Codex MCP server");
|
|
58746
|
+
console.log("[DEBUG] Session:", session.id);
|
|
58747
|
+
}
|
|
58748
|
+
const fullPrompt = combinePrompts2(systemPrompt, customPrompt, agent);
|
|
58749
|
+
return {
|
|
58750
|
+
sessionId: session.id,
|
|
58751
|
+
session,
|
|
58752
|
+
/**
|
|
58753
|
+
* Query Codex via MCP protocol with event streaming
|
|
58754
|
+
*/
|
|
58755
|
+
async *query(prompt, opts = {}) {
|
|
58756
|
+
let finalPrompt = prompt;
|
|
58757
|
+
if (!session.conversationId && fullPrompt) {
|
|
58758
|
+
finalPrompt = `${fullPrompt}
|
|
58759
|
+
|
|
58760
|
+
${prompt}`;
|
|
58761
|
+
}
|
|
58762
|
+
const isFollowUp = session.conversationId !== null;
|
|
58763
|
+
const toolName = isFollowUp ? "codex-reply" : "codex";
|
|
58764
|
+
const toolArgs = { prompt: finalPrompt };
|
|
58765
|
+
if (isFollowUp) {
|
|
58766
|
+
toolArgs.conversationId = session.conversationId;
|
|
58767
|
+
if (debug) {
|
|
58768
|
+
console.log(`[DEBUG] Follow-up with conversationId: ${session.conversationId}`);
|
|
58769
|
+
}
|
|
58770
|
+
} else {
|
|
58771
|
+
if (model) {
|
|
58772
|
+
toolArgs.model = model;
|
|
58773
|
+
}
|
|
58774
|
+
if (mcpServerUrl && mcpServerName) {
|
|
58775
|
+
toolArgs.config = {
|
|
58776
|
+
mcp_servers: {
|
|
58777
|
+
[mcpServerName]: { url: mcpServerUrl }
|
|
58778
|
+
}
|
|
58779
|
+
};
|
|
58780
|
+
}
|
|
58781
|
+
if (debug) {
|
|
58782
|
+
console.log(`[DEBUG] Initial query with tool: ${toolName}`);
|
|
58783
|
+
}
|
|
58784
|
+
}
|
|
58785
|
+
try {
|
|
58786
|
+
const reqId = requestId + 1;
|
|
58787
|
+
let fullResponse = "";
|
|
58788
|
+
let gotSessionId = false;
|
|
58789
|
+
const eventPromise = new Promise((resolve6) => {
|
|
58790
|
+
eventHandlers.set(reqId, (eventParams) => {
|
|
58791
|
+
const msg = eventParams.msg;
|
|
58792
|
+
if (msg.type === "session_configured" && msg.session_id && !gotSessionId) {
|
|
58793
|
+
session.setConversationId(msg.session_id);
|
|
58794
|
+
gotSessionId = true;
|
|
58795
|
+
}
|
|
58796
|
+
if (msg.type === "raw_response_item" && msg.item?.role === "assistant") {
|
|
58797
|
+
const content = msg.item.content;
|
|
58798
|
+
if (Array.isArray(content)) {
|
|
58799
|
+
for (const part of content) {
|
|
58800
|
+
if (part.type === "text" && part.text) {
|
|
58801
|
+
fullResponse += part.text;
|
|
58802
|
+
}
|
|
58803
|
+
}
|
|
58804
|
+
}
|
|
58805
|
+
}
|
|
58806
|
+
});
|
|
58807
|
+
setTimeout(() => {
|
|
58808
|
+
eventHandlers.delete(reqId);
|
|
58809
|
+
resolve6();
|
|
58810
|
+
}, 6e5);
|
|
58811
|
+
});
|
|
58812
|
+
const resultPromise = sendRequest("tools/call", {
|
|
58813
|
+
name: toolName,
|
|
58814
|
+
arguments: toolArgs
|
|
58815
|
+
});
|
|
58816
|
+
const result = await resultPromise;
|
|
58817
|
+
eventHandlers.delete(reqId);
|
|
58818
|
+
if (result && result.content && Array.isArray(result.content)) {
|
|
58819
|
+
for (const item of result.content) {
|
|
58820
|
+
if (item.type === "text" && item.text) {
|
|
58821
|
+
yield {
|
|
58822
|
+
type: "text",
|
|
58823
|
+
content: item.text
|
|
58824
|
+
};
|
|
58825
|
+
fullResponse = item.text;
|
|
58826
|
+
}
|
|
58827
|
+
}
|
|
58828
|
+
}
|
|
58829
|
+
if (fullResponse && (!result.content || result.content.length === 0)) {
|
|
58830
|
+
yield {
|
|
58831
|
+
type: "text",
|
|
58832
|
+
content: fullResponse
|
|
58833
|
+
};
|
|
58834
|
+
}
|
|
58835
|
+
session.incrementMessageCount();
|
|
58836
|
+
yield {
|
|
58837
|
+
type: "metadata",
|
|
58838
|
+
data: {
|
|
58839
|
+
sessionId: session.id,
|
|
58840
|
+
conversationId: session.conversationId,
|
|
58841
|
+
messageCount: session.messageCount
|
|
58842
|
+
}
|
|
58843
|
+
};
|
|
58844
|
+
} catch (error) {
|
|
58845
|
+
if (debug) {
|
|
58846
|
+
console.error("[DEBUG] Codex query error:", error);
|
|
58847
|
+
}
|
|
58848
|
+
yield {
|
|
58849
|
+
type: "error",
|
|
58850
|
+
error
|
|
58851
|
+
};
|
|
58852
|
+
}
|
|
58853
|
+
},
|
|
58854
|
+
/**
|
|
58855
|
+
* Get session info
|
|
58856
|
+
*/
|
|
58857
|
+
getSession() {
|
|
58858
|
+
return session.getInfo();
|
|
58859
|
+
},
|
|
58860
|
+
/**
|
|
58861
|
+
* Clean up resources
|
|
58862
|
+
*/
|
|
58863
|
+
async close() {
|
|
58864
|
+
try {
|
|
58865
|
+
if (stdoutReader) {
|
|
58866
|
+
stdoutReader.close();
|
|
58867
|
+
if (debug) {
|
|
58868
|
+
console.log("[DEBUG] Closed stdout reader");
|
|
58869
|
+
}
|
|
58870
|
+
}
|
|
58871
|
+
pendingRequests.clear();
|
|
58872
|
+
eventHandlers.clear();
|
|
58873
|
+
if (codexProcess && !codexProcess.killed) {
|
|
58874
|
+
codexProcess.kill();
|
|
58875
|
+
if (debug) {
|
|
58876
|
+
console.log("[DEBUG] Killed Codex MCP server process");
|
|
58877
|
+
}
|
|
58878
|
+
}
|
|
58879
|
+
if (mcpServer) {
|
|
58880
|
+
await mcpServer.stop();
|
|
58881
|
+
if (debug) {
|
|
58882
|
+
console.log("[DEBUG] Stopped Probe MCP server");
|
|
58883
|
+
}
|
|
58884
|
+
}
|
|
58885
|
+
if (debug) {
|
|
58886
|
+
console.log("[DEBUG] Engine closed, session:", session.id);
|
|
58887
|
+
}
|
|
58888
|
+
} catch (error) {
|
|
58889
|
+
if (debug) {
|
|
58890
|
+
console.error("[DEBUG] Error during cleanup:", error.message);
|
|
58891
|
+
}
|
|
58892
|
+
}
|
|
58893
|
+
}
|
|
58894
|
+
};
|
|
58895
|
+
}
|
|
58896
|
+
function combinePrompts2(systemPrompt, customPrompt, agent) {
|
|
58897
|
+
if (!systemPrompt && customPrompt) {
|
|
58898
|
+
return customPrompt;
|
|
58899
|
+
}
|
|
58900
|
+
if (systemPrompt && customPrompt) {
|
|
58901
|
+
return systemPrompt + "\n\n## Additional Instructions\n" + customPrompt;
|
|
58902
|
+
}
|
|
58903
|
+
return systemPrompt || "";
|
|
58904
|
+
}
|
|
58905
|
+
var init_codex = __esm({
|
|
58906
|
+
"src/agent/engines/codex.js"() {
|
|
58907
|
+
"use strict";
|
|
58908
|
+
init_built_in_server();
|
|
58909
|
+
init_Session();
|
|
58215
58910
|
}
|
|
58216
58911
|
});
|
|
58217
58912
|
|
|
@@ -58294,7 +58989,7 @@ import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
|
|
|
58294
58989
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
58295
58990
|
import { createAmazonBedrock as createAmazonBedrock2 } from "@ai-sdk/amazon-bedrock";
|
|
58296
58991
|
import { streamText as streamText2 } from "ai";
|
|
58297
|
-
import { randomUUID as
|
|
58992
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
58298
58993
|
import { EventEmitter as EventEmitter5 } from "events";
|
|
58299
58994
|
import { existsSync as existsSync5 } from "fs";
|
|
58300
58995
|
import { readFile, stat } from "fs/promises";
|
|
@@ -58314,6 +59009,7 @@ var init_ProbeAgent = __esm({
|
|
|
58314
59009
|
init_index();
|
|
58315
59010
|
init_schemaUtils();
|
|
58316
59011
|
init_xmlParsingUtils();
|
|
59012
|
+
init_prompts();
|
|
58317
59013
|
init_mcp();
|
|
58318
59014
|
init_RetryManager();
|
|
58319
59015
|
init_FallbackManager();
|
|
@@ -58335,6 +59031,7 @@ var init_ProbeAgent = __esm({
|
|
|
58335
59031
|
* @param {Object} options - Configuration options
|
|
58336
59032
|
* @param {string} [options.sessionId] - Optional session ID
|
|
58337
59033
|
* @param {string} [options.customPrompt] - Custom prompt to replace the default system message
|
|
59034
|
+
* @param {string} [options.systemPrompt] - Alias for customPrompt; takes precedence when both are provided
|
|
58338
59035
|
* @param {string} [options.promptType] - Predefined prompt type (architect, code-review, support)
|
|
58339
59036
|
* @param {boolean} [options.allowEdit=false] - Allow the use of the 'implement' tool
|
|
58340
59037
|
* @param {boolean} [options.enableDelegate=false] - Enable the delegate tool for task distribution to subagents
|
|
@@ -58369,8 +59066,8 @@ var init_ProbeAgent = __esm({
|
|
|
58369
59066
|
* @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
|
|
58370
59067
|
*/
|
|
58371
59068
|
constructor(options = {}) {
|
|
58372
|
-
this.sessionId = options.sessionId ||
|
|
58373
|
-
this.customPrompt = options.customPrompt || null;
|
|
59069
|
+
this.sessionId = options.sessionId || randomUUID5();
|
|
59070
|
+
this.customPrompt = options.systemPrompt || options.customPrompt || null;
|
|
58374
59071
|
this.promptType = options.promptType || "code-explorer";
|
|
58375
59072
|
this.allowEdit = !!options.allowEdit;
|
|
58376
59073
|
this.enableDelegate = !!options.enableDelegate;
|
|
@@ -58494,9 +59191,10 @@ var init_ProbeAgent = __esm({
|
|
|
58494
59191
|
* This method initializes MCP and merges MCP tools into the tool list, and loads history from storage
|
|
58495
59192
|
*/
|
|
58496
59193
|
async initialize() {
|
|
58497
|
-
if (!this.provider && !this.clientApiProvider && this.apiType !== "claude-code") {
|
|
59194
|
+
if (!this.provider && !this.clientApiProvider && this.apiType !== "claude-code" && this.apiType !== "codex") {
|
|
58498
59195
|
if (this.apiType === "uninitialized") {
|
|
58499
59196
|
const claudeAvailable = await this.isClaudeCommandAvailable();
|
|
59197
|
+
const codexAvailable = await this.isCodexCommandAvailable();
|
|
58500
59198
|
if (claudeAvailable) {
|
|
58501
59199
|
if (this.debug) {
|
|
58502
59200
|
console.log("[DEBUG] No API keys found, but claude command detected");
|
|
@@ -58506,8 +59204,17 @@ var init_ProbeAgent = __esm({
|
|
|
58506
59204
|
this.provider = null;
|
|
58507
59205
|
this.model = this.clientApiModel || "claude-3-5-sonnet-20241022";
|
|
58508
59206
|
this.apiType = "claude-code";
|
|
59207
|
+
} else if (codexAvailable) {
|
|
59208
|
+
if (this.debug) {
|
|
59209
|
+
console.log("[DEBUG] No API keys found, but codex command detected");
|
|
59210
|
+
console.log("[DEBUG] Auto-switching to codex provider");
|
|
59211
|
+
}
|
|
59212
|
+
this.clientApiProvider = "codex";
|
|
59213
|
+
this.provider = null;
|
|
59214
|
+
this.model = this.clientApiModel || "gpt-4o";
|
|
59215
|
+
this.apiType = "codex";
|
|
58509
59216
|
} else {
|
|
58510
|
-
throw new Error("No API key provided and claude command
|
|
59217
|
+
throw new Error("No API key provided and neither claude nor codex command found. Please either:\n1. Set an API key: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or AWS credentials\n2. Install claude command from https://docs.claude.com/en/docs/claude-code\n3. Install codex command from https://openai.com/codex");
|
|
58511
59218
|
}
|
|
58512
59219
|
}
|
|
58513
59220
|
}
|
|
@@ -58570,25 +59277,43 @@ var init_ProbeAgent = __esm({
|
|
|
58570
59277
|
* Initialize tools with configuration
|
|
58571
59278
|
*/
|
|
58572
59279
|
initializeTools() {
|
|
59280
|
+
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
58573
59281
|
const configOptions = {
|
|
58574
59282
|
sessionId: this.sessionId,
|
|
58575
59283
|
debug: this.debug,
|
|
58576
59284
|
defaultPath: this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd(),
|
|
58577
59285
|
allowedFolders: this.allowedFolders,
|
|
58578
59286
|
outline: this.outline,
|
|
59287
|
+
allowEdit: this.allowEdit,
|
|
59288
|
+
enableDelegate: this.enableDelegate,
|
|
58579
59289
|
enableBash: this.enableBash,
|
|
58580
|
-
bashConfig: this.bashConfig
|
|
59290
|
+
bashConfig: this.bashConfig,
|
|
59291
|
+
allowedTools: this.allowedTools,
|
|
59292
|
+
isToolAllowed
|
|
58581
59293
|
};
|
|
58582
59294
|
const baseTools = createTools(configOptions);
|
|
58583
59295
|
const wrappedTools = createWrappedTools(baseTools);
|
|
58584
|
-
this.toolImplementations = {
|
|
58585
|
-
|
|
58586
|
-
|
|
58587
|
-
|
|
58588
|
-
|
|
58589
|
-
|
|
58590
|
-
|
|
58591
|
-
|
|
59296
|
+
this.toolImplementations = {};
|
|
59297
|
+
if (wrappedTools.searchToolInstance && isToolAllowed("search")) {
|
|
59298
|
+
this.toolImplementations.search = wrappedTools.searchToolInstance;
|
|
59299
|
+
}
|
|
59300
|
+
if (wrappedTools.queryToolInstance && isToolAllowed("query")) {
|
|
59301
|
+
this.toolImplementations.query = wrappedTools.queryToolInstance;
|
|
59302
|
+
}
|
|
59303
|
+
if (wrappedTools.extractToolInstance && isToolAllowed("extract")) {
|
|
59304
|
+
this.toolImplementations.extract = wrappedTools.extractToolInstance;
|
|
59305
|
+
}
|
|
59306
|
+
if (this.enableDelegate && wrappedTools.delegateToolInstance && isToolAllowed("delegate")) {
|
|
59307
|
+
this.toolImplementations.delegate = wrappedTools.delegateToolInstance;
|
|
59308
|
+
}
|
|
59309
|
+
if (isToolAllowed("listFiles")) {
|
|
59310
|
+
this.toolImplementations.listFiles = listFilesToolInstance;
|
|
59311
|
+
}
|
|
59312
|
+
if (isToolAllowed("searchFiles")) {
|
|
59313
|
+
this.toolImplementations.searchFiles = searchFilesToolInstance;
|
|
59314
|
+
}
|
|
59315
|
+
if (isToolAllowed("readImage")) {
|
|
59316
|
+
this.toolImplementations.readImage = {
|
|
58592
59317
|
execute: async (params) => {
|
|
58593
59318
|
const imagePath = params.path;
|
|
58594
59319
|
if (!imagePath) {
|
|
@@ -58600,16 +59325,16 @@ var init_ProbeAgent = __esm({
|
|
|
58600
59325
|
}
|
|
58601
59326
|
return `Image loaded successfully: ${imagePath}. The image is now available for analysis in the conversation.`;
|
|
58602
59327
|
}
|
|
58603
|
-
}
|
|
58604
|
-
}
|
|
58605
|
-
if (this.enableBash && wrappedTools.bashToolInstance) {
|
|
59328
|
+
};
|
|
59329
|
+
}
|
|
59330
|
+
if (this.enableBash && wrappedTools.bashToolInstance && isToolAllowed("bash")) {
|
|
58606
59331
|
this.toolImplementations.bash = wrappedTools.bashToolInstance;
|
|
58607
59332
|
}
|
|
58608
59333
|
if (this.allowEdit) {
|
|
58609
|
-
if (wrappedTools.editToolInstance) {
|
|
59334
|
+
if (wrappedTools.editToolInstance && isToolAllowed("edit")) {
|
|
58610
59335
|
this.toolImplementations.edit = wrappedTools.editToolInstance;
|
|
58611
59336
|
}
|
|
58612
|
-
if (wrappedTools.createToolInstance) {
|
|
59337
|
+
if (wrappedTools.createToolInstance && isToolAllowed("create")) {
|
|
58613
59338
|
this.toolImplementations.create = wrappedTools.createToolInstance;
|
|
58614
59339
|
}
|
|
58615
59340
|
}
|
|
@@ -58629,13 +59354,33 @@ var init_ProbeAgent = __esm({
|
|
|
58629
59354
|
}
|
|
58630
59355
|
/**
|
|
58631
59356
|
* Check if claude command is available on the system
|
|
59357
|
+
* Uses execFile instead of exec to avoid shell injection risks
|
|
58632
59358
|
* @returns {Promise<boolean>} True if claude command is available
|
|
58633
59359
|
* @private
|
|
58634
59360
|
*/
|
|
58635
59361
|
async isClaudeCommandAvailable() {
|
|
58636
59362
|
try {
|
|
58637
|
-
const {
|
|
58638
|
-
|
|
59363
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
59364
|
+
const { promisify: promisify8 } = await import("util");
|
|
59365
|
+
const execFileAsync3 = promisify8(execFile3);
|
|
59366
|
+
await execFileAsync3("claude", ["--version"], { timeout: 5e3 });
|
|
59367
|
+
return true;
|
|
59368
|
+
} catch (error) {
|
|
59369
|
+
return false;
|
|
59370
|
+
}
|
|
59371
|
+
}
|
|
59372
|
+
/**
|
|
59373
|
+
* Check if codex command is available on the system
|
|
59374
|
+
* Uses execFile instead of exec to avoid shell injection risks
|
|
59375
|
+
* @returns {Promise<boolean>} True if codex command is available
|
|
59376
|
+
* @private
|
|
59377
|
+
*/
|
|
59378
|
+
async isCodexCommandAvailable() {
|
|
59379
|
+
try {
|
|
59380
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
59381
|
+
const { promisify: promisify8 } = await import("util");
|
|
59382
|
+
const execFileAsync3 = promisify8(execFile3);
|
|
59383
|
+
await execFileAsync3("codex", ["--version"], { timeout: 5e3 });
|
|
58639
59384
|
return true;
|
|
58640
59385
|
} catch (error) {
|
|
58641
59386
|
return false;
|
|
@@ -58659,6 +59404,20 @@ var init_ProbeAgent = __esm({
|
|
|
58659
59404
|
}
|
|
58660
59405
|
return;
|
|
58661
59406
|
}
|
|
59407
|
+
if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
|
|
59408
|
+
this.provider = null;
|
|
59409
|
+
this.model = modelName || null;
|
|
59410
|
+
this.apiType = "codex";
|
|
59411
|
+
if (this.debug) {
|
|
59412
|
+
console.log("[DEBUG] Codex CLI engine selected - will use built-in access if available");
|
|
59413
|
+
if (this.model) {
|
|
59414
|
+
console.log(`[DEBUG] Using model: ${this.model}`);
|
|
59415
|
+
} else {
|
|
59416
|
+
console.log("[DEBUG] Using Codex account default model");
|
|
59417
|
+
}
|
|
59418
|
+
}
|
|
59419
|
+
return;
|
|
59420
|
+
}
|
|
58662
59421
|
const anthropicApiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
|
|
58663
59422
|
const openaiApiKey = process.env.OPENAI_API_KEY;
|
|
58664
59423
|
const googleApiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY;
|
|
@@ -58820,6 +59579,44 @@ var init_ProbeAgent = __esm({
|
|
|
58820
59579
|
}
|
|
58821
59580
|
}
|
|
58822
59581
|
}
|
|
59582
|
+
if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
|
|
59583
|
+
try {
|
|
59584
|
+
const engine = await this.getEngine();
|
|
59585
|
+
if (engine && engine.query) {
|
|
59586
|
+
const userMessages = options.messages.filter(
|
|
59587
|
+
(m) => m.role === "user" && !m.content.includes("WARNING: You have reached the maximum tool iterations limit")
|
|
59588
|
+
);
|
|
59589
|
+
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
59590
|
+
const prompt = lastUserMessage ? lastUserMessage.content : "";
|
|
59591
|
+
const engineOptions = {
|
|
59592
|
+
maxTokens: options.maxTokens,
|
|
59593
|
+
temperature: options.temperature,
|
|
59594
|
+
messages: options.messages,
|
|
59595
|
+
systemPrompt: options.messages.find((m) => m.role === "system")?.content
|
|
59596
|
+
};
|
|
59597
|
+
const engineStream = engine.query(prompt, engineOptions);
|
|
59598
|
+
async function* createTextStream() {
|
|
59599
|
+
for await (const message of engineStream) {
|
|
59600
|
+
if (message.type === "text" && message.content) {
|
|
59601
|
+
yield message.content;
|
|
59602
|
+
} else if (typeof message === "string") {
|
|
59603
|
+
yield message;
|
|
59604
|
+
}
|
|
59605
|
+
}
|
|
59606
|
+
}
|
|
59607
|
+
return {
|
|
59608
|
+
textStream: createTextStream(),
|
|
59609
|
+
usage: Promise.resolve({})
|
|
59610
|
+
// Engine should handle its own usage tracking
|
|
59611
|
+
// Add other streamText-compatible properties as needed
|
|
59612
|
+
};
|
|
59613
|
+
}
|
|
59614
|
+
} catch (error) {
|
|
59615
|
+
if (this.debug) {
|
|
59616
|
+
console.log(`[DEBUG] Failed to use Codex engine, falling back to Vercel:`, error.message);
|
|
59617
|
+
}
|
|
59618
|
+
}
|
|
59619
|
+
}
|
|
58823
59620
|
if (!this.retryManager) {
|
|
58824
59621
|
this.retryManager = new RetryManager({
|
|
58825
59622
|
maxRetries: this.retryConfig.maxRetries ?? 3,
|
|
@@ -58972,6 +59769,35 @@ var init_ProbeAgent = __esm({
|
|
|
58972
59769
|
this.clientApiProvider = null;
|
|
58973
59770
|
}
|
|
58974
59771
|
}
|
|
59772
|
+
if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
|
|
59773
|
+
try {
|
|
59774
|
+
const { createCodexEngine: createCodexEngine2 } = await Promise.resolve().then(() => (init_codex(), codex_exports));
|
|
59775
|
+
const systemPrompt = this.customPrompt || this.getCodexNativeSystemPrompt();
|
|
59776
|
+
this.engine = await createCodexEngine2({
|
|
59777
|
+
agent: this,
|
|
59778
|
+
// Pass reference to ProbeAgent for tool access
|
|
59779
|
+
systemPrompt,
|
|
59780
|
+
customPrompt: this.customPrompt,
|
|
59781
|
+
sessionId: this.options?.sessionId,
|
|
59782
|
+
debug: this.debug,
|
|
59783
|
+
allowedTools: this.allowedTools,
|
|
59784
|
+
// Pass tool filtering configuration
|
|
59785
|
+
model: this.model
|
|
59786
|
+
// Pass model name (e.g., gpt-4o, o3, etc.)
|
|
59787
|
+
});
|
|
59788
|
+
if (this.debug) {
|
|
59789
|
+
console.log("[DEBUG] Using Codex CLI engine with Probe tools");
|
|
59790
|
+
if (this.customPrompt) {
|
|
59791
|
+
console.log("[DEBUG] Using custom prompt/persona");
|
|
59792
|
+
}
|
|
59793
|
+
}
|
|
59794
|
+
return this.engine;
|
|
59795
|
+
} catch (error) {
|
|
59796
|
+
console.warn("[WARNING] Failed to load Codex CLI engine:", error.message);
|
|
59797
|
+
console.warn("[WARNING] Falling back to Vercel AI SDK");
|
|
59798
|
+
this.clientApiProvider = null;
|
|
59799
|
+
}
|
|
59800
|
+
}
|
|
58975
59801
|
const { createEnhancedVercelEngine: createEnhancedVercelEngine2 } = await Promise.resolve().then(() => (init_enhanced_vercel(), enhanced_vercel_exports));
|
|
58976
59802
|
this.engine = createEnhancedVercelEngine2(this);
|
|
58977
59803
|
if (this.debug) {
|
|
@@ -58979,6 +59805,32 @@ var init_ProbeAgent = __esm({
|
|
|
58979
59805
|
}
|
|
58980
59806
|
return this.engine;
|
|
58981
59807
|
}
|
|
59808
|
+
/**
|
|
59809
|
+
* Get session information including thread ID for resumability
|
|
59810
|
+
* @returns {Object} Session info with sessionId, threadId, messageCount
|
|
59811
|
+
*/
|
|
59812
|
+
getSessionInfo() {
|
|
59813
|
+
if (this.engine && this.engine.getSession) {
|
|
59814
|
+
return this.engine.getSession();
|
|
59815
|
+
}
|
|
59816
|
+
return {
|
|
59817
|
+
id: this.sessionId,
|
|
59818
|
+
threadId: null,
|
|
59819
|
+
messageCount: 0
|
|
59820
|
+
};
|
|
59821
|
+
}
|
|
59822
|
+
/**
|
|
59823
|
+
* Close the agent and clean up resources (e.g., MCP servers)
|
|
59824
|
+
* @returns {Promise<void>}
|
|
59825
|
+
*/
|
|
59826
|
+
async close() {
|
|
59827
|
+
if (this.engine && this.engine.close) {
|
|
59828
|
+
await this.engine.close();
|
|
59829
|
+
}
|
|
59830
|
+
if (this.mcpBridge) {
|
|
59831
|
+
this.mcpBridge = null;
|
|
59832
|
+
}
|
|
59833
|
+
}
|
|
58982
59834
|
/**
|
|
58983
59835
|
* Process assistant response content and detect/load image references
|
|
58984
59836
|
* @param {string} content - The assistant's response content
|
|
@@ -59271,11 +60123,61 @@ var init_ProbeAgent = __esm({
|
|
|
59271
60123
|
*/
|
|
59272
60124
|
getClaudeNativeSystemPrompt() {
|
|
59273
60125
|
let systemPrompt = "";
|
|
59274
|
-
if (this.
|
|
59275
|
-
|
|
59276
|
-
|
|
59277
|
-
|
|
59278
|
-
|
|
60126
|
+
if (this.customPrompt) {
|
|
60127
|
+
systemPrompt += this.customPrompt + "\n\n";
|
|
60128
|
+
} else if (this.promptType && predefinedPrompts[this.promptType]) {
|
|
60129
|
+
systemPrompt += predefinedPrompts[this.promptType] + "\n\n";
|
|
60130
|
+
} else {
|
|
60131
|
+
systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
|
|
60132
|
+
}
|
|
60133
|
+
systemPrompt += `You have access to powerful code search and analysis tools through MCP:
|
|
60134
|
+
- search: Find code patterns using semantic search
|
|
60135
|
+
- extract: Extract specific code sections with context
|
|
60136
|
+
- query: Use AST patterns for structural code matching
|
|
60137
|
+
- listFiles: Browse directory contents
|
|
60138
|
+
- searchFiles: Find files by name patterns`;
|
|
60139
|
+
if (this.enableBash) {
|
|
60140
|
+
systemPrompt += `
|
|
60141
|
+
- bash: Execute bash commands for system operations`;
|
|
60142
|
+
}
|
|
60143
|
+
systemPrompt += `
|
|
60144
|
+
|
|
60145
|
+
When exploring code:
|
|
60146
|
+
1. Start with search to find relevant code patterns
|
|
60147
|
+
2. Use extract to get detailed context when needed
|
|
60148
|
+
3. Prefer focused, specific searches over broad queries
|
|
60149
|
+
4. Combine multiple tools to build complete understanding`;
|
|
60150
|
+
if (this.allowedFolders && this.allowedFolders.length > 0) {
|
|
60151
|
+
systemPrompt += `
|
|
60152
|
+
|
|
60153
|
+
Workspace: ${this.allowedFolders.join(", ")}`;
|
|
60154
|
+
}
|
|
60155
|
+
if (this.fileList) {
|
|
60156
|
+
systemPrompt += `
|
|
60157
|
+
|
|
60158
|
+
# Repository Structure
|
|
60159
|
+
`;
|
|
60160
|
+
systemPrompt += `You are working with a repository located at: ${this.allowedFolders[0]}
|
|
60161
|
+
|
|
60162
|
+
`;
|
|
60163
|
+
systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
|
|
60164
|
+
|
|
60165
|
+
`;
|
|
60166
|
+
systemPrompt += "```\n" + this.fileList + "\n```\n";
|
|
60167
|
+
}
|
|
60168
|
+
return systemPrompt;
|
|
60169
|
+
}
|
|
60170
|
+
/**
|
|
60171
|
+
* Get system prompt for Codex CLI (similar to Claude but optimized for Codex)
|
|
60172
|
+
*/
|
|
60173
|
+
getCodexNativeSystemPrompt() {
|
|
60174
|
+
let systemPrompt = "";
|
|
60175
|
+
if (this.customPrompt) {
|
|
60176
|
+
systemPrompt += this.customPrompt + "\n\n";
|
|
60177
|
+
} else if (this.promptType && predefinedPrompts[this.promptType]) {
|
|
60178
|
+
systemPrompt += predefinedPrompts[this.promptType] + "\n\n";
|
|
60179
|
+
} else {
|
|
60180
|
+
systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
|
|
59279
60181
|
}
|
|
59280
60182
|
systemPrompt += `You have access to powerful code search and analysis tools through MCP:
|
|
59281
60183
|
- search: Find code patterns using semantic search
|
|
@@ -59471,7 +60373,7 @@ Follow these instructions carefully:
|
|
|
59471
60373
|
- Use 'create' for new files or complete file rewrites` : ""}
|
|
59472
60374
|
</instructions>
|
|
59473
60375
|
`;
|
|
59474
|
-
const
|
|
60376
|
+
const predefinedPrompts2 = {
|
|
59475
60377
|
"code-explorer": `You are ProbeChat Code Explorer, a specialized AI assistant focused on helping developers, product managers, and QAs understand and navigate codebases. Your primary function is to answer questions based on code, explain how systems work, and provide insights into code functionality using the provided code analysis tools.
|
|
59476
60378
|
|
|
59477
60379
|
When exploring code:
|
|
@@ -59527,14 +60429,14 @@ When troubleshooting:
|
|
|
59527
60429
|
if (this.debug) {
|
|
59528
60430
|
console.log(`[DEBUG] Using custom prompt`);
|
|
59529
60431
|
}
|
|
59530
|
-
} else if (this.promptType &&
|
|
59531
|
-
systemMessage = "<role>" +
|
|
60432
|
+
} else if (this.promptType && predefinedPrompts2[this.promptType]) {
|
|
60433
|
+
systemMessage = "<role>" + predefinedPrompts2[this.promptType] + "</role>";
|
|
59532
60434
|
if (this.debug) {
|
|
59533
60435
|
console.log(`[DEBUG] Using predefined prompt: ${this.promptType}`);
|
|
59534
60436
|
}
|
|
59535
60437
|
systemMessage += commonInstructions;
|
|
59536
60438
|
} else {
|
|
59537
|
-
systemMessage = "<role>" +
|
|
60439
|
+
systemMessage = "<role>" + predefinedPrompts2["code-explorer"] + "</role>";
|
|
59538
60440
|
if (this.debug) {
|
|
59539
60441
|
console.log(`[DEBUG] Using default prompt: code explorer`);
|
|
59540
60442
|
}
|
|
@@ -59675,6 +60577,7 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
59675
60577
|
const baseMaxIterations = this.maxIterations || MAX_TOOL_ITERATIONS;
|
|
59676
60578
|
const maxIterations = options.schema ? baseMaxIterations + 4 : baseMaxIterations;
|
|
59677
60579
|
const isClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
|
|
60580
|
+
const isCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
|
|
59678
60581
|
if (isClaudeCode) {
|
|
59679
60582
|
if (this.debug) {
|
|
59680
60583
|
console.log(`[DEBUG] Using Claude Code engine - bypassing tool loop (black box mode)`);
|
|
@@ -59727,6 +60630,58 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
59727
60630
|
throw error;
|
|
59728
60631
|
}
|
|
59729
60632
|
}
|
|
60633
|
+
if (isCodex) {
|
|
60634
|
+
if (this.debug) {
|
|
60635
|
+
console.log(`[DEBUG] Using Codex engine - bypassing tool loop (black box mode)`);
|
|
60636
|
+
console.log(`[DEBUG] Sending question directly to Codex: ${message.substring(0, 100)}...`);
|
|
60637
|
+
}
|
|
60638
|
+
try {
|
|
60639
|
+
const engine = await this.getEngine();
|
|
60640
|
+
if (engine && engine.query) {
|
|
60641
|
+
let assistantResponseContent = "";
|
|
60642
|
+
let toolBatch = null;
|
|
60643
|
+
for await (const chunk of engine.query(message, options)) {
|
|
60644
|
+
if (chunk.type === "text" && chunk.content) {
|
|
60645
|
+
assistantResponseContent += chunk.content;
|
|
60646
|
+
if (options.onStream) {
|
|
60647
|
+
options.onStream(chunk.content);
|
|
60648
|
+
}
|
|
60649
|
+
} else if (chunk.type === "toolBatch" && chunk.tools) {
|
|
60650
|
+
toolBatch = chunk.tools;
|
|
60651
|
+
if (this.debug) {
|
|
60652
|
+
console.log(`[DEBUG] Received batch of ${chunk.tools.length} tool events from Codex`);
|
|
60653
|
+
}
|
|
60654
|
+
} else if (chunk.type === "error") {
|
|
60655
|
+
throw chunk.error;
|
|
60656
|
+
}
|
|
60657
|
+
}
|
|
60658
|
+
if (toolBatch && toolBatch.length > 0 && this.events) {
|
|
60659
|
+
if (this.debug) {
|
|
60660
|
+
console.log(`[DEBUG] Emitting ${toolBatch.length} tool events from Codex batch`);
|
|
60661
|
+
}
|
|
60662
|
+
for (const toolEvent of toolBatch) {
|
|
60663
|
+
this.events.emit("toolCall", toolEvent);
|
|
60664
|
+
}
|
|
60665
|
+
}
|
|
60666
|
+
this.history.push(userMessage);
|
|
60667
|
+
this.history.push({
|
|
60668
|
+
role: "assistant",
|
|
60669
|
+
content: assistantResponseContent
|
|
60670
|
+
});
|
|
60671
|
+
await this.hooks.emit(HOOK_TYPES.COMPLETION, {
|
|
60672
|
+
sessionId: this.sessionId,
|
|
60673
|
+
prompt: message,
|
|
60674
|
+
response: assistantResponseContent
|
|
60675
|
+
});
|
|
60676
|
+
return assistantResponseContent;
|
|
60677
|
+
}
|
|
60678
|
+
} catch (error) {
|
|
60679
|
+
if (this.debug) {
|
|
60680
|
+
console.error("[DEBUG] Codex error:", error);
|
|
60681
|
+
}
|
|
60682
|
+
throw error;
|
|
60683
|
+
}
|
|
60684
|
+
}
|
|
59730
60685
|
if (this.debug) {
|
|
59731
60686
|
console.log(`[DEBUG] Starting agentic flow for question: ${message.substring(0, 100)}...`);
|
|
59732
60687
|
if (options.schema) {
|
|
@@ -60607,7 +61562,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
60607
61562
|
*/
|
|
60608
61563
|
clone(options = {}) {
|
|
60609
61564
|
const {
|
|
60610
|
-
sessionId =
|
|
61565
|
+
sessionId = randomUUID5(),
|
|
60611
61566
|
stripInternalMessages = true,
|
|
60612
61567
|
keepSystemMessage = true,
|
|
60613
61568
|
deepCopy = true,
|
|
@@ -60826,7 +61781,7 @@ import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
|
|
|
60826
61781
|
import { resolve as resolve5 } from "path";
|
|
60827
61782
|
|
|
60828
61783
|
// src/agent/acp/server.js
|
|
60829
|
-
import { randomUUID as
|
|
61784
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
60830
61785
|
|
|
60831
61786
|
// src/agent/acp/connection.js
|
|
60832
61787
|
import { EventEmitter as EventEmitter6 } from "events";
|
|
@@ -61318,7 +62273,7 @@ var ACPServer = class {
|
|
|
61318
62273
|
* Handle new session request
|
|
61319
62274
|
*/
|
|
61320
62275
|
async handleNewSession(params) {
|
|
61321
|
-
const sessionId = params?.sessionId ||
|
|
62276
|
+
const sessionId = params?.sessionId || randomUUID6();
|
|
61322
62277
|
const mode = params?.mode || SessionMode.NORMAL;
|
|
61323
62278
|
const session = new ACPSession(sessionId, mode);
|
|
61324
62279
|
this.sessions.set(sessionId, session);
|
|
@@ -61490,7 +62445,7 @@ var ACPServer = class {
|
|
|
61490
62445
|
};
|
|
61491
62446
|
|
|
61492
62447
|
// src/agent/acp/tools.js
|
|
61493
|
-
import { randomUUID as
|
|
62448
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
61494
62449
|
|
|
61495
62450
|
// src/agent/index.js
|
|
61496
62451
|
dotenv3.config();
|