@probelabs/probe 0.6.0-rc167 → 0.6.0-rc168

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.
@@ -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: randomUUID7 } = await import("crypto");
8300
- tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID7()}.txt`);
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}`);
@@ -55844,6 +55844,126 @@ Provide only the corrected Mermaid diagram within a mermaid code block. Do not a
55844
55844
  }
55845
55845
  });
55846
55846
 
55847
+ // src/agent/shared/prompts.js
55848
+ var predefinedPrompts;
55849
+ var init_prompts = __esm({
55850
+ "src/agent/shared/prompts.js"() {
55851
+ "use strict";
55852
+ predefinedPrompts = {
55853
+ "code-explorer": `You are ProbeChat Code Explorer - an AI assistant focused on reading and explaining code using Probe's semantic search capabilities.
55854
+
55855
+ Your primary role is to explore codebases, understand code structure, and provide clear explanations. You should:
55856
+
55857
+ 1. Use the 'search' tool to find relevant code snippets across the codebase
55858
+ 2. Use the 'query' tool to locate specific symbols, functions, or classes
55859
+ 3. Use the 'extract' tool to get full context for files or specific code blocks
55860
+ 4. Explain code behavior, architecture patterns, and relationships between components
55861
+ 5. Provide concise summaries with key insights highlighted
55862
+
55863
+ When exploring code:
55864
+ - Start with targeted searches to find relevant areas
55865
+ - Extract full context when you need to understand implementation details
55866
+ - Trace function calls and data flow to understand how components interact
55867
+ - Focus on "why" and "how" rather than just describing what the code does
55868
+
55869
+ You should NOT:
55870
+ - Make changes to the codebase (read-only access)
55871
+ - Execute or run code
55872
+ - Make assumptions without verifying through search/query/extract`,
55873
+ "architect": `You are ProbeChat Architect - a senior software architect specialized in analyzing and designing software systems.
55874
+
55875
+ Your role is to:
55876
+
55877
+ 1. Analyze existing codebases to understand architecture patterns and design decisions
55878
+ 2. Identify architectural issues, technical debt, and improvement opportunities
55879
+ 3. Propose refactoring strategies and architectural changes
55880
+ 4. Design new features that fit well with existing architecture
55881
+ 5. Create high-level architecture diagrams and documentation
55882
+
55883
+ When analyzing architecture:
55884
+ - Use search/query/extract to understand component boundaries and dependencies
55885
+ - Identify layers, modules, and their responsibilities
55886
+ - Look for patterns like MVC, microservices, event-driven, etc.
55887
+ - Assess coupling, cohesion, and separation of concerns
55888
+ - Consider scalability, maintainability, and testability
55889
+
55890
+ When proposing changes:
55891
+ - Provide clear rationale backed by architectural principles
55892
+ - Consider migration paths and backwards compatibility
55893
+ - Identify risks and tradeoffs
55894
+ - Suggest incremental implementation steps`,
55895
+ "code-review": `You are ProbeChat Code Reviewer - a meticulous code reviewer focused on quality, best practices, and maintainability.
55896
+
55897
+ Your role is to:
55898
+
55899
+ 1. Review code changes for correctness, clarity, and best practices
55900
+ 2. Identify bugs, security issues, and performance problems
55901
+ 3. Suggest improvements for readability and maintainability
55902
+ 4. Ensure consistency with project conventions and patterns
55903
+ 5. Verify test coverage and edge case handling
55904
+
55905
+ When reviewing code:
55906
+ - Use search to find similar patterns in the codebase for consistency
55907
+ - Look for common issues: null checks, error handling, resource leaks
55908
+ - Check for security vulnerabilities: injection, XSS, etc.
55909
+ - Assess complexity and suggest simplifications
55910
+ - Verify naming conventions and code organization
55911
+
55912
+ Provide constructive feedback:
55913
+ - Start with what's good about the code
55914
+ - Be specific about issues with examples
55915
+ - Suggest concrete improvements with code snippets
55916
+ - Prioritize critical issues over style preferences
55917
+ - Explain the "why" behind your suggestions`,
55918
+ "engineer": `You are a senior engineer who helps implement features and fix bugs.
55919
+
55920
+ Your role is to:
55921
+
55922
+ 1. Implement new features following project conventions
55923
+ 2. Fix bugs by understanding root causes
55924
+ 3. Refactor code to improve quality
55925
+ 4. Write clear, maintainable code
55926
+ 5. Add appropriate tests and documentation
55927
+
55928
+ When implementing:
55929
+ - Use search/query to understand existing patterns
55930
+ - Follow the project's coding style and conventions
55931
+ - Consider edge cases and error handling
55932
+ - Write self-documenting code with clear names
55933
+ - Add comments for complex logic
55934
+
55935
+ You have access to:
55936
+ - search: Find relevant code patterns
55937
+ - query: Locate specific symbols/functions
55938
+ - extract: Get full file context
55939
+ - implement: Create or modify files (use carefully)
55940
+ - delegate: Break down complex tasks`,
55941
+ "support": `You are ProbeChat Support - a helpful assistant focused on answering questions about codebases.
55942
+
55943
+ Your role is to:
55944
+
55945
+ 1. Answer questions about how code works
55946
+ 2. Help users locate specific functionality
55947
+ 3. Explain error messages and debugging approaches
55948
+ 4. Guide users to relevant documentation
55949
+ 5. Provide examples and usage patterns
55950
+
55951
+ When helping users:
55952
+ - Ask clarifying questions if the request is ambiguous
55953
+ - Use search/query to find relevant code quickly
55954
+ - Provide clear, step-by-step explanations
55955
+ - Include code examples when helpful
55956
+ - Point to relevant files and line numbers
55957
+
55958
+ You should be:
55959
+ - Patient and encouraging
55960
+ - Clear and concise
55961
+ - Thorough but not overwhelming
55962
+ - Honest about limitations (say "I don't know" when appropriate)`
55963
+ };
55964
+ }
55965
+ });
55966
+
55847
55967
  // src/agent/mcp/config.js
55848
55968
  import { readFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync } from "fs";
55849
55969
  import { join as join2, dirname as dirname3 } from "path";
