@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.
@@ -5308,11 +5308,11 @@ var require_randomUUID = __commonJS({
5308
5308
  var require_dist_cjs19 = __commonJS({
5309
5309
  "node_modules/@smithy/uuid/dist-cjs/index.js"(exports2) {
5310
5310
  "use strict";
5311
- var randomUUID5 = require_randomUUID();
5311
+ var randomUUID6 = require_randomUUID();
5312
5312
  var decimalToHex = Array.from({ length: 256 }, (_, i4) => i4.toString(16).padStart(2, "0"));
5313
5313
  var v4 = () => {
5314
- if (randomUUID5.randomUUID) {
5315
- return randomUUID5.randomUUID();
5314
+ if (randomUUID6.randomUUID) {
5315
+ return randomUUID6.randomUUID();
5316
5316
  }
5317
5317
  const rnds = new Uint8Array(16);
5318
5318
  crypto.getRandomValues(rnds);
@@ -34323,8 +34323,8 @@ var init_vercel = __esm({
34323
34323
  const { writeFileSync: writeFileSync2, unlinkSync } = await import("fs");
34324
34324
  const { join: join3 } = await import("path");
34325
34325
  const { tmpdir } = await import("os");
34326
- const { randomUUID: randomUUID5 } = await import("crypto");
34327
- tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID5()}.txt`);
34326
+ const { randomUUID: randomUUID6 } = await import("crypto");
34327
+ tempFilePath = join3(tmpdir(), `probe-extract-${randomUUID6()}.txt`);
34328
34328
  writeFileSync2(tempFilePath, input_content);
34329
34329
  if (debug) {
34330
34330
  console.error(`Created temporary file for input content: ${tempFilePath}`);
@@ -81658,6 +81658,126 @@ Provide only the corrected Mermaid diagram within a mermaid code block. Do not a
81658
81658
  }
81659
81659
  });
81660
81660
 
81661
+ // src/agent/shared/prompts.js
81662
+ var predefinedPrompts;
81663
+ var init_prompts = __esm({
81664
+ "src/agent/shared/prompts.js"() {
81665
+ "use strict";
81666
+ predefinedPrompts = {
81667
+ "code-explorer": `You are ProbeChat Code Explorer - an AI assistant focused on reading and explaining code using Probe's semantic search capabilities.
81668
+
81669
+ Your primary role is to explore codebases, understand code structure, and provide clear explanations. You should:
81670
+
81671
+ 1. Use the 'search' tool to find relevant code snippets across the codebase
81672
+ 2. Use the 'query' tool to locate specific symbols, functions, or classes
81673
+ 3. Use the 'extract' tool to get full context for files or specific code blocks
81674
+ 4. Explain code behavior, architecture patterns, and relationships between components
81675
+ 5. Provide concise summaries with key insights highlighted
81676
+
81677
+ When exploring code:
81678
+ - Start with targeted searches to find relevant areas
81679
+ - Extract full context when you need to understand implementation details
81680
+ - Trace function calls and data flow to understand how components interact
81681
+ - Focus on "why" and "how" rather than just describing what the code does
81682
+
81683
+ You should NOT:
81684
+ - Make changes to the codebase (read-only access)
81685
+ - Execute or run code
81686
+ - Make assumptions without verifying through search/query/extract`,
81687
+ "architect": `You are ProbeChat Architect - a senior software architect specialized in analyzing and designing software systems.
81688
+
81689
+ Your role is to:
81690
+
81691
+ 1. Analyze existing codebases to understand architecture patterns and design decisions
81692
+ 2. Identify architectural issues, technical debt, and improvement opportunities
81693
+ 3. Propose refactoring strategies and architectural changes
81694
+ 4. Design new features that fit well with existing architecture
81695
+ 5. Create high-level architecture diagrams and documentation
81696
+
81697
+ When analyzing architecture:
81698
+ - Use search/query/extract to understand component boundaries and dependencies
81699
+ - Identify layers, modules, and their responsibilities
81700
+ - Look for patterns like MVC, microservices, event-driven, etc.
81701
+ - Assess coupling, cohesion, and separation of concerns
81702
+ - Consider scalability, maintainability, and testability
81703
+
81704
+ When proposing changes:
81705
+ - Provide clear rationale backed by architectural principles
81706
+ - Consider migration paths and backwards compatibility
81707
+ - Identify risks and tradeoffs
81708
+ - Suggest incremental implementation steps`,
81709
+ "code-review": `You are ProbeChat Code Reviewer - a meticulous code reviewer focused on quality, best practices, and maintainability.
81710
+
81711
+ Your role is to:
81712
+
81713
+ 1. Review code changes for correctness, clarity, and best practices
81714
+ 2. Identify bugs, security issues, and performance problems
81715
+ 3. Suggest improvements for readability and maintainability
81716
+ 4. Ensure consistency with project conventions and patterns
81717
+ 5. Verify test coverage and edge case handling
81718
+
81719
+ When reviewing code:
81720
+ - Use search to find similar patterns in the codebase for consistency
81721
+ - Look for common issues: null checks, error handling, resource leaks
81722
+ - Check for security vulnerabilities: injection, XSS, etc.
81723
+ - Assess complexity and suggest simplifications
81724
+ - Verify naming conventions and code organization
81725
+
81726
+ Provide constructive feedback:
81727
+ - Start with what's good about the code
81728
+ - Be specific about issues with examples
81729
+ - Suggest concrete improvements with code snippets
81730
+ - Prioritize critical issues over style preferences
81731
+ - Explain the "why" behind your suggestions`,
81732
+ "engineer": `You are a senior engineer who helps implement features and fix bugs.
81733
+
81734
+ Your role is to:
81735
+
81736
+ 1. Implement new features following project conventions
81737
+ 2. Fix bugs by understanding root causes
81738
+ 3. Refactor code to improve quality
81739
+ 4. Write clear, maintainable code
81740
+ 5. Add appropriate tests and documentation
81741
+
81742
+ When implementing:
81743
+ - Use search/query to understand existing patterns
81744
+ - Follow the project's coding style and conventions
81745
+ - Consider edge cases and error handling
81746
+ - Write self-documenting code with clear names
81747
+ - Add comments for complex logic
81748
+
81749
+ You have access to:
81750
+ - search: Find relevant code patterns
81751
+ - query: Locate specific symbols/functions
81752
+ - extract: Get full file context
81753
+ - implement: Create or modify files (use carefully)
81754
+ - delegate: Break down complex tasks`,
81755
+ "support": `You are ProbeChat Support - a helpful assistant focused on answering questions about codebases.
81756
+
81757
+ Your role is to:
81758
+
81759
+ 1. Answer questions about how code works
81760
+ 2. Help users locate specific functionality
81761
+ 3. Explain error messages and debugging approaches
81762
+ 4. Guide users to relevant documentation
81763
+ 5. Provide examples and usage patterns
81764
+
81765
+ When helping users:
81766
+ - Ask clarifying questions if the request is ambiguous
81767
+ - Use search/query to find relevant code quickly
81768
+ - Provide clear, step-by-step explanations
81769
+ - Include code examples when helpful
81770
+ - Point to relevant files and line numbers
81771
+
81772
+ You should be:
81773
+ - Patient and encouraging
81774
+ - Clear and concise
81775
+ - Thorough but not overwhelming
81776
+ - Honest about limitations (say "I don't know" when appropriate)`
81777
+ };
81778
+ }
81779
+ });
81780
+
81661
81781
  // src/agent/mcp/config.js
81662
81782
  function loadMCPConfigurationFromPath(configPath) {
81663
81783
  if (!configPath) {
@@ -83195,14 +83315,58 @@ var init_contextCompactor = __esm({
83195
83315
  });
83196
83316
 
83197
83317
  // src/agent/mcp/built-in-server.js
83198
- var import_http, import_events2, import_server, import_types3, BuiltInMCPServer;
83318
+ var import_http, import_events2, import_crypto5, import_server, import_sse2, import_streamableHttp, import_types3, InMemoryEventStore, BuiltInMCPServer;
83199
83319
  var init_built_in_server = __esm({
83200
83320
  "src/agent/mcp/built-in-server.js"() {
83201
83321
  "use strict";
83202
83322
  import_http = require("http");
83203
83323
  import_events2 = require("events");
83324
+ import_crypto5 = require("crypto");
83204
83325
  import_server = require("@modelcontextprotocol/sdk/server/index.js");
83326
+ import_sse2 = require("@modelcontextprotocol/sdk/server/sse.js");
83327
+ import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
83205
83328
  import_types3 = require("@modelcontextprotocol/sdk/types.js");
83329
+ InMemoryEventStore = class {
83330
+ constructor() {
83331
+ this.events = /* @__PURE__ */ new Map();
83332
+ }
83333
+ generateEventId(streamId) {
83334
+ return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
83335
+ }
83336
+ getStreamIdFromEventId(eventId) {
83337
+ const parts = eventId.split("_");
83338
+ return parts.length > 0 ? parts[0] : "";
83339
+ }
83340
+ async storeEvent(streamId, message) {
83341
+ const eventId = this.generateEventId(streamId);
83342
+ this.events.set(eventId, { streamId, message });
83343
+ return eventId;
83344
+ }
83345
+ async replayEventsAfter(lastEventId, { send }) {
83346
+ if (!lastEventId || !this.events.has(lastEventId)) {
83347
+ return "";
83348
+ }
83349
+ const streamId = this.getStreamIdFromEventId(lastEventId);
83350
+ if (!streamId) {
83351
+ return "";
83352
+ }
83353
+ let foundLastEvent = false;
83354
+ const sortedEvents = [...this.events.entries()].sort((a4, b4) => a4[0].localeCompare(b4[0]));
83355
+ for (const [eventId, { streamId: eventStreamId, message }] of sortedEvents) {
83356
+ if (eventStreamId !== streamId) {
83357
+ continue;
83358
+ }
83359
+ if (eventId === lastEventId) {
83360
+ foundLastEvent = true;
83361
+ continue;
83362
+ }
83363
+ if (foundLastEvent) {
83364
+ await send(eventId, message);
83365
+ }
83366
+ }
83367
+ return streamId;
83368
+ }
83369
+ };
83206
83370
  BuiltInMCPServer = class extends import_events2.EventEmitter {
83207
83371
  constructor(agent, options = {}) {
83208
83372
  super();
@@ -83211,6 +83375,8 @@ var init_built_in_server = __esm({
83211
83375
  this.host = options.host || "127.0.0.1";
83212
83376
  this.httpServer = null;
83213
83377
  this.mcpServer = null;
83378
+ this.sseTransports = /* @__PURE__ */ new Map();
83379
+ this.streamableTransports = /* @__PURE__ */ new Map();
83214
83380
  this.connections = /* @__PURE__ */ new Set();
83215
83381
  this.debug = options.debug || false;
83216
83382
  }
@@ -83232,11 +83398,13 @@ var init_built_in_server = __esm({
83232
83398
  });
83233
83399
  this.registerHandlers();
83234
83400
  return new Promise((resolve5, reject2) => {
83235
- this.httpServer.listen(this.port, this.host, () => {
83401
+ this.httpServer.listen(this.port, this.host, async () => {
83236
83402
  const address = this.httpServer.address();
83237
83403
  this.port = address.port;
83238
83404
  if (this.debug) {
83239
83405
  console.log(`[MCP] Built-in server started at http://${this.host}:${this.port}`);
83406
+ console.log(`[MCP] SSE endpoint: http://${this.host}:${this.port}/sse`);
83407
+ console.log(`[MCP] Messages endpoint: http://${this.host}:${this.port}/messages`);
83240
83408
  }
83241
83409
  this.emit("ready", { host: this.host, port: this.port });
83242
83410
  resolve5({ host: this.host, port: this.port });
@@ -83249,6 +83417,9 @@ var init_built_in_server = __esm({
83249
83417
  */
83250
83418
  handleRequest(req, res) {
83251
83419
  const { method, url } = req;
83420
+ if (this.debug) {
83421
+ console.log(`[MCP] Request: ${method} ${url}`);
83422
+ }
83252
83423
  res.setHeader("Access-Control-Allow-Origin", "*");
83253
83424
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
83254
83425
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
@@ -83258,15 +83429,22 @@ var init_built_in_server = __esm({
83258
83429
  return;
83259
83430
  }
83260
83431
  if (url === "/sse" && method === "GET") {
83261
- this.handleSSE(req, res);
83432
+ if (this.debug) {
83433
+ console.log("[MCP] Routing to handleSSEConnection");
83434
+ }
83435
+ this.handleSSEConnection(req, res);
83436
+ return;
83437
+ }
83438
+ if (url.startsWith("/messages") && method === "POST") {
83439
+ this.handleSSEMessage(req, res);
83262
83440
  return;
83263
83441
  }
83264
83442
  if (url === "/rpc" && method === "POST") {
83265
83443
  this.handleJSONRPC(req, res);
83266
83444
  return;
83267
83445
  }
83268
- if (url === "/mcp" && method === "POST") {
83269
- this.handleMCPProtocol(req, res);
83446
+ if (url === "/mcp") {
83447
+ this.handleStreamableHTTP(req, res);
83270
83448
  return;
83271
83449
  }
83272
83450
  if (url === "/health") {
@@ -83282,7 +83460,190 @@ var init_built_in_server = __esm({
83282
83460
  res.end("Not Found");
83283
83461
  }
83284
83462
  /**
83285
- * Handle Server-Sent Events connection
83463
+ * Handle SSE connection (GET /sse) - creates new transport
83464
+ */
83465
+ async handleSSEConnection(req, res) {
83466
+ if (this.debug) {
83467
+ console.log("[MCP] New SSE connection request");
83468
+ }
83469
+ const transport = new import_sse2.SSEServerTransport("/messages", res);
83470
+ this.sseTransports.set(transport.sessionId, transport);
83471
+ res.on("close", () => {
83472
+ if (this.debug) {
83473
+ console.log("[MCP] SSE connection closed, sessionId:", transport.sessionId);
83474
+ }
83475
+ this.sseTransports.delete(transport.sessionId);
83476
+ });
83477
+ try {
83478
+ await this.mcpServer.connect(transport);
83479
+ if (this.debug) {
83480
+ console.log("[MCP] MCP server connected to SSE transport, sessionId:", transport.sessionId);
83481
+ }
83482
+ } catch (error2) {
83483
+ if (this.debug) {
83484
+ console.error("[MCP] Error connecting MCP server to transport:", error2);
83485
+ }
83486
+ this.sseTransports.delete(transport.sessionId);
83487
+ }
83488
+ }
83489
+ /**
83490
+ * Handle SSE message (POST /messages?sessionId=...) - routes to existing transport
83491
+ */
83492
+ async handleSSEMessage(req, res) {
83493
+ const url = new URL(req.url, `http://${req.headers.host}`);
83494
+ const sessionId = url.searchParams.get("sessionId");
83495
+ if (!sessionId) {
83496
+ res.writeHead(400, { "Content-Type": "application/json" });
83497
+ res.end(JSON.stringify({
83498
+ jsonrpc: "2.0",
83499
+ error: {
83500
+ code: -32e3,
83501
+ message: "Bad Request: sessionId query parameter is required"
83502
+ },
83503
+ id: null
83504
+ }));
83505
+ return;
83506
+ }
83507
+ const transport = this.sseTransports.get(sessionId);
83508
+ if (!transport) {
83509
+ res.writeHead(400, { "Content-Type": "application/json" });
83510
+ res.end(JSON.stringify({
83511
+ jsonrpc: "2.0",
83512
+ error: {
83513
+ code: -32e3,
83514
+ message: `Bad Request: No transport found for sessionId: ${sessionId}`
83515
+ },
83516
+ id: null
83517
+ }));
83518
+ return;
83519
+ }
83520
+ let body = "";
83521
+ req.on("data", (chunk) => {
83522
+ body += chunk.toString();
83523
+ });
83524
+ req.on("end", async () => {
83525
+ try {
83526
+ const message = JSON.parse(body);
83527
+ await transport.handlePostMessage(req, res, message);
83528
+ } catch (error2) {
83529
+ res.writeHead(500, { "Content-Type": "application/json" });
83530
+ res.end(JSON.stringify({
83531
+ jsonrpc: "2.0",
83532
+ error: {
83533
+ code: -32603,
83534
+ message: "Internal error",
83535
+ data: error2.message
83536
+ },
83537
+ id: null
83538
+ }));
83539
+ }
83540
+ });
83541
+ }
83542
+ /**
83543
+ * Handle Streamable HTTP protocol (GET/POST/DELETE on /mcp)
83544
+ */
83545
+ async handleStreamableHTTP(req, res) {
83546
+ const { method } = req;
83547
+ if (this.debug) {
83548
+ console.log(`[MCP] Streamable HTTP ${method} request`);
83549
+ }
83550
+ try {
83551
+ let body = null;
83552
+ if (method === "POST") {
83553
+ body = await this.parseRequestBody(req);
83554
+ }
83555
+ const sessionId = req.headers["mcp-session-id"];
83556
+ let transport;
83557
+ if (sessionId && this.streamableTransports.has(sessionId)) {
83558
+ transport = this.streamableTransports.get(sessionId);
83559
+ if (this.debug) {
83560
+ console.log(`[MCP] Reusing existing transport for session: ${sessionId}`);
83561
+ }
83562
+ } else if (!sessionId && method === "POST" && body && (0, import_types3.isInitializeRequest)(body)) {
83563
+ if (this.debug) {
83564
+ console.log("[MCP] Creating new Streamable HTTP transport for initialization");
83565
+ }
83566
+ const eventStore = new InMemoryEventStore();
83567
+ transport = new import_streamableHttp.StreamableHTTPServerTransport({
83568
+ sessionIdGenerator: () => (0, import_crypto5.randomUUID)(),
83569
+ eventStore,
83570
+ // Enable resumability
83571
+ onsessioninitialized: (newSessionId) => {
83572
+ if (this.debug) {
83573
+ console.log(`[MCP] Streamable HTTP session initialized: ${newSessionId}`);
83574
+ }
83575
+ this.streamableTransports.set(newSessionId, transport);
83576
+ },
83577
+ onsessionclosed: (closedSessionId) => {
83578
+ if (this.debug) {
83579
+ console.log(`[MCP] Streamable HTTP session closed: ${closedSessionId}`);
83580
+ }
83581
+ this.streamableTransports.delete(closedSessionId);
83582
+ }
83583
+ });
83584
+ transport.onclose = () => {
83585
+ const sid = transport.sessionId;
83586
+ if (sid && this.streamableTransports.has(sid)) {
83587
+ if (this.debug) {
83588
+ console.log(`[MCP] Transport closed for session ${sid}`);
83589
+ }
83590
+ this.streamableTransports.delete(sid);
83591
+ }
83592
+ };
83593
+ await this.mcpServer.connect(transport);
83594
+ } else {
83595
+ res.writeHead(400, { "Content-Type": "application/json" });
83596
+ res.end(JSON.stringify({
83597
+ jsonrpc: "2.0",
83598
+ error: {
83599
+ code: -32e3,
83600
+ message: "Bad Request: No valid session ID provided or not an initialization request"
83601
+ },
83602
+ id: null
83603
+ }));
83604
+ return;
83605
+ }
83606
+ await transport.handleRequest(req, res, body);
83607
+ } catch (error2) {
83608
+ if (this.debug) {
83609
+ console.error("[MCP] Error handling Streamable HTTP request:", error2);
83610
+ }
83611
+ if (!res.headersSent) {
83612
+ res.writeHead(500, { "Content-Type": "application/json" });
83613
+ res.end(JSON.stringify({
83614
+ jsonrpc: "2.0",
83615
+ error: {
83616
+ code: -32603,
83617
+ message: "Internal server error",
83618
+ data: error2.message
83619
+ },
83620
+ id: null
83621
+ }));
83622
+ }
83623
+ }
83624
+ }
83625
+ /**
83626
+ * Parse request body as JSON
83627
+ */
83628
+ async parseRequestBody(req) {
83629
+ return new Promise((resolve5, reject2) => {
83630
+ let body = "";
83631
+ req.on("data", (chunk) => {
83632
+ body += chunk.toString();
83633
+ });
83634
+ req.on("end", () => {
83635
+ try {
83636
+ const parsed = body ? JSON.parse(body) : null;
83637
+ resolve5(parsed);
83638
+ } catch (error2) {
83639
+ reject2(error2);
83640
+ }
83641
+ });
83642
+ req.on("error", reject2);
83643
+ });
83644
+ }
83645
+ /**
83646
+ * Handle Server-Sent Events connection (DEPRECATED - use handleSSEConnection instead)
83286
83647
  */
83287
83648
  handleSSE(req, res) {
83288
83649
  res.writeHead(200, {
@@ -83549,6 +83910,32 @@ data: ${JSON.stringify(data2)}
83549
83910
  * Stop the server
83550
83911
  */
83551
83912
  async stop() {
83913
+ for (const [sessionId, transport] of this.streamableTransports.entries()) {
83914
+ try {
83915
+ await transport.close();
83916
+ if (this.debug) {
83917
+ console.log(`[MCP] Closed Streamable HTTP transport for session: ${sessionId}`);
83918
+ }
83919
+ } catch (error2) {
83920
+ if (this.debug) {
83921
+ console.error(`[MCP] Error closing Streamable HTTP transport ${sessionId}:`, error2);
83922
+ }
83923
+ }
83924
+ }
83925
+ this.streamableTransports.clear();
83926
+ for (const [sessionId, transport] of this.sseTransports.entries()) {
83927
+ try {
83928
+ await transport.close();
83929
+ if (this.debug) {
83930
+ console.log(`[MCP] Closed SSE transport for session: ${sessionId}`);
83931
+ }
83932
+ } catch (error2) {
83933
+ if (this.debug) {
83934
+ console.error(`[MCP] Error closing SSE transport ${sessionId}:`, error2);
83935
+ }
83936
+ }
83937
+ }
83938
+ this.sseTransports.clear();
83552
83939
  for (const connection of this.connections) {
83553
83940
  connection.end();
83554
83941
  }
@@ -83580,6 +83967,59 @@ data: ${JSON.stringify(data2)}
83580
83967
  }
83581
83968
  });
83582
83969
 
83970
+ // src/agent/shared/Session.js
83971
+ var Session;
83972
+ var init_Session = __esm({
83973
+ "src/agent/shared/Session.js"() {
83974
+ "use strict";
83975
+ Session = class {
83976
+ constructor(id, debug = false) {
83977
+ this.id = id;
83978
+ this.conversationId = null;
83979
+ this.messageCount = 0;
83980
+ this.debug = debug;
83981
+ }
83982
+ /**
83983
+ * Set the conversation ID for session resumption
83984
+ * @param {string} conversationId - Provider's conversation/thread ID
83985
+ */
83986
+ setConversationId(conversationId) {
83987
+ this.conversationId = conversationId;
83988
+ if (this.debug) {
83989
+ console.log(`[Session ${this.id}] Conversation ID: ${conversationId}`);
83990
+ }
83991
+ }
83992
+ /**
83993
+ * Increment the message count
83994
+ */
83995
+ incrementMessageCount() {
83996
+ this.messageCount++;
83997
+ }
83998
+ /**
83999
+ * Get session info as plain object
84000
+ * @returns {Object} Session information
84001
+ */
84002
+ getInfo() {
84003
+ return {
84004
+ id: this.id,
84005
+ conversationId: this.conversationId,
84006
+ messageCount: this.messageCount
84007
+ };
84008
+ }
84009
+ /**
84010
+ * Get resume arguments for CLI commands (used by Claude Code)
84011
+ * @returns {Array<string>} CLI arguments for resuming conversation
84012
+ */
84013
+ getResumeArgs() {
84014
+ if (this.conversationId && this.messageCount > 0) {
84015
+ return ["--resume", this.conversationId];
84016
+ }
84017
+ return [];
84018
+ }
84019
+ };
84020
+ }
84021
+ });
84022
+
83583
84023
  // src/agent/engines/enhanced-claude-code.js
83584
84024
  var enhanced_claude_code_exports = {};
83585
84025
  __export(enhanced_claude_code_exports, {
@@ -83587,8 +84027,8 @@ __export(enhanced_claude_code_exports, {
83587
84027
  });
83588
84028
  async function createEnhancedClaudeCLIEngine(options = {}) {
83589
84029
  const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools } = options;
83590
- const session = new ClaudeSession(
83591
- sessionId || (0, import_crypto5.randomBytes)(8).toString("hex"),
84030
+ const session = new Session(
84031
+ sessionId || (0, import_crypto6.randomBytes)(8).toString("hex"),
83592
84032
  debug
83593
84033
  );
83594
84034
  let mcpServer = null;
@@ -83798,11 +84238,7 @@ ${opts.schema}`;
83798
84238
  * Get session info
83799
84239
  */
83800
84240
  getSession() {
83801
- return {
83802
- id: session.id,
83803
- conversationId: session.conversationId,
83804
- messageCount: session.messageCount
83805
- };
84241
+ return session.getInfo();
83806
84242
  },
83807
84243
  /**
83808
84244
  * Clean up - MUST be called to stop MCP server and clean resources
@@ -83983,46 +84419,293 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
83983
84419
  }
83984
84420
  return systemPrompt || "";
83985
84421
  }
83986
- var import_child_process9, import_crypto5, import_promises2, import_path11, import_os4, import_events3, ClaudeSession;
84422
+ var import_child_process9, import_crypto6, import_promises2, import_path11, import_os4, import_events3;
83987
84423
  var init_enhanced_claude_code = __esm({
83988
84424
  "src/agent/engines/enhanced-claude-code.js"() {
83989
84425
  "use strict";
83990
84426
  import_child_process9 = require("child_process");
83991
- import_crypto5 = require("crypto");
84427
+ import_crypto6 = require("crypto");
83992
84428
  import_promises2 = __toESM(require("fs/promises"), 1);
83993
84429
  import_path11 = __toESM(require("path"), 1);
83994
84430
  import_os4 = __toESM(require("os"), 1);
83995
84431
  import_events3 = require("events");
83996
84432
  init_built_in_server();
83997
- ClaudeSession = class {
83998
- constructor(id, debug = false) {
83999
- this.id = id;
84000
- this.conversationId = null;
84001
- this.messageCount = 0;
84002
- this.debug = debug;
84433
+ init_Session();
84434
+ }
84435
+ });
84436
+
84437
+ // src/agent/engines/codex.js
84438
+ var codex_exports = {};
84439
+ __export(codex_exports, {
84440
+ createCodexEngine: () => createCodexEngine
84441
+ });
84442
+ async function createCodexEngine(options = {}) {
84443
+ const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, model } = options;
84444
+ const session = new Session(
84445
+ sessionId || (0, import_crypto7.randomBytes)(8).toString("hex"),
84446
+ debug
84447
+ );
84448
+ let mcpServer = null;
84449
+ let mcpServerUrl = null;
84450
+ let mcpServerName = null;
84451
+ if (agent) {
84452
+ mcpServer = new BuiltInMCPServer(agent, {
84453
+ port: 0,
84454
+ host: "127.0.0.1",
84455
+ debug
84456
+ });
84457
+ const { host, port } = await mcpServer.start();
84458
+ mcpServerUrl = `http://${host}:${port}/mcp`;
84459
+ mcpServerName = `probe_${session.id}`;
84460
+ if (debug) {
84461
+ console.log("[DEBUG] Built-in Probe MCP server started");
84462
+ console.log("[DEBUG] Probe MCP URL:", mcpServerUrl);
84463
+ }
84464
+ }
84465
+ if (debug) {
84466
+ console.log("[DEBUG] Starting Codex MCP server...");
84467
+ }
84468
+ const codexProcess = (0, import_child_process10.spawn)("codex", ["mcp-server"], {
84469
+ stdio: ["pipe", "pipe", "pipe"]
84470
+ });
84471
+ let requestId = 0;
84472
+ const pendingRequests = /* @__PURE__ */ new Map();
84473
+ const eventHandlers = /* @__PURE__ */ new Map();
84474
+ const stdoutReader = (0, import_readline.createInterface)({
84475
+ input: codexProcess.stdout,
84476
+ crlfDelay: Infinity
84477
+ });
84478
+ stdoutReader.on("line", (line) => {
84479
+ try {
84480
+ const message = JSON.parse(line);
84481
+ if (debug) {
84482
+ if (message.method === "codex/event") {
84483
+ console.log(`[DEBUG] Codex event: ${message.params?.msg?.type}`);
84484
+ }
84003
84485
  }
84004
- /**
84005
- * Update session with Claude's conversation ID
84006
- */
84007
- setConversationId(convId) {
84008
- this.conversationId = convId;
84009
- if (this.debug) {
84010
- console.log(`[Session ${this.id}] Conversation ID: ${convId}`);
84486
+ if (message.id !== void 0 && pendingRequests.has(message.id)) {
84487
+ const { resolve: resolve5, reject: reject2 } = pendingRequests.get(message.id);
84488
+ pendingRequests.delete(message.id);
84489
+ if (message.error) {
84490
+ reject2(new Error(message.error.message || JSON.stringify(message.error)));
84491
+ } else {
84492
+ resolve5(message.result);
84011
84493
  }
84012
84494
  }
84013
- /**
84014
- * Get resume arguments for continuing conversation
84015
- */
84016
- getResumeArgs() {
84017
- if (this.conversationId && this.messageCount > 0) {
84018
- return ["--resume", this.conversationId];
84495
+ if (message.method === "codex/event" && message.params) {
84496
+ const requestId2 = message.params._meta?.requestId;
84497
+ if (requestId2 !== void 0 && eventHandlers.has(requestId2)) {
84498
+ eventHandlers.get(requestId2)(message.params);
84019
84499
  }
84020
- return [];
84021
84500
  }
84022
- incrementMessageCount() {
84023
- this.messageCount++;
84501
+ } catch (e4) {
84502
+ if (debug) {
84503
+ console.error("[DEBUG] Failed to parse message:", line);
84024
84504
  }
84025
- };
84505
+ }
84506
+ });
84507
+ if (debug) {
84508
+ codexProcess.stderr.on("data", (data2) => {
84509
+ console.error("[CODEX STDERR]", data2.toString());
84510
+ });
84511
+ }
84512
+ function sendRequest(method, params = {}) {
84513
+ return new Promise((resolve5, reject2) => {
84514
+ const id = ++requestId;
84515
+ const request = {
84516
+ jsonrpc: "2.0",
84517
+ id,
84518
+ method,
84519
+ params
84520
+ };
84521
+ pendingRequests.set(id, { resolve: resolve5, reject: reject2 });
84522
+ setTimeout(() => {
84523
+ if (pendingRequests.has(id)) {
84524
+ pendingRequests.delete(id);
84525
+ reject2(new Error(`Request ${method} timed out after 10 minutes`));
84526
+ }
84527
+ }, 6e5);
84528
+ codexProcess.stdin.write(JSON.stringify(request) + "\n");
84529
+ });
84530
+ }
84531
+ await sendRequest("initialize", {
84532
+ protocolVersion: "2024-11-05",
84533
+ capabilities: { tools: {} },
84534
+ clientInfo: {
84535
+ name: "probe-codex-client",
84536
+ version: "1.0.0"
84537
+ }
84538
+ });
84539
+ if (debug) {
84540
+ console.log("[DEBUG] Connected to Codex MCP server");
84541
+ console.log("[DEBUG] Session:", session.id);
84542
+ }
84543
+ const fullPrompt = combinePrompts2(systemPrompt, customPrompt, agent);
84544
+ return {
84545
+ sessionId: session.id,
84546
+ session,
84547
+ /**
84548
+ * Query Codex via MCP protocol with event streaming
84549
+ */
84550
+ async *query(prompt, opts = {}) {
84551
+ let finalPrompt = prompt;
84552
+ if (!session.conversationId && fullPrompt) {
84553
+ finalPrompt = `${fullPrompt}
84554
+
84555
+ ${prompt}`;
84556
+ }
84557
+ const isFollowUp = session.conversationId !== null;
84558
+ const toolName = isFollowUp ? "codex-reply" : "codex";
84559
+ const toolArgs = { prompt: finalPrompt };
84560
+ if (isFollowUp) {
84561
+ toolArgs.conversationId = session.conversationId;
84562
+ if (debug) {
84563
+ console.log(`[DEBUG] Follow-up with conversationId: ${session.conversationId}`);
84564
+ }
84565
+ } else {
84566
+ if (model) {
84567
+ toolArgs.model = model;
84568
+ }
84569
+ if (mcpServerUrl && mcpServerName) {
84570
+ toolArgs.config = {
84571
+ mcp_servers: {
84572
+ [mcpServerName]: { url: mcpServerUrl }
84573
+ }
84574
+ };
84575
+ }
84576
+ if (debug) {
84577
+ console.log(`[DEBUG] Initial query with tool: ${toolName}`);
84578
+ }
84579
+ }
84580
+ try {
84581
+ const reqId = requestId + 1;
84582
+ let fullResponse = "";
84583
+ let gotSessionId = false;
84584
+ const eventPromise = new Promise((resolve5) => {
84585
+ eventHandlers.set(reqId, (eventParams) => {
84586
+ const msg = eventParams.msg;
84587
+ if (msg.type === "session_configured" && msg.session_id && !gotSessionId) {
84588
+ session.setConversationId(msg.session_id);
84589
+ gotSessionId = true;
84590
+ }
84591
+ if (msg.type === "raw_response_item" && msg.item?.role === "assistant") {
84592
+ const content = msg.item.content;
84593
+ if (Array.isArray(content)) {
84594
+ for (const part of content) {
84595
+ if (part.type === "text" && part.text) {
84596
+ fullResponse += part.text;
84597
+ }
84598
+ }
84599
+ }
84600
+ }
84601
+ });
84602
+ setTimeout(() => {
84603
+ eventHandlers.delete(reqId);
84604
+ resolve5();
84605
+ }, 6e5);
84606
+ });
84607
+ const resultPromise = sendRequest("tools/call", {
84608
+ name: toolName,
84609
+ arguments: toolArgs
84610
+ });
84611
+ const result = await resultPromise;
84612
+ eventHandlers.delete(reqId);
84613
+ if (result && result.content && Array.isArray(result.content)) {
84614
+ for (const item of result.content) {
84615
+ if (item.type === "text" && item.text) {
84616
+ yield {
84617
+ type: "text",
84618
+ content: item.text
84619
+ };
84620
+ fullResponse = item.text;
84621
+ }
84622
+ }
84623
+ }
84624
+ if (fullResponse && (!result.content || result.content.length === 0)) {
84625
+ yield {
84626
+ type: "text",
84627
+ content: fullResponse
84628
+ };
84629
+ }
84630
+ session.incrementMessageCount();
84631
+ yield {
84632
+ type: "metadata",
84633
+ data: {
84634
+ sessionId: session.id,
84635
+ conversationId: session.conversationId,
84636
+ messageCount: session.messageCount
84637
+ }
84638
+ };
84639
+ } catch (error2) {
84640
+ if (debug) {
84641
+ console.error("[DEBUG] Codex query error:", error2);
84642
+ }
84643
+ yield {
84644
+ type: "error",
84645
+ error: error2
84646
+ };
84647
+ }
84648
+ },
84649
+ /**
84650
+ * Get session info
84651
+ */
84652
+ getSession() {
84653
+ return session.getInfo();
84654
+ },
84655
+ /**
84656
+ * Clean up resources
84657
+ */
84658
+ async close() {
84659
+ try {
84660
+ if (stdoutReader) {
84661
+ stdoutReader.close();
84662
+ if (debug) {
84663
+ console.log("[DEBUG] Closed stdout reader");
84664
+ }
84665
+ }
84666
+ pendingRequests.clear();
84667
+ eventHandlers.clear();
84668
+ if (codexProcess && !codexProcess.killed) {
84669
+ codexProcess.kill();
84670
+ if (debug) {
84671
+ console.log("[DEBUG] Killed Codex MCP server process");
84672
+ }
84673
+ }
84674
+ if (mcpServer) {
84675
+ await mcpServer.stop();
84676
+ if (debug) {
84677
+ console.log("[DEBUG] Stopped Probe MCP server");
84678
+ }
84679
+ }
84680
+ if (debug) {
84681
+ console.log("[DEBUG] Engine closed, session:", session.id);
84682
+ }
84683
+ } catch (error2) {
84684
+ if (debug) {
84685
+ console.error("[DEBUG] Error during cleanup:", error2.message);
84686
+ }
84687
+ }
84688
+ }
84689
+ };
84690
+ }
84691
+ function combinePrompts2(systemPrompt, customPrompt, agent) {
84692
+ if (!systemPrompt && customPrompt) {
84693
+ return customPrompt;
84694
+ }
84695
+ if (systemPrompt && customPrompt) {
84696
+ return systemPrompt + "\n\n## Additional Instructions\n" + customPrompt;
84697
+ }
84698
+ return systemPrompt || "";
84699
+ }
84700
+ var import_child_process10, import_crypto7, import_readline;
84701
+ var init_codex = __esm({
84702
+ "src/agent/engines/codex.js"() {
84703
+ "use strict";
84704
+ import_child_process10 = require("child_process");
84705
+ import_crypto7 = require("crypto");
84706
+ import_readline = require("readline");
84707
+ init_built_in_server();
84708
+ init_Session();
84026
84709
  }
84027
84710
  });
84028
84711
 
@@ -84101,7 +84784,7 @@ __export(ProbeAgent_exports, {
84101
84784
  ProbeAgent: () => ProbeAgent
84102
84785
  });
84103
84786
  module.exports = __toCommonJS(ProbeAgent_exports);
84104
- var import_dotenv2, import_anthropic2, import_openai2, import_google2, import_ai5, import_crypto6, import_events4, import_fs10, import_promises3, import_path12, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
84787
+ var import_dotenv2, import_anthropic2, import_openai2, import_google2, import_ai5, import_crypto8, import_events4, import_fs10, import_promises3, import_path12, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
84105
84788
  var init_ProbeAgent = __esm({
84106
84789
  "src/agent/ProbeAgent.js"() {
84107
84790
  import_dotenv2 = __toESM(require_main(), 1);
@@ -84110,7 +84793,7 @@ var init_ProbeAgent = __esm({
84110
84793
  import_google2 = require("@ai-sdk/google");
84111
84794
  init_dist3();
84112
84795
  import_ai5 = require("ai");
84113
- import_crypto6 = require("crypto");
84796
+ import_crypto8 = require("crypto");
84114
84797
  import_events4 = require("events");
84115
84798
  import_fs10 = require("fs");
84116
84799
  import_promises3 = require("fs/promises");
@@ -84126,6 +84809,7 @@ var init_ProbeAgent = __esm({
84126
84809
  init_index();
84127
84810
  init_schemaUtils();
84128
84811
  init_xmlParsingUtils();
84812
+ init_prompts();
84129
84813
  init_mcp();
84130
84814
  init_RetryManager();
84131
84815
  init_FallbackManager();
@@ -84147,6 +84831,7 @@ var init_ProbeAgent = __esm({
84147
84831
  * @param {Object} options - Configuration options
84148
84832
  * @param {string} [options.sessionId] - Optional session ID
84149
84833
  * @param {string} [options.customPrompt] - Custom prompt to replace the default system message
84834
+ * @param {string} [options.systemPrompt] - Alias for customPrompt; takes precedence when both are provided
84150
84835
  * @param {string} [options.promptType] - Predefined prompt type (architect, code-review, support)
84151
84836
  * @param {boolean} [options.allowEdit=false] - Allow the use of the 'implement' tool
84152
84837
  * @param {boolean} [options.enableDelegate=false] - Enable the delegate tool for task distribution to subagents
@@ -84181,8 +84866,8 @@ var init_ProbeAgent = __esm({
84181
84866
  * @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
84182
84867
  */
84183
84868
  constructor(options = {}) {
84184
- this.sessionId = options.sessionId || (0, import_crypto6.randomUUID)();
84185
- this.customPrompt = options.customPrompt || null;
84869
+ this.sessionId = options.sessionId || (0, import_crypto8.randomUUID)();
84870
+ this.customPrompt = options.systemPrompt || options.customPrompt || null;
84186
84871
  this.promptType = options.promptType || "code-explorer";
84187
84872
  this.allowEdit = !!options.allowEdit;
84188
84873
  this.enableDelegate = !!options.enableDelegate;
@@ -84306,9 +84991,10 @@ var init_ProbeAgent = __esm({
84306
84991
  * This method initializes MCP and merges MCP tools into the tool list, and loads history from storage
84307
84992
  */
84308
84993
  async initialize() {
84309
- if (!this.provider && !this.clientApiProvider && this.apiType !== "claude-code") {
84994
+ if (!this.provider && !this.clientApiProvider && this.apiType !== "claude-code" && this.apiType !== "codex") {
84310
84995
  if (this.apiType === "uninitialized") {
84311
84996
  const claudeAvailable = await this.isClaudeCommandAvailable();
84997
+ const codexAvailable = await this.isCodexCommandAvailable();
84312
84998
  if (claudeAvailable) {
84313
84999
  if (this.debug) {
84314
85000
  console.log("[DEBUG] No API keys found, but claude command detected");
@@ -84318,8 +85004,17 @@ var init_ProbeAgent = __esm({
84318
85004
  this.provider = null;
84319
85005
  this.model = this.clientApiModel || "claude-3-5-sonnet-20241022";
84320
85006
  this.apiType = "claude-code";
85007
+ } else if (codexAvailable) {
85008
+ if (this.debug) {
85009
+ console.log("[DEBUG] No API keys found, but codex command detected");
85010
+ console.log("[DEBUG] Auto-switching to codex provider");
85011
+ }
85012
+ this.clientApiProvider = "codex";
85013
+ this.provider = null;
85014
+ this.model = this.clientApiModel || "gpt-4o";
85015
+ this.apiType = "codex";
84321
85016
  } else {
84322
- 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");
85017
+ 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");
84323
85018
  }
84324
85019
  }
84325
85020
  }
@@ -84441,13 +85136,33 @@ var init_ProbeAgent = __esm({
84441
85136
  }
84442
85137
  /**
84443
85138
  * Check if claude command is available on the system
85139
+ * Uses execFile instead of exec to avoid shell injection risks
84444
85140
  * @returns {Promise<boolean>} True if claude command is available
84445
85141
  * @private
84446
85142
  */
84447
85143
  async isClaudeCommandAvailable() {
84448
85144
  try {
84449
- const { execSync } = await import("child_process");
84450
- execSync("claude --version", { stdio: "ignore" });
85145
+ const { execFile: execFile3 } = await import("child_process");
85146
+ const { promisify: promisify8 } = await import("util");
85147
+ const execFileAsync3 = promisify8(execFile3);
85148
+ await execFileAsync3("claude", ["--version"], { timeout: 5e3 });
85149
+ return true;
85150
+ } catch (error2) {
85151
+ return false;
85152
+ }
85153
+ }
85154
+ /**
85155
+ * Check if codex command is available on the system
85156
+ * Uses execFile instead of exec to avoid shell injection risks
85157
+ * @returns {Promise<boolean>} True if codex command is available
85158
+ * @private
85159
+ */
85160
+ async isCodexCommandAvailable() {
85161
+ try {
85162
+ const { execFile: execFile3 } = await import("child_process");
85163
+ const { promisify: promisify8 } = await import("util");
85164
+ const execFileAsync3 = promisify8(execFile3);
85165
+ await execFileAsync3("codex", ["--version"], { timeout: 5e3 });
84451
85166
  return true;
84452
85167
  } catch (error2) {
84453
85168
  return false;
@@ -84471,6 +85186,20 @@ var init_ProbeAgent = __esm({
84471
85186
  }
84472
85187
  return;
84473
85188
  }
85189
+ if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
85190
+ this.provider = null;
85191
+ this.model = modelName || null;
85192
+ this.apiType = "codex";
85193
+ if (this.debug) {
85194
+ console.log("[DEBUG] Codex CLI engine selected - will use built-in access if available");
85195
+ if (this.model) {
85196
+ console.log(`[DEBUG] Using model: ${this.model}`);
85197
+ } else {
85198
+ console.log("[DEBUG] Using Codex account default model");
85199
+ }
85200
+ }
85201
+ return;
85202
+ }
84474
85203
  const anthropicApiKey = process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
84475
85204
  const openaiApiKey = process.env.OPENAI_API_KEY;
84476
85205
  const googleApiKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY;
@@ -84632,6 +85361,44 @@ var init_ProbeAgent = __esm({
84632
85361
  }
84633
85362
  }
84634
85363
  }
85364
+ if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
85365
+ try {
85366
+ const engine = await this.getEngine();
85367
+ if (engine && engine.query) {
85368
+ const userMessages = options.messages.filter(
85369
+ (m4) => m4.role === "user" && !m4.content.includes("WARNING: You have reached the maximum tool iterations limit")
85370
+ );
85371
+ const lastUserMessage = userMessages[userMessages.length - 1];
85372
+ const prompt = lastUserMessage ? lastUserMessage.content : "";
85373
+ const engineOptions = {
85374
+ maxTokens: options.maxTokens,
85375
+ temperature: options.temperature,
85376
+ messages: options.messages,
85377
+ systemPrompt: options.messages.find((m4) => m4.role === "system")?.content
85378
+ };
85379
+ const engineStream = engine.query(prompt, engineOptions);
85380
+ async function* createTextStream() {
85381
+ for await (const message of engineStream) {
85382
+ if (message.type === "text" && message.content) {
85383
+ yield message.content;
85384
+ } else if (typeof message === "string") {
85385
+ yield message;
85386
+ }
85387
+ }
85388
+ }
85389
+ return {
85390
+ textStream: createTextStream(),
85391
+ usage: Promise.resolve({})
85392
+ // Engine should handle its own usage tracking
85393
+ // Add other streamText-compatible properties as needed
85394
+ };
85395
+ }
85396
+ } catch (error2) {
85397
+ if (this.debug) {
85398
+ console.log(`[DEBUG] Failed to use Codex engine, falling back to Vercel:`, error2.message);
85399
+ }
85400
+ }
85401
+ }
84635
85402
  if (!this.retryManager) {
84636
85403
  this.retryManager = new RetryManager({
84637
85404
  maxRetries: this.retryConfig.maxRetries ?? 3,
@@ -84784,6 +85551,35 @@ var init_ProbeAgent = __esm({
84784
85551
  this.clientApiProvider = null;
84785
85552
  }
84786
85553
  }
85554
+ if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
85555
+ try {
85556
+ const { createCodexEngine: createCodexEngine2 } = await Promise.resolve().then(() => (init_codex(), codex_exports));
85557
+ const systemPrompt = this.customPrompt || this.getCodexNativeSystemPrompt();
85558
+ this.engine = await createCodexEngine2({
85559
+ agent: this,
85560
+ // Pass reference to ProbeAgent for tool access
85561
+ systemPrompt,
85562
+ customPrompt: this.customPrompt,
85563
+ sessionId: this.options?.sessionId,
85564
+ debug: this.debug,
85565
+ allowedTools: this.allowedTools,
85566
+ // Pass tool filtering configuration
85567
+ model: this.model
85568
+ // Pass model name (e.g., gpt-4o, o3, etc.)
85569
+ });
85570
+ if (this.debug) {
85571
+ console.log("[DEBUG] Using Codex CLI engine with Probe tools");
85572
+ if (this.customPrompt) {
85573
+ console.log("[DEBUG] Using custom prompt/persona");
85574
+ }
85575
+ }
85576
+ return this.engine;
85577
+ } catch (error2) {
85578
+ console.warn("[WARNING] Failed to load Codex CLI engine:", error2.message);
85579
+ console.warn("[WARNING] Falling back to Vercel AI SDK");
85580
+ this.clientApiProvider = null;
85581
+ }
85582
+ }
84787
85583
  const { createEnhancedVercelEngine: createEnhancedVercelEngine2 } = await Promise.resolve().then(() => (init_enhanced_vercel(), enhanced_vercel_exports));
84788
85584
  this.engine = createEnhancedVercelEngine2(this);
84789
85585
  if (this.debug) {
@@ -84791,6 +85587,32 @@ var init_ProbeAgent = __esm({
84791
85587
  }
84792
85588
  return this.engine;
84793
85589
  }
85590
+ /**
85591
+ * Get session information including thread ID for resumability
85592
+ * @returns {Object} Session info with sessionId, threadId, messageCount
85593
+ */
85594
+ getSessionInfo() {
85595
+ if (this.engine && this.engine.getSession) {
85596
+ return this.engine.getSession();
85597
+ }
85598
+ return {
85599
+ id: this.sessionId,
85600
+ threadId: null,
85601
+ messageCount: 0
85602
+ };
85603
+ }
85604
+ /**
85605
+ * Close the agent and clean up resources (e.g., MCP servers)
85606
+ * @returns {Promise<void>}
85607
+ */
85608
+ async close() {
85609
+ if (this.engine && this.engine.close) {
85610
+ await this.engine.close();
85611
+ }
85612
+ if (this.mcpBridge) {
85613
+ this.mcpBridge = null;
85614
+ }
85615
+ }
84794
85616
  /**
84795
85617
  * Process assistant response content and detect/load image references
84796
85618
  * @param {string} content - The assistant's response content
@@ -85083,11 +85905,61 @@ var init_ProbeAgent = __esm({
85083
85905
  */
85084
85906
  getClaudeNativeSystemPrompt() {
85085
85907
  let systemPrompt = "";
85086
- if (this.predefinedPrompt) {
85087
- const personaPrompt = getPromptByType(this.predefinedPrompt);
85088
- if (personaPrompt?.system) {
85089
- systemPrompt += personaPrompt.system + "\n\n";
85090
- }
85908
+ if (this.customPrompt) {
85909
+ systemPrompt += this.customPrompt + "\n\n";
85910
+ } else if (this.promptType && predefinedPrompts[this.promptType]) {
85911
+ systemPrompt += predefinedPrompts[this.promptType] + "\n\n";
85912
+ } else {
85913
+ systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
85914
+ }
85915
+ systemPrompt += `You have access to powerful code search and analysis tools through MCP:
85916
+ - search: Find code patterns using semantic search
85917
+ - extract: Extract specific code sections with context
85918
+ - query: Use AST patterns for structural code matching
85919
+ - listFiles: Browse directory contents
85920
+ - searchFiles: Find files by name patterns`;
85921
+ if (this.enableBash) {
85922
+ systemPrompt += `
85923
+ - bash: Execute bash commands for system operations`;
85924
+ }
85925
+ systemPrompt += `
85926
+
85927
+ When exploring code:
85928
+ 1. Start with search to find relevant code patterns
85929
+ 2. Use extract to get detailed context when needed
85930
+ 3. Prefer focused, specific searches over broad queries
85931
+ 4. Combine multiple tools to build complete understanding`;
85932
+ if (this.allowedFolders && this.allowedFolders.length > 0) {
85933
+ systemPrompt += `
85934
+
85935
+ Workspace: ${this.allowedFolders.join(", ")}`;
85936
+ }
85937
+ if (this.fileList) {
85938
+ systemPrompt += `
85939
+
85940
+ # Repository Structure
85941
+ `;
85942
+ systemPrompt += `You are working with a repository located at: ${this.allowedFolders[0]}
85943
+
85944
+ `;
85945
+ systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
85946
+
85947
+ `;
85948
+ systemPrompt += "```\n" + this.fileList + "\n```\n";
85949
+ }
85950
+ return systemPrompt;
85951
+ }
85952
+ /**
85953
+ * Get system prompt for Codex CLI (similar to Claude but optimized for Codex)
85954
+ */
85955
+ getCodexNativeSystemPrompt() {
85956
+ let systemPrompt = "";
85957
+ if (this.customPrompt) {
85958
+ systemPrompt += this.customPrompt + "\n\n";
85959
+ } else if (this.promptType && predefinedPrompts[this.promptType]) {
85960
+ systemPrompt += predefinedPrompts[this.promptType] + "\n\n";
85961
+ } else {
85962
+ systemPrompt += predefinedPrompts["code-explorer"] + "\n\n";
85091
85963
  }
85092
85964
  systemPrompt += `You have access to powerful code search and analysis tools through MCP:
85093
85965
  - search: Find code patterns using semantic search
@@ -85283,7 +86155,7 @@ Follow these instructions carefully:
85283
86155
  - Use 'create' for new files or complete file rewrites` : ""}
85284
86156
  </instructions>
85285
86157
  `;
85286
- const predefinedPrompts = {
86158
+ const predefinedPrompts2 = {
85287
86159
  "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.
85288
86160
 
85289
86161
  When exploring code:
@@ -85339,14 +86211,14 @@ When troubleshooting:
85339
86211
  if (this.debug) {
85340
86212
  console.log(`[DEBUG] Using custom prompt`);
85341
86213
  }
85342
- } else if (this.promptType && predefinedPrompts[this.promptType]) {
85343
- systemMessage = "<role>" + predefinedPrompts[this.promptType] + "</role>";
86214
+ } else if (this.promptType && predefinedPrompts2[this.promptType]) {
86215
+ systemMessage = "<role>" + predefinedPrompts2[this.promptType] + "</role>";
85344
86216
  if (this.debug) {
85345
86217
  console.log(`[DEBUG] Using predefined prompt: ${this.promptType}`);
85346
86218
  }
85347
86219
  systemMessage += commonInstructions;
85348
86220
  } else {
85349
- systemMessage = "<role>" + predefinedPrompts["code-explorer"] + "</role>";
86221
+ systemMessage = "<role>" + predefinedPrompts2["code-explorer"] + "</role>";
85350
86222
  if (this.debug) {
85351
86223
  console.log(`[DEBUG] Using default prompt: code explorer`);
85352
86224
  }
@@ -85487,6 +86359,7 @@ You are working with a repository located at: ${searchDirectory}
85487
86359
  const baseMaxIterations = this.maxIterations || MAX_TOOL_ITERATIONS;
85488
86360
  const maxIterations = options.schema ? baseMaxIterations + 4 : baseMaxIterations;
85489
86361
  const isClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
86362
+ const isCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
85490
86363
  if (isClaudeCode) {
85491
86364
  if (this.debug) {
85492
86365
  console.log(`[DEBUG] Using Claude Code engine - bypassing tool loop (black box mode)`);
@@ -85539,6 +86412,58 @@ You are working with a repository located at: ${searchDirectory}
85539
86412
  throw error2;
85540
86413
  }
85541
86414
  }
86415
+ if (isCodex) {
86416
+ if (this.debug) {
86417
+ console.log(`[DEBUG] Using Codex engine - bypassing tool loop (black box mode)`);
86418
+ console.log(`[DEBUG] Sending question directly to Codex: ${message.substring(0, 100)}...`);
86419
+ }
86420
+ try {
86421
+ const engine = await this.getEngine();
86422
+ if (engine && engine.query) {
86423
+ let assistantResponseContent = "";
86424
+ let toolBatch = null;
86425
+ for await (const chunk of engine.query(message, options)) {
86426
+ if (chunk.type === "text" && chunk.content) {
86427
+ assistantResponseContent += chunk.content;
86428
+ if (options.onStream) {
86429
+ options.onStream(chunk.content);
86430
+ }
86431
+ } else if (chunk.type === "toolBatch" && chunk.tools) {
86432
+ toolBatch = chunk.tools;
86433
+ if (this.debug) {
86434
+ console.log(`[DEBUG] Received batch of ${chunk.tools.length} tool events from Codex`);
86435
+ }
86436
+ } else if (chunk.type === "error") {
86437
+ throw chunk.error;
86438
+ }
86439
+ }
86440
+ if (toolBatch && toolBatch.length > 0 && this.events) {
86441
+ if (this.debug) {
86442
+ console.log(`[DEBUG] Emitting ${toolBatch.length} tool events from Codex batch`);
86443
+ }
86444
+ for (const toolEvent of toolBatch) {
86445
+ this.events.emit("toolCall", toolEvent);
86446
+ }
86447
+ }
86448
+ this.history.push(userMessage);
86449
+ this.history.push({
86450
+ role: "assistant",
86451
+ content: assistantResponseContent
86452
+ });
86453
+ await this.hooks.emit(HOOK_TYPES.COMPLETION, {
86454
+ sessionId: this.sessionId,
86455
+ prompt: message,
86456
+ response: assistantResponseContent
86457
+ });
86458
+ return assistantResponseContent;
86459
+ }
86460
+ } catch (error2) {
86461
+ if (this.debug) {
86462
+ console.error("[DEBUG] Codex error:", error2);
86463
+ }
86464
+ throw error2;
86465
+ }
86466
+ }
85542
86467
  if (this.debug) {
85543
86468
  console.log(`[DEBUG] Starting agentic flow for question: ${message.substring(0, 100)}...`);
85544
86469
  if (options.schema) {
@@ -86419,7 +87344,7 @@ Convert your previous response content into actual JSON data that follows this s
86419
87344
  */
86420
87345
  clone(options = {}) {
86421
87346
  const {
86422
- sessionId = (0, import_crypto6.randomUUID)(),
87347
+ sessionId = (0, import_crypto8.randomUUID)(),
86423
87348
  stripInternalMessages = true,
86424
87349
  keepSystemMessage = true,
86425
87350
  deepCopy = true,