@@ -57383,15 +57503,60 @@ var init_contextCompactor = __esm({
57383
57503
  // src/agent/mcp/built-in-server.js
57384
57504
  import { createServer } from "http";
57385
57505
  import { EventEmitter as EventEmitter3 } from "events";
57506
+ import { randomUUID as randomUUID4 } from "crypto";
57386
57507
  import { Server as MCPServer } from "@modelcontextprotocol/sdk/server/index.js";
57508
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
57509
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
57387
57510
  import {
57388
57511
  CallToolRequestSchema,
57389
- ListToolsRequestSchema
57512
+ ListToolsRequestSchema,
57513
+ isInitializeRequest
57390
57514
  } from "@modelcontextprotocol/sdk/types.js";
57391
- var BuiltInMCPServer;
57515
+ var InMemoryEventStore, BuiltInMCPServer;
57392
57516
  var init_built_in_server = __esm({
57393
57517
  "src/agent/mcp/built-in-server.js"() {
57394
57518
  "use strict";
57519
+ InMemoryEventStore = class {
57520
+ constructor() {
57521
+ this.events = /* @__PURE__ */ new Map();
57522
+ }
57523
+ generateEventId(streamId) {
57524
+ return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
57525
+ }
57526
+ getStreamIdFromEventId(eventId) {
57527
+ const parts = eventId.split("_");
57528
+ return parts.length > 0 ? parts[0] : "";
57529
+ }
57530
+ async storeEvent(streamId, message) {
57531
+ const eventId = this.generateEventId(streamId);
57532
+ this.events.set(eventId, { streamId, message });
57533
+ return eventId;
57534
+ }
57535
+ async replayEventsAfter(lastEventId, { send }) {
57536
+ if (!lastEventId || !this.events.has(lastEventId)) {
57537
+ return "";
57538
+ }
57539
+ const streamId = this.getStreamIdFromEventId(lastEventId);
57540
+ if (!streamId) {
57541
+ return "";
57542
+ }
57543
+ let foundLastEvent = false;
57544
+ const sortedEvents = [...this.events.entries()].sort((a, b) => a[0].localeCompare(b[0]));
57545
+ for (const [eventId, { streamId: eventStreamId, message }] of sortedEvents) {
57546
+ if (eventStreamId !== streamId) {
57547
+ continue;
57548
+ }
57549
+ if (eventId === lastEventId) {
57550
+ foundLastEvent = true;
57551
+ continue;
57552
+ }
57553
+ if (foundLastEvent) {
57554
+ await send(eventId, message);
57555
+ }
57556
+ }
57557
+ return streamId;
57558
+ }
57559
+ };
57395
57560
  BuiltInMCPServer = class extends EventEmitter3 {
57396
57561
  constructor(agent, options = {}) {
57397
57562
  super();
@@ -57400,6 +57565,8 @@ var init_built_in_server = __esm({
57400
57565
  this.host = options.host || "127.0.0.1";
57401
57566
  this.httpServer = null;
57402
57567
  this.mcpServer = null;
57568
+ this.sseTransports = /* @__PURE__ */ new Map();
57569
+ this.streamableTransports = /* @__PURE__ */ new Map();
57403
57570
  this.connections = /* @__PURE__ */ new Set();
57404
57571
  this.debug = options.debug || false;
57405
57572
  }
@@ -57421,11 +57588,13 @@ var init_built_in_server = __esm({
57421
57588
  });
57422
57589
  this.registerHandlers();
57423
57590
  return new Promise((resolve6, reject2) => {
57424
- this.httpServer.listen(this.port, this.host, () => {
57591
+ this.httpServer.listen(this.port, this.host, async () => {
57425
57592
  const address = this.httpServer.address();
57426
57593
  this.port = address.port;
57427
57594
  if (this.debug) {
57428
57595
  console.log(`[MCP] Built-in server started at http://${this.host}:${this.port}`);
57596
+ console.log(`[MCP] SSE endpoint: http://${this.host}:${this.port}/sse`);
57597
+ console.log(`[MCP] Messages endpoint: http://${this.host}:${this.port}/messages`);
57429
57598
  }
57430
57599
  this.emit("ready", { host: this.host, port: this.port });
57431
57600
  resolve6({ host: this.host, port: this.port });
@@ -57438,6 +57607,9 @@ var init_built_in_server = __esm({
57438
57607
  */
57439
57608
  handleRequest(req, res) {
57440
57609
  const { method, url } = req;
57610
+ if (this.debug) {
57611
+ console.log(`[MCP] Request: ${method} ${url}`);
57612
+ }
57441
57613
  res.setHeader("Access-Control-Allow-Origin", "*");
57442
57614
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
57443
57615
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
@@ -57447,15 +57619,22 @@ var init_built_in_server = __esm({
57447
57619
  return;
57448
57620
  }
57449
57621
  if (url === "/sse" && method === "GET") {
57450
- this.handleSSE(req, res);
57622
+ if (this.debug) {
57623
+ console.log("[MCP] Routing to handleSSEConnection");
57624
+ }
57625
+ this.handleSSEConnection(req, res);
57626
+ return;
57627
+ }
57628
+ if (url.startsWith("/messages") && method === "POST") {
57629
+ this.handleSSEMessage(req, res);
57451
57630
  return;
57452
57631
  }
57453
57632
  if (url === "/rpc" && method === "POST") {
57454
57633
  this.handleJSONRPC(req, res);
57455
57634
  return;
57456
57635
  }
57457
- if (url === "/mcp" && method === "POST") {
57458
- this.handleMCPProtocol(req, res);
57636
+ if (url === "/mcp") {
57637
+ this.handleStreamableHTTP(req, res);
57459
57638
  return;
57460
57639
  }
57461
57640
  if (url === "/health") {
@@ -57471,7 +57650,190 @@ var init_built_in_server = __esm({
57471
57650
  res.end("Not Found");
57472
57651
  }
57473
57652
  /**
57474
- * Handle Server-Sent Events connection
57653
+ * Handle SSE connection (GET /sse) - creates new transport
57654
+ */
57655
+ async handleSSEConnection(req, res) {
57656
+ if (this.debug) {
57657
+ console.log("[MCP] New SSE connection request");
57658
+ }
57659
+ const transport = new SSEServerTransport("/messages", res);
57660
+ this.sseTransports.set(transport.sessionId, transport);
57661
+ res.on("close", () => {
57662
+ if (this.debug) {
57663
+ console.log("[MCP] SSE connection closed, sessionId:", transport.sessionId);
57664
+ }
57665
+ this.sseTransports.delete(transport.sessionId);
57666
+ });
57667
+ try {
57668
+ await this.mcpServer.connect(transport);
57669
+ if (this.debug) {
57670
+ console.log("[MCP] MCP server connected to SSE transport, sessionId:", transport.sessionId);
57671
+ }
57672
+ } catch (error) {
57673
+ if (this.debug) {
57674
+ console.error("[MCP] Error connecting MCP server to transport:", error);
57675
+ }
57676
+ this.sseTransports.delete(transport.sessionId);
57677
+ }
57678
+ }
57679
+ /**
57680
+ * Handle SSE message (POST /messages?sessionId=...) - routes to existing transport
57681
+ */
57682
+ async handleSSEMessage(req, res) {
57683
+ const url = new URL(req.url, `http://${req.headers.host}`);
57684
+ const sessionId = url.searchParams.get("sessionId");
57685
+ if (!sessionId) {
57686
+ res.writeHead(400, { "Content-Type": "application/json" });
57687
+ res.end(JSON.stringify({
57688
+ jsonrpc: "2.0",
57689
+ error: {
57690
+ code: -32e3,
57691
+ message: "Bad Request: sessionId query parameter is required"
57692
+ },
57693
+ id: null
57694
+ }));
57695
+ return;
57696
+ }
57697
+ const transport = this.sseTransports.get(sessionId);
57698
+ if (!transport) {
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: No transport found for sessionId: ${sessionId}`
57705
+ },
57706
+ id: null
57707
+ }));
57708
+ return;
57709
+ }
57710
+ let body = "";
57711
+ req.on("data", (chunk) => {
57712
+ body += chunk.toString();
57713
+ });
57714
+ req.on("end", async () => {
57715
+ try {
57716
+ const message = JSON.parse(body);
57717
+ await transport.handlePostMessage(req, res, message);
57718
+ } catch (error) {
57719
+ res.writeHead(500, { "Content-Type": "application/json" });
57720
+ res.end(JSON.stringify({
57721
+ jsonrpc: "2.0",
57722
+ error: {
57723
+ code: -32603,
57724
+ message: "Internal error",
57725
+ data: error.message
57726
+ },
57727
+ id: null
57728
+ }));
57729
+ }
57730
+ });
57731
+ }
57732
+ /**
57733
+ * Handle Streamable HTTP protocol (GET/POST/DELETE on /mcp)
57734
+ */
57735
+ async handleStreamableHTTP(req, res) {
57736
+ const { method } = req;
57737
+ if (this.debug) {
57738
+ console.log(`[MCP] Streamable HTTP ${method} request`);
57739
+ }
57740
+ try {
57741
+ let body = null;
57742
+ if (method === "POST") {
57743
+ body = await this.parseRequestBody(req);
57744
+ }
57745
+ const sessionId = req.headers["mcp-session-id"];
57746
+ let transport;
57747
+ if (sessionId && this.streamableTransports.has(sessionId)) {
57748
+ transport = this.streamableTransports.get(sessionId);
57749
+ if (this.debug) {
57750
+ console.log(`[MCP] Reusing existing transport for session: ${sessionId}`);
57751
+ }
57752
+ } else if (!sessionId && method === "POST" && body && isInitializeRequest(body)) {
57753
+ if (this.debug) {
57754
+ console.log("[MCP] Creating new Streamable HTTP transport for initialization");
57755
+ }
57756
+ const eventStore = new InMemoryEventStore();
57757
+ transport = new StreamableHTTPServerTransport({
57758
+ sessionIdGenerator: () => randomUUID4(),
57759
+ eventStore,
57760
+ // Enable resumability
57761
+ onsessioninitialized: (newSessionId) => {
57762
+ if (this.debug) {
57763
+ console.log(`[MCP] Streamable HTTP session initialized: ${newSessionId}`);
57764
+ }
57765
+ this.streamableTransports.set(newSessionId, transport);
57766
+ },
57767
+ onsessionclosed: (closedSessionId) => {
57768
+ if (this.debug) {
57769
+ console.log(`[MCP] Streamable HTTP session closed: ${closedSessionId}`);
57770
+ }
57771
+ this.streamableTransports.delete(closedSessionId);
57772
+ }
57773
+ });
57774
+ transport.onclose = () => {
57775
+ const sid = transport.sessionId;
57776
+ if (sid && this.streamableTransports.has(sid)) {
57777
+ if (this.debug) {
57778
+ console.log(`[MCP] Transport closed for session ${sid}`);
57779
+ }
57780
+ this.streamableTransports.delete(sid);
57781
+ }
57782
+ };
57783
+ await this.mcpServer.connect(transport);
57784
+ } else {
57785
+ res.writeHead(400, { "Content-Type": "application/json" });
57786
+ res.end(JSON.stringify({
57787
+ jsonrpc: "2.0",
57788
+ error: {
57789
+ code: -32e3,
57790
+ message: "Bad Request: No valid session ID provided or not an initialization request"
57791
+ },
57792
+ id: null
57793
+ }));
57794
+ return;
57795
+ }
57796
+ await transport.handleRequest(req, res, body);
57797
+ } catch (error) {
57798
+ if (this.debug) {
57799
+ console.error("[MCP] Error handling Streamable HTTP request:", error);
57800
+ }
57801
+ if (!res.headersSent) {
57802
+ res.writeHead(500, { "Content-Type": "application/json" });
57803
+ res.end(JSON.stringify({
57804
+ jsonrpc: "2.0",
57805
+ error: {
57806
+ code: -32603,
57807
+ message: "Internal server error",
57808
+ data: error.message
57809
+ },
57810
+ id: null
57811
+ }));
57812
+ }
57813
+ }
57814
+ }
57815
+ /**
57816
+ * Parse request body as JSON
57817
+ */
57818
+ async parseRequestBody(req) {
57819
+ return new Promise((resolve6, reject2) => {
57820
+ let body = "";
57821
+ req.on("data", (chunk) => {
57822
+ body += chunk.toString();
57823
+ });
57824
+ req.on("end", () => {
57825
+ try {
57826
+ const parsed = body ? JSON.parse(body) : null;
57827
+ resolve6(parsed);
57828
+ } catch (error) {
57829
+ reject2(error);
57830
+ }
57831
+ });
57832
+ req.on("error", reject2);
57833
+ });
57834
+ }
57835
+ /**
57836
+ * Handle Server-Sent Events connection (DEPRECATED - use handleSSEConnection instead)
57475
57837
  */
57476
57838
  handleSSE(req, res) {
57477
57839
  res.writeHead(200, {
@@ -57738,6 +58100,32 @@ data: ${JSON.stringify(data)}
57738
58100
  * Stop the server
57739
58101
  */
57740
58102
  async stop() {
58103
+ for (const [sessionId, transport] of this.streamableTransports.entries()) {
58104
+ try {
58105
+ await transport.close();
58106
+ if (this.debug) {
58107
+ console.log(`[MCP] Closed Streamable HTTP transport for session: ${sessionId}`);
58108
+ }
58109
+ } catch (error) {
58110
+ if (this.debug) {
58111
+ console.error(`[MCP] Error closing Streamable HTTP transport ${sessionId}:`, error);
58112
+ }
58113
+ }
58114
+ }
58115
+ this.streamableTransports.clear();
58116
+ for (const [sessionId, transport] of this.sseTransports.entries()) {
58117
+ try {
58118
+ await transport.close();
58119
+ if (this.debug) {
58120
+ console.log(`[MCP] Closed SSE transport for session: ${sessionId}`);
58121
+ }
58122
+ } catch (error) {
58123
+ if (this.debug) {
58124
+ console.error(`[MCP] Error closing SSE transport ${sessionId}:`, error);
58125
+ }
58126
+ }
58127
+ }
58128
+ this.sseTransports.clear();
57741
58129
  for (const connection of this.connections) {
57742
58130
  connection.end();
57743
58131
  }
@@ -57769,6 +58157,59 @@ data: ${JSON.stringify(data)}
57769
58157
  }
57770
58158
  });
57771
58159
 
58160
+ // src/agent/shared/Session.js
58161
+ var Session;
58162
+ var init_Session = __esm({
58163
+ "src/agent/shared/Session.js"() {
58164
+ "use strict";
58165
+ Session = class {
58166
+ constructor(id, debug = false) {
58167
+ this.id = id;
58168
+ this.conversationId = null;
58169
+ this.messageCount = 0;
58170
+ this.debug = debug;
58171
+ }
58172
+ /**
58173
+ * Set the conversation ID for session resumption
58174
+ * @param {string} conversationId - Provider's conversation/thread ID
58175
+ */
58176
+ setConversationId(conversationId) {
58177
+ this.conversationId = conversationId;
58178
+ if (this.debug) {
58179
+ console.log(`[Session ${this.id}] Conversation ID: ${conversationId}`);
58180
+ }
58181
+ }
58182
+ /**
58183
+ * Increment the message count
58184
+ */
58185
+ incrementMessageCount() {
58186
+ this.messageCount++;
58187
+ }
58188
+ /**
58189
+ * Get session info as plain object
58190
+ * @returns {Object} Session information
58191
+ */
58192
+ getInfo() {
58193
+ return {
58194
+ id: this.id,
58195
+ conversationId: this.conversationId,
58196
+ messageCount: this.messageCount
58197
+ };
58198
+ }
58199
+ /**
58200
+ * Get resume arguments for CLI commands (used by Claude Code)
58201
+ * @returns {Array<string>} CLI arguments for resuming conversation
58202
+ */
58203
+ getResumeArgs() {
58204
+ if (this.conversationId && this.messageCount > 0) {
58205
+ return ["--resume", this.conversationId];
58206
+ }
58207
+ return [];
58208
+ }
58209
+ };
58210
+ }
58211
+ });
58212
+
57772
58213
  // src/agent/engines/enhanced-claude-code.js
57773
58214
  var enhanced_claude_code_exports = {};
57774
58215
  __export(enhanced_claude_code_exports, {
@@ -57782,7 +58223,7 @@ import os3 from "os";
57782
58223
  import { EventEmitter as EventEmitter4 } from "events";
57783
58224
  async function createEnhancedClaudeCLIEngine(options = {}) {
57784
58225
  const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools } = options;
57785
- const session = new ClaudeSession(
58226
+ const session = new Session(
57786
58227
  sessionId || randomBytes(8).toString("hex"),
57787
58228
  debug
57788
58229
  );
@@ -57993,11 +58434,7 @@ ${opts.schema}`;
57993
58434
  * Get session info
57994
58435
  */
57995
58436
  getSession() {
57996
- return {
57997
- id: session.id,
57998
- conversationId: session.conversationId,
57999
- messageCount: session.messageCount
58000
- };
58437
+ return session.getInfo();
58001
58438
  },
58002
58439
  /**
58003
58440
  * Clean up - MUST be called to stop MCP server and clean resources
@@ -58178,40 +58615,285 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
58178
58615
  }
58179
58616
  return systemPrompt || "";
58180
58617
  }
58181
- var ClaudeSession;
58182
58618
  var init_enhanced_claude_code = __esm({
58183
58619
  "src/agent/engines/enhanced-claude-code.js"() {
58184
58620
  "use strict";
58185
58621
  init_built_in_server();
58186
- ClaudeSession = class {
58187
- constructor(id, debug = false) {
58188
- this.id = id;
58189
- this.conversationId = null;
58190
- this.messageCount = 0;
58191
- this.debug = debug;
58622
+ init_Session();
58623
+ }
58624
+ });
58625
+
58626
+ // src/agent/engines/codex.js
58627
+ var codex_exports = {};
58628
+ __export(codex_exports, {
58629
+ createCodexEngine: () => createCodexEngine
58630
+ });
58631
+ import { spawn as spawn4 } from "child_process";
58632
+ import { randomBytes as randomBytes2 } from "crypto";
58633
+ import { createInterface } from "readline";
58634
+ async function createCodexEngine(options = {}) {
58635
+ const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, model } = options;
58636
+ const session = new Session(
58637
+ sessionId || randomBytes2(8).toString("hex"),
58638
+ debug
58639
+ );
58640
+ let mcpServer = null;
58641
+ let mcpServerUrl = null;
58642
+ let mcpServerName = null;
58643
+ if (agent) {
58644
+ mcpServer = new BuiltInMCPServer(agent, {
58645
+ port: 0,
58646
+ host: "127.0.0.1",
58647
+ debug
58648
+ });
58649
+ const { host, port } = await mcpServer.start();
58650
+ mcpServerUrl = `http://${host}:${port}/mcp`;
58651
+ mcpServerName = `probe_${session.id}`;
58652
+ if (debug) {
58653
+ console.log("[DEBUG] Built-in Probe MCP server started");
58654
+ console.log("[DEBUG] Probe MCP URL:", mcpServerUrl);
58655
+ }
58656
+ }
58657
+ if (debug) {
58658
+ console.log("[DEBUG] Starting Codex MCP server...");
58659
+ }
58660
+ const codexProcess = spawn4("codex", ["mcp-server"], {
58661
+ stdio: ["pipe", "pipe", "pipe"]
58662
+ });
58663
+ let requestId = 0;
58664
+ const pendingRequests = /* @__PURE__ */ new Map();
58665
+ const eventHandlers = /* @__PURE__ */ new Map();
58666
+ const stdoutReader = createInterface({
58667
+ input: codexProcess.stdout,
58668
+ crlfDelay: Infinity
58669
+ });
58670
+ stdoutReader.on("line", (line) => {
58671
+ try {
58672
+ const message = JSON.parse(line);
58673
+ if (debug) {
58674
+ if (message.method === "codex/event") {
58675
+ console.log(`[DEBUG] Codex event: ${message.params?.msg?.type}`);
58676
+ }
58192
58677
  }
58193
- /**
58194
- * Update session with Claude's conversation ID
58195
- */
58196
- setConversationId(convId) {
58197
- this.conversationId = convId;
58198
- if (this.debug) {
58199
- console.log(`[Session ${this.id}] Conversation ID: ${convId}`);
58678
+ if (message.id !== void 0 && pendingRequests.has(message.id)) {
58679
+ const { resolve: resolve6, reject: reject2 } = pendingRequests.get(message.id);
58680
+ pendingRequests.delete(message.id);
58681
+ if (message.error) {
58682
+ reject2(new Error(message.error.message || JSON.stringify(message.error)));
58683
+ } else {
58684
+ resolve6(message.result);
58200
58685
  }
58201
58686
  }
58202
- /**
58203
- * Get resume arguments for continuing conversation
58204
- */
58205
- getResumeArgs() {
58206
- if (this.conversationId && this.messageCount > 0) {
58207
- return ["--resume", this.conversationId];
58687
+ if (message.method === "codex/event" && message.params) {
58688
+ const requestId2 = message.params._meta?.requestId;
58689
+ if (requestId2 !== void 0 && eventHandlers.has(requestId2)) {
58690
+ eventHandlers.get(requestId2)(message.params);
58208
58691
  }
58209
- return [];
58210
58692
  }
58211
- incrementMessageCount() {
58212
- this.messageCount++;
58693
+ } catch (e) {
58694
+ if (debug) {
58695
+ console.error("[DEBUG] Failed to parse message:", line);
58213
58696
  }
58214
- };
58697
+ }
58698
+ });
58699
+ if (debug) {
58700
+ codexProcess.stderr.on("data", (data) => {
58701
+ console.error("[CODEX STDERR]", data.toString());
58702
+ });
58703
+ }
58704
+ function sendRequest(method, params = {}) {
58705
+ return new Promise((resolve6, reject2) => {
58706
+ const id = ++requestId;
58707
+ const request = {
58708
+ jsonrpc: "2.0",
58709
+ id,
58710
+ method,
58711
+ params
58712
+ };
58713
+ pendingRequests.set(id, { resolve: resolve6, reject: reject2 });
58714
+ setTimeout(() => {
58715
+ if (pendingRequests.has(id)) {
58716
+ pendingRequests.delete(id);
58717
+ reject2(new Error(`Request ${method} timed out after 10 minutes`));
58718
+ }
58719
+ }, 6e5);
58720
+ codexProcess.stdin.write(JSON.stringify(request) + "\n");
58721
+ });
58722
+ }
58723
+ await sendRequest("initialize", {
58724
+ protocolVersion: "2024-11-05",
58725
+ capabilities: { tools: {} },
58726
+ clientInfo: {
58727
+ name: "probe-codex-client",
58728
+ version: "1.0.0"
58729
+ }
58730
+ });
58731
+ if (debug) {
58732
+ console.log("[DEBUG] Connected to Codex MCP server");
58733
+ console.log("[DEBUG] Session:", session.id);
58734
+ }
58735
+ const fullPrompt = combinePrompts2(systemPrompt, customPrompt, agent);
58736
+ return {
58737
+ sessionId: session.id,
58738
+ session,
58739
+ /**
58740
+ * Query Codex via MCP protocol with event streaming
58741
+ */
58742
+ async *query(prompt, opts = {}) {
58743
+ let finalPrompt = prompt;
58744
+ if (!session.conversationId && fullPrompt) {
58745
+ finalPrompt = `${fullPrompt}
58746
+
58747
+ ${prompt}`;
58748
+ }
58749
+ const isFollowUp = session.conversationId !== null;
58750
+ const toolName = isFollowUp ? "codex-reply" : "codex";
58751
+ const toolArgs = { prompt: finalPrompt };
58752
+ if (isFollowUp) {
58753
+ toolArgs.conversationId = session.conversationId;
58754
+ if (debug) {
58755
+ console.log(`[DEBUG] Follow-up with conversationId: ${session.conversationId}`);
58756
+ }
58757
+ } else {
58758
+ if (model) {
58759
+ toolArgs.model = model;
58760
+ }
58761
+ if (mcpServerUrl && mcpServerName) {
58762
+ toolArgs.config = {
58763
+ mcp_servers: {
58764
+ [mcpServerName]: { url: mcpServerUrl }
58765
+ }
58766
+ };
58767
+ }
58768
+ if (debug) {
58769
+ console.log(`[DEBUG] Initial query with tool: ${toolName}`);
58770
+ }
58771
+ }
58772
+ try {
58773
+ const reqId = requestId + 1;
58774
+ let fullResponse = "";
58775
+ let gotSessionId = false;
58776
+ const eventPromise = new Promise((resolve6) => {
58777
+ eventHandlers.set(reqId, (eventParams) => {
58778
+ const msg = eventParams.msg;
58779
+ if (msg.type === "session_configured" && msg.session_id && !gotSessionId) {
58780
+ session.setConversationId(msg.session_id);
58781
+ gotSessionId = true;
58782
+ }
58783
+ if (msg.type === "raw_response_item" && msg.item?.role === "assistant") {
58784
+ const content = msg.item.content;
58785
+ if (Array.isArray(content)) {
58786
+ for (const part of content) {
58787
+ if (part.type === "text" && part.text) {
58788
+ fullResponse += part.text;
58789
+ }
58790
+ }
58791
+ }
58792
+ }
58793
+ });
58794
+ setTimeout(() => {
58795
+ eventHandlers.delete(reqId);
58796
+ resolve6();
58797
+ }, 6e5);
58798
+ });
58799
+ const resultPromise = sendRequest("tools/call", {
58800
+ name: toolName,
58801
+ arguments: toolArgs
58802
+ });
58803
+ const result = await resultPromise;
58804
+ eventHandlers.delete(reqId);
58805
+ if (result && result.content && Array.isArray(result.content)) {
58806
+ for (const item of result.content) {
58807
+ if (item.type === "text" && item.text) {
58808
+ yield {
58809
+ type: "text",
58810
+ content: item.text
58811
+ };
58812
+ fullResponse = item.text;
58813
+ }
58814
+ }
58815
+ }
58816
+ if (fullResponse && (!result.content || result.content.length === 0)) {
58817
+ yield {
58818
+ type: "text",
58819
+ content: fullResponse
58820
+ };
58821
+ }
58822
+ session.incrementMessageCount();
58823
+ yield {
58824
+ type: "metadata",
58825
+ data: {
58826
+ sessionId: session.id,
58827
+ conversationId: session.conversationId,
58828
+ messageCount: session.messageCount
58829
+ }
58830
+ };
58831
+ } catch (error) {
58832
+ if (debug) {
58833
+ console.error("[DEBUG] Codex query error:", error);
58834
+ }
58835
+ yield {
58836
+ type: "error",
58837
+ error
58838
+ };
58839
+ }
58840
+ },
58841
+ /**
58842
+ * Get session info
58843
+ */
58844
+ getSession() {
58845
+ return session.getInfo();
58846
+ },
58847
+ /**
58848
+ * Clean up resources
58849
+ */
58850
+ async close() {
58851
+ try {
58852
+ if (stdoutReader) {
58853
+ stdoutReader.close();
58854
+ if (debug) {
58855
+ console.log("[DEBUG] Closed stdout reader");
58856
+ }
58857
+ }
58858
+ pendingRequests.clear();
58859
+ eventHandlers.clear();
58860
+ if (codexProcess && !codexProcess.killed) {
58861
+ codexProcess.kill();
58862
+ if (debug) {
58863
+ console.log("[DEBUG] Killed Codex MCP server process");
58864
+ }
58865
+ }
58866
+ if (mcpServer) {
58867
+ await mcpServer.stop();
58868
+ if (debug) {
58869
+ console.log("[DEBUG] Stopped Probe MCP server");
58870
+ }
58871
+ }
58872
+ if (debug) {
58873
+ console.log("[DEBUG] Engine closed, session:", session.id);
58874
+ }
58875
+ } catch (error) {
58876
+ if (debug) {
58877
+ console.error("[DEBUG] Error during cleanup:", error.message);
58878
+ }
58879
+ }
58880
+ }
58881
+ };
58882
+ }
58883
+ function combinePrompts2(systemPrompt, customPrompt, agent) {
58884
+ if (!systemPrompt && customPrompt) {
58885
+ return customPrompt;
58886
+ }
58887
+ if (systemPrompt && customPrompt) {
58888
+ return systemPrompt + "\n\n## Additional Instructions\n" + customPrompt;
58889
+ }
58890
+ return systemPrompt || "";
58891
+ }
58892
+ var init_codex = __esm({
58893
+ "src/agent/engines/codex.js"() {
58894
+ "use strict";
58895
+ init_built_in_server();
58896
+ init_Session();
58215
58897
  }
58216
58898
  });
58217
58899
 
@@ -58294,7 +58976,7 @@ import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
58294
58976
  import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
58295
58977
  import { createAmazonBedrock as createAmazonBedrock2 } from "@ai-sdk/amazon-bedrock";
58296
58978
  import { streamText as streamText2 } from "ai";
58297
- import { randomUUID as randomUUID4 } from "crypto";
58979
+ import { randomUUID as randomUUID5 } from "crypto";
58298
58980
  import { EventEmitter as EventEmitter5 } from "events";
58299
58981
  import { existsSync as existsSync5 } from "fs";
58300
58982
  import { readFile, stat } from "fs/promises";
@@ -58314,6 +58996,7 @@ var init_ProbeAgent = __esm({
58314
58996
  init_index();
58315
58997
  init_schemaUtils();
58316
58998
  init_xmlParsingUtils();
58999
+ init_prompts();
58317
59000
  init_mcp();
58318
59001
  init_RetryManager();
58319
59002
  init_FallbackManager();
@@ -58335,6 +59018,7 @@ var init_ProbeAgent = __esm({
58335
59018
  * @param {Object} options - Configuration options
58336
59019
  * @param {string} [options.sessionId] - Optional session ID
58337
59020
  * @param {string} [options.customPrompt] - Custom prompt to replace the default system message
59021
+ * @param {string} [options.systemPrompt] - Alias for customPrompt; takes precedence when both are provided
58338
59022
  * @param {string} [options.promptType] - Predefined prompt type (architect, code-review, support)
58339
59023
  * @param {boolean} [options.allowEdit=false] - Allow the use of the 'implement' tool
58340
59024
  * @param {boolean} [options.enableDelegate=false] - Enable the delegate tool for task distribution to subagents
@@ -58369,8 +59053,8 @@ var init_ProbeAgent = __esm({
58369
59053
  * @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
58370
59054
  */
58371
59055
  constructor(options = {}) {
58372
- this.sessionId = options.sessionId || randomUUID4();
58373
- this.customPrompt = options.customPrompt || null;
59056
+ this.sessionId = options.sessionId || randomUUID5();
59057
+ this.customPrompt = options.systemPrompt || options.customPrompt || null;
58374
59058
  this.promptType = options.promptType || "code-explorer";
58375
59059
  this.allowEdit = !!options.allowEdit;
58376
59060
  this.enableDelegate = !!options.enableDelegate;
@@ -58494,9 +59178,10 @@ var init_ProbeAgent = __esm({
58494
59178
  * This method initializes MCP and merges MCP tools into the tool list, and loads history from storage
58495
59179
  */
58496
59180
  async initialize() {
58497
- if (!this.provider && !this.clientApiProvider && this.apiType !== "claude-code") {
59181
+ if (!this.provider && !this.clientApiProvider && this.apiType !== "claude-code" && this.apiType !== "codex") {
58498
59182
  if (this.apiType === "uninitialized") {
58499
59183
  const claudeAvailable = await this.isClaudeCommandAvailable();
59184
+ const codexAvailable = await this.isCodexCommandAvailable();
58500
59185
  if (claudeAvailable) {
58501
59186
  if (this.debug) {
58502
59187
  console.log("[DEBUG] No API keys found, but claude command detected");
@@ -58506,8 +59191,17 @@ var init_ProbeAgent = __esm({
58506
59191
  this.provider = null;
58507
59192
  this.model = this.clientApiModel || "claude-3-5-sonnet-20241022";
58508
59193
  this.apiType = "claude-code";
59194
+ } else if (codexAvailable) {
59195
+ if (this.debug) {
59196
+ console.log("[DEBUG] No API keys found, but codex command detected");
59197
+ console.log("[DEBUG] Auto-switching to codex provider");
59198
+ }
59199
+ this.clientApiProvider = "codex";
59200
+ this.provider = null;
59201
+ this.model = this.clientApiModel || "gpt-4o";
59202
+ this.apiType = "codex";
58509
59203
  } else {
58510
- throw new Error("No API key provided and claude command not 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");
59204
+ 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
59205
  }
58512
59206
  }
58513
59207
  }
@@ -58629,13 +59323,33 @@ var init_ProbeAgent = __esm({
58629
59323
  }
58630
59324
  /**
58631
59325
  * Check if claude command is available on the system
59326
+ * Uses execFile instead of exec to avoid shell injection risks
58632
59327
  * @returns {Promise<boolean>} True if claude command is available
58633
59328
  * @private
58634
59329
  */
58635
59330
  async isClaudeCommandAvailable() {
58636
59331
  try {
58637
- const { execSync } = await import("child_process");
58638
- execSync("claude --version", { stdio: "ignore" });
59332
+ const { execFile: execFile3 } = await import("child_process");
59333
+ const { promisify: promisify8 } = await import("util");
59334
+ const execFileAsync3 = promisify8(execFile3);
59335
+ await execFileAsync3("claude", ["--version"], { timeout: 5e3 });
59336
+ return true;
59337
+ } catch (error) {
59338
+ return false;
59339
+ }
59340
+ }
59341
+ /**
59342
+ * Check if codex command is available on the system
59343
+ * Uses execFile instead of exec to avoid shell injection risks
59344
+ * @returns {Promise<boolean>} True if codex command is available
59345
+ * @private
59346
+ */
59347
+ async isCodexCommandAvailable() {
59348
+ try {
59349
+ const { execFile: execFile3 } = await import("child_process");
59350
+ const { promisify: promisify8 } = await import("util");
59351
+ const execFileAsync3 = promisify8(execFile3);
59352
+ await execFileAsync3("codex", ["--version"], { timeout: 5e3 });
58639
59353
  return true;
58640
59354
  } catch (error) {
58641
59355
  return false;
@@ -58659,6 +59373,20 @@ var init_ProbeAgent = __esm({
58659
59373
  }
58660
59374
  return;
58661
59375
  }
59376
+ if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
59377
+ this.provider = null;
59378
+ this.model = modelName || null;
59379
+ this.apiType = "codex";
59380
+ if (this.debug) {
59381
+ console.log("[DEBUG] Codex CLI engine selected - will use built-in access if available");
59382
+ if (this.model) {
59383
+ console.log(`[DEBUG] Using model: ${this.model}`);
59384
+ } else {
59385
+ console.log("[DEBUG] Using Codex account default model");
59386
+ }
59387
+ }
59388
+ return;
59389
+ }
58662
59390
  const anthropicApiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
58663
59391
  const openaiApiKey = process.env.OPENAI_API_KEY;
58664
59392
  const googleApiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY;
@@ -58820,6 +59548,44 @@ var init_ProbeAgent = __esm({
58820
59548
  }
58821
59549
  }
58822
59550
  }
59551
+ if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
59552
+ try {
59553
+ const engine = await this.getEngine();
59554
+ if (engine && engine.query) {
59555
+ const userMessages = options.messages.filter(
59556
+ (m) => m.role === "user" && !m.content.includes("WARNING: You have reached the maximum tool iterations limit")
59557
+ );
59558
+ const lastUserMessage = userMessages[userMessages.length - 1];
59559
+ const prompt = lastUserMessage ? lastUserMessage.content : "";
59560
+ const engineOptions = {
59561
+ maxTokens: options.maxTokens,
59562
+ temperature: options.temperature,
59563
+ messages: options.messages,
59564
+ systemPrompt: options.messages.find((m) => m.role === "system")?.content
59565
+ };
59566
+ const engineStream = engine.query(prompt, engineOptions);
59567
+ async function* createTextStream() {
59568
+ for await (const message of engineStream) {
59569
+ if (message.type === "text" && message.content) {
59570
+ yield message.content;
59571
+ } else if (typeof message === "string") {
59572
+ yield message;
59573
+ }
59574
+ }
59575
+ }
59576
+ return {
59577
+ textStream: createTextStream(),
59578
+ usage: Promise.resolve({})
59579
+ // Engine should handle its own usage tracking
59580
+ // Add other streamText-compatible properties as needed
59581
+ };
59582
+ }
59583
+ } catch (error) {
59584
+ if (this.debug) {
59585
+ console.log(`[DEBUG] Failed to use Codex engine, falling back to Vercel:`, error.message);
59586
+ }
59587
+ }
59588
+ }
58823
59589
  if (!this.retryManager) {
58824
59590
  this.retryManager = new RetryManager({
58825
59591
  maxRetries: this.retryConfig.maxRetries ?? 3,
@@ -58972,6 +59738,35 @@ var init_ProbeAgent = __esm({
58972
59738
  this.clientApiProvider = null;
58973
59739
  }
58974
59740
  }
59741
+ if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
59742
+ try {
59743
+ const { createCodexEngine: createCodexEngine2 } = await Promise.resolve().then(() => (init_codex(), codex_exports));
59744
+ const systemPrompt = this.customPrompt || this.getCodexNativeSystemPrompt();
59745
+ this.engine = await createCodexEngine2({
59746
+ agent: this,
59747
+ // Pass reference to ProbeAgent for tool access
59748
+ systemPrompt,
59749
+ customPrompt: this.customPrompt,
59750
+ sessionId: this.options?.sessionId,
59751
+ debug: this.debug,
59752
+ allowedTools: this.allowedTools,
59753
+ // Pass tool filtering configuration
59754
+ model: this.model
59755
+ // Pass model name (e.g., gpt-4o, o3, etc.)
59756
+ });
59757
+ if (this.debug) {
59758
+ console.log("[DEBUG] Using Codex CLI engine with Probe tools");
59759
+ if (this.customPrompt) {
59760
+ console.log("[DEBUG] Using custom prompt/persona");
59761
+ }
59762
+ }
59763
+ return this.engine;
59764
+ } catch (error) {
59765
+ console.warn("[WARNING] Failed to load Codex CLI engine:", error.message);
59766
+ console.warn("[WARNING] Falling back to Vercel AI SDK");
59767
+ this.clientApiProvider = null;
59768
+ }
59769
+ }
58975
59770
  const { createEnhancedVercelEngine: createEnhancedVercelEngine2 } = await Promise.resolve().then(() => (init_enhanced_vercel(), enhanced_vercel_exports));
58976
59771
  this.engine = createEnhancedVercelEngine2(this);
58977
59772
  if (this.debug) {
@@ -58979,6 +59774,32 @@ var init_ProbeAgent = __esm({
58979
59774
  }
58980
59775
  return this.engine;
58981
59776
  }
59777
+ /**
59778
+ * Get session information including thread ID for resumability
59779
+ * @returns {Object} Session info with sessionId, threadId, messageCount
59780
+ */
59781
+ getSessionInfo() {
59782
+ if (this.engine && this.engine.getSession) {
59783
+ return this.engine.getSession();
59784
+ }
59785
+ return {
59786
+ id: this.sessionId,
59787
+ threadId: null,
59788
+ messageCount: 0
59789
+ };
59790
+ }
59791
+ /**
59792
+ * Close the agent and clean up resources (e.g., MCP servers)
59793
+ * @returns {Promise<void>}
59794
+ */
59795
+ async close() {
59796
+ if (this.engine && this.engine.close) {
59797
+ await this.engine.close();
59798
+ }
59799
+ if (this.mcpBridge) {
59800
+ this.mcpBridge = null;
59801
+ }
59802
+ }
58982
59803
  /**
58983
59804
  * Process assistant response content and detect/load image references
58984
59805
  * @param {string} content - The assistant's response content
@@ -59271,11 +60092,61 @@ var init_ProbeAgent = __esm({
59271
60092
  */
59272
60093
  getClaudeNativeSystemPrompt() {
59273
60094
  let systemPrompt = "";
59274
- if (this.predefinedPrompt) {
59275
- const personaPrompt = getPromptByType(this.predefinedPrompt);
59276
- if (personaPrompt?.system) {
59277
- systemPrompt += personaPrompt.system + "\n\n";
59278
- }
60095
+ if (this.customPrompt) {
60096
+ systemPrompt += this.customPrompt + "\n\n";
60097
+ } else if (this.promptType && predefinedPrompts[this.promptType]) {
60098
+ systemPrompt += predefinedPrompts[this.promptType] + "\n\n";
60099
+ } else {
60100
+ systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
60101
+ }
60102
+ systemPrompt += `You have access to powerful code search and analysis tools through MCP:
60103
+ - search: Find code patterns using semantic search
60104
+ - extract: Extract specific code sections with context
60105
+ - query: Use AST patterns for structural code matching
60106
+ - listFiles: Browse directory contents
60107
+ - searchFiles: Find files by name patterns`;
60108
+ if (this.enableBash) {
60109
+ systemPrompt += `
60110
+ - bash: Execute bash commands for system operations`;
60111
+ }
60112
+ systemPrompt += `
60113
+
60114
+ When exploring code:
60115
+ 1. Start with search to find relevant code patterns
60116
+ 2. Use extract to get detailed context when needed
60117
+ 3. Prefer focused, specific searches over broad queries
60118
+ 4. Combine multiple tools to build complete understanding`;
60119
+ if (this.allowedFolders && this.allowedFolders.length > 0) {
60120
+ systemPrompt += `
60121
+
60122
+ Workspace: ${this.allowedFolders.join(", ")}`;
60123
+ }
60124
+ if (this.fileList) {
60125
+ systemPrompt += `
60126
+
60127
+ # Repository Structure
60128
+ `;
60129
+ systemPrompt += `You are working with a repository located at: ${this.allowedFolders[0]}
60130
+
60131
+ `;
60132
+ systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
60133
+
60134
+ `;
60135
+ systemPrompt += "```\n" + this.fileList + "\n```\n";
60136
+ }
60137
+ return systemPrompt;
60138
+ }
60139
+ /**
60140
+ * Get system prompt for Codex CLI (similar to Claude but optimized for Codex)
60141
+ */
60142
+ getCodexNativeSystemPrompt() {
60143
+ let systemPrompt = "";
60144
+ if (this.customPrompt) {
60145
+ systemPrompt += this.customPrompt + "\n\n";
60146
+ } else if (this.promptType && predefinedPrompts[this.promptType]) {
60147
+ systemPrompt += predefinedPrompts[this.promptType] + "\n\n";
60148
+ } else {
60149
+ systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
59279
60150
  }
59280
60151
  systemPrompt += `You have access to powerful code search and analysis tools through MCP:
59281
60152
  - search: Find code patterns using semantic search
@@ -59471,7 +60342,7 @@ Follow these instructions carefully:
59471
60342
  - Use 'create' for new files or complete file rewrites` : ""}
59472
60343
  </instructions>
59473
60344
  `;
59474
- const predefinedPrompts = {
60345
+ const predefinedPrompts2 = {
59475
60346
  "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
60347
 
59477
60348
  When exploring code:
@@ -59527,14 +60398,14 @@ When troubleshooting:
59527
60398
  if (this.debug) {
59528
60399
  console.log(`[DEBUG] Using custom prompt`);
59529
60400
  }
59530
- } else if (this.promptType && predefinedPrompts[this.promptType]) {
59531
- systemMessage = "<role>" + predefinedPrompts[this.promptType] + "</role>";
60401
+ } else if (this.promptType && predefinedPrompts2[this.promptType]) {
60402
+ systemMessage = "<role>" + predefinedPrompts2[this.promptType] + "</role>";
59532
60403
  if (this.debug) {
59533
60404
  console.log(`[DEBUG] Using predefined prompt: ${this.promptType}`);
59534
60405
  }
59535
60406
  systemMessage += commonInstructions;
59536
60407
  } else {
59537
- systemMessage = "<role>" + predefinedPrompts["code-explorer"] + "</role>";
60408
+ systemMessage = "<role>" + predefinedPrompts2["code-explorer"] + "</role>";
59538
60409
  if (this.debug) {
59539
60410
  console.log(`[DEBUG] Using default prompt: code explorer`);
59540
60411
  }
@@ -59675,6 +60546,7 @@ You are working with a repository located at: ${searchDirectory}
59675
60546
  const baseMaxIterations = this.maxIterations || MAX_TOOL_ITERATIONS;
59676
60547
  const maxIterations = options.schema ? baseMaxIterations + 4 : baseMaxIterations;
59677
60548
  const isClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
60549
+ const isCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
59678
60550
  if (isClaudeCode) {
59679
60551
  if (this.debug) {
59680
60552
  console.log(`[DEBUG] Using Claude Code engine - bypassing tool loop (black box mode)`);
@@ -59727,6 +60599,58 @@ You are working with a repository located at: ${searchDirectory}
59727
60599
  throw error;
59728
60600
  }
59729
60601
  }
60602
+ if (isCodex) {
60603
+ if (this.debug) {
60604
+ console.log(`[DEBUG] Using Codex engine - bypassing tool loop (black box mode)`);
60605
+ console.log(`[DEBUG] Sending question directly to Codex: ${message.substring(0, 100)}...`);
60606
+ }
60607
+ try {
60608
+ const engine = await this.getEngine();
60609
+ if (engine && engine.query) {
60610
+ let assistantResponseContent = "";
60611
+ let toolBatch = null;
60612
+ for await (const chunk of engine.query(message, options)) {
60613
+ if (chunk.type === "text" && chunk.content) {
60614
+ assistantResponseContent += chunk.content;
60615
+ if (options.onStream) {
60616
+ options.onStream(chunk.content);
60617
+ }
60618
+ } else if (chunk.type === "toolBatch" && chunk.tools) {
60619
+ toolBatch = chunk.tools;
60620
+ if (this.debug) {
60621
+ console.log(`[DEBUG] Received batch of ${chunk.tools.length} tool events from Codex`);
60622
+ }
60623
+ } else if (chunk.type === "error") {
60624
+ throw chunk.error;
60625
+ }
60626
+ }
60627
+ if (toolBatch && toolBatch.length > 0 && this.events) {
60628
+ if (this.debug) {
60629
+ console.log(`[DEBUG] Emitting ${toolBatch.length} tool events from Codex batch`);
60630
+ }
60631
+ for (const toolEvent of toolBatch) {
60632
+ this.events.emit("toolCall", toolEvent);
60633
+ }
60634
+ }
60635
+ this.history.push(userMessage);
60636
+ this.history.push({
60637
+ role: "assistant",
60638
+ content: assistantResponseContent
60639
+ });
60640
+ await this.hooks.emit(HOOK_TYPES.COMPLETION, {
60641
+ sessionId: this.sessionId,
60642
+ prompt: message,
60643
+ response: assistantResponseContent
60644
+ });
60645
+ return assistantResponseContent;
60646
+ }
60647
+ } catch (error) {
60648
+ if (this.debug) {
60649
+ console.error("[DEBUG] Codex error:", error);
60650
+ }
60651
+ throw error;
60652
+ }
60653
+ }
59730
60654
  if (this.debug) {
59731
60655
  console.log(`[DEBUG] Starting agentic flow for question: ${message.substring(0, 100)}...`);
59732
60656
  if (options.schema) {
@@ -60607,7 +61531,7 @@ Convert your previous response content into actual JSON data that follows this s
60607
61531
  */
60608
61532
  clone(options = {}) {
60609
61533
  const {
60610
- sessionId = randomUUID4(),
61534
+ sessionId = randomUUID5(),
60611
61535
  stripInternalMessages = true,
60612
61536
  keepSystemMessage = true,
60613
61537
  deepCopy = true,
@@ -60826,7 +61750,7 @@ import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
60826
61750
  import { resolve as resolve5 } from "path";
60827
61751
 
60828
61752
  // src/agent/acp/server.js
60829
- import { randomUUID as randomUUID5 } from "crypto";
61753
+ import { randomUUID as randomUUID6 } from "crypto";
60830
61754
 
60831
61755
  // src/agent/acp/connection.js
60832
61756
  import { EventEmitter as EventEmitter6 } from "events";
@@ -61318,7 +62242,7 @@ var ACPServer = class {
61318
62242
  * Handle new session request
61319
62243
  */
61320
62244
  async handleNewSession(params) {
61321
- const sessionId = params?.sessionId || randomUUID5();
62245
+ const sessionId = params?.sessionId || randomUUID6();
61322
62246
  const mode = params?.mode || SessionMode.NORMAL;
61323
62247
  const session = new ACPSession(sessionId, mode);
61324
62248
  this.sessions.set(sessionId, session);
@@ -61490,7 +62414,7 @@ var ACPServer = class {
61490
62414
  };
61491
62415
 
61492
62416
  // src/agent/acp/tools.js
61493
- import { randomUUID as randomUUID6 } from "crypto";
62417
+ import { randomUUID as randomUUID7 } from "crypto";
61494
62418
 
61495
62419
  // src/agent/index.js
61496
62420
  dotenv3.config();