@probelabs/probe-chat 0.6.0-rc197 → 0.6.0-rc199

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.
@@ -63,15 +63,18 @@ export class ChatSessionManager {
63
63
  }
64
64
 
65
65
  /**
66
- * Initialize the ChatSessionManager by loading history
66
+ * Initialize the ChatSessionManager by initializing ProbeAgent and loading history
67
67
  * This must be called before using chat()
68
68
  */
69
69
  async initialize() {
70
70
  if (this._ready) return; // Already initialized
71
-
71
+
72
+ // Initialize ProbeAgent (handles API key detection and CLI fallback)
73
+ await this.agent.initialize();
74
+
72
75
  await this.loadHistory();
73
76
  this._ready = true;
74
-
77
+
75
78
  if (this.debug) {
76
79
  console.log(`[ChatSessionManager] Initialized session ${this.sessionId} with ${this.agent.history.length} messages from storage`);
77
80
  }
package/index.js CHANGED
@@ -346,12 +346,6 @@ export function main() {
346
346
  process.env.PORT = options.port;
347
347
  }
348
348
 
349
- // Check for API keys
350
- const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
351
- const openaiApiKey = process.env.OPENAI_API_KEY;
352
- const googleApiKey = process.env.GOOGLE_API_KEY;
353
- const hasApiKeys = !!(anthropicApiKey || openaiApiKey || googleApiKey);
354
-
355
349
  // --- Bash Configuration Processing ---
356
350
  let bashConfig = null;
357
351
  if (options.enableBash) {
@@ -406,16 +400,13 @@ export function main() {
406
400
 
407
401
  // --- Web Mode (check before non-interactive to override) ---
408
402
  if (options.web) {
409
- if (!hasApiKeys) {
410
- // Use logWarn for web mode warning
411
- logWarn(chalk.yellow('Warning: No API key provided. The web interface will show instructions on how to set up API keys.'));
412
- }
413
- // Import and start web server
403
+ // Note: API key / CLI availability is checked lazily in ProbeAgent.initialize()
404
+ // when the first chat message is sent. This allows fallback to Claude Code or Codex CLI.
414
405
  import('./webServer.js')
415
406
  .then(async module => {
416
407
  const { startWebServer } = module;
417
408
  logInfo(`Starting web server on port ${process.env.PORT || 8080}...`);
418
- await startWebServer(version, hasApiKeys, { allowEdit: options.allowEdit });
409
+ await startWebServer(version, { allowEdit: options.allowEdit });
419
410
  })
420
411
  .catch(error => {
421
412
  logError(chalk.red(`Error starting web server: ${error.message}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe-chat",
3
- "version": "0.6.0-rc197",
3
+ "version": "0.6.0-rc199",
4
4
  "description": "CLI and web interface for Probe code search (formerly @probelabs/probe-web and @probelabs/probe-chat)",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,86 @@
1
+ import { describe, it, beforeEach, afterEach, mock } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { ChatSessionManager } from '../../ChatSessionManager.js';
4
+
5
+ // Store original environment
6
+ let originalEnv;
7
+
8
+ describe('ChatSessionManager Tests', () => {
9
+ beforeEach(() => {
10
+ // Store original environment
11
+ originalEnv = { ...process.env };
12
+
13
+ // Set test mode
14
+ process.env.NODE_ENV = 'test';
15
+ process.env.USE_MOCK_AI = 'true';
16
+ });
17
+
18
+ afterEach(() => {
19
+ // Restore original environment
20
+ Object.keys(process.env).forEach(key => {
21
+ if (!(key in originalEnv)) {
22
+ delete process.env[key];
23
+ }
24
+ });
25
+ Object.assign(process.env, originalEnv);
26
+ });
27
+
28
+ describe('initialize()', () => {
29
+ it('should call agent.initialize() when initializing', async () => {
30
+ // Create a ChatSessionManager
31
+ const session = new ChatSessionManager({
32
+ sessionId: 'test-session-123',
33
+ debug: false
34
+ });
35
+
36
+ // Track if agent.initialize was called
37
+ let agentInitializeCalled = false;
38
+ const originalInitialize = session.agent.initialize.bind(session.agent);
39
+ session.agent.initialize = async function() {
40
+ agentInitializeCalled = true;
41
+ return originalInitialize();
42
+ };
43
+
44
+ // Initialize the session
45
+ await session.initialize();
46
+
47
+ // Verify agent.initialize was called
48
+ assert.strictEqual(agentInitializeCalled, true, 'agent.initialize() should be called during ChatSessionManager.initialize()');
49
+ });
50
+
51
+ it('should only initialize once even if called multiple times', async () => {
52
+ const session = new ChatSessionManager({
53
+ sessionId: 'test-session-456',
54
+ debug: false
55
+ });
56
+
57
+ let initializeCallCount = 0;
58
+ const originalInitialize = session.agent.initialize.bind(session.agent);
59
+ session.agent.initialize = async function() {
60
+ initializeCallCount++;
61
+ return originalInitialize();
62
+ };
63
+
64
+ // Call initialize multiple times
65
+ await session.initialize();
66
+ await session.initialize();
67
+ await session.initialize();
68
+
69
+ // Should only be called once due to _ready flag
70
+ assert.strictEqual(initializeCallCount, 1, 'agent.initialize() should only be called once');
71
+ });
72
+
73
+ it('should set _ready flag after successful initialization', async () => {
74
+ const session = new ChatSessionManager({
75
+ sessionId: 'test-session-789',
76
+ debug: false
77
+ });
78
+
79
+ assert.strictEqual(session._ready, false, '_ready should be false before initialize');
80
+
81
+ await session.initialize();
82
+
83
+ assert.strictEqual(session._ready, true, '_ready should be true after initialize');
84
+ });
85
+ });
86
+ });
package/webServer.js CHANGED
@@ -98,13 +98,12 @@ function getOrCreateChat(sessionId, apiCredentials = null) {
98
98
  /**
99
99
  * Start the web server
100
100
  * @param {string} version - The version of the application
101
- * @param {boolean} hasApiKeys - Whether any API keys are configured
102
101
  * @param {Object} options - Additional options
103
102
  * @param {boolean} options.allowEdit - Whether to allow editing files via the implement tool
104
103
  */
105
- export async function startWebServer(version, hasApiKeys = true, options = {}) {
104
+ export async function startWebServer(version, options = {}) {
106
105
  const allowEdit = options?.allowEdit || false;
107
-
106
+
108
107
  if (allowEdit) {
109
108
  console.log('Edit mode enabled: implement tool is available');
110
109
  }
@@ -120,11 +119,11 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
120
119
  }
121
120
 
122
121
  // Initialize persistent storage for web mode
123
- globalStorage = new JsonChatStorage({
124
- webMode: true,
125
- verbose: process.env.DEBUG_CHAT === '1'
122
+ globalStorage = new JsonChatStorage({
123
+ webMode: true,
124
+ verbose: process.env.DEBUG_CHAT === '1'
126
125
  });
127
-
126
+
128
127
  // Initialize storage synchronously before server starts
129
128
  try {
130
129
  await globalStorage.initialize();
@@ -144,13 +143,9 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
144
143
  ? process.env.ALLOWED_FOLDERS.split(',').map(folder => folder.trim()).filter(Boolean)
145
144
  : [];
146
145
 
147
-
148
- let noApiKeysMode = !hasApiKeys;
149
- if (noApiKeysMode) {
150
- console.log('Running in No API Keys mode - will show setup instructions to users');
151
- } else {
152
- console.log('API keys detected. Chat functionality enabled.');
153
- }
146
+ // Note: API key / CLI availability is checked lazily in ProbeAgent.initialize()
147
+ // when the first chat message is sent. This allows fallback to Claude Code or Codex CLI.
148
+ console.log('Chat functionality enabled (API availability checked on first message)');
154
149
 
155
150
 
156
151
  // Define the tools available for direct API calls (bypassing LLM loop)
@@ -419,7 +414,7 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
419
414
  // UI Routes
420
415
  'GET /': (req, res) => {
421
416
  const htmlPath = join(__dirname, 'index.html');
422
- serveHtml(res, htmlPath, { 'data-no-api-keys': noApiKeysMode ? 'true' : 'false' });
417
+ serveHtml(res, htmlPath, { 'data-no-api-keys': 'false' });
423
418
  },
424
419
 
425
420
  // Chat session route - serves HTML with injected session ID
@@ -428,15 +423,15 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
428
423
  if (!sessionId) {
429
424
  return sendError(res, 400, 'Invalid session ID in URL');
430
425
  }
431
-
426
+
432
427
  // Validate that session exists or at least has a valid UUID format
433
428
  if (!isValidUUID(sessionId)) {
434
429
  return sendError(res, 400, 'Invalid session ID format');
435
430
  }
436
431
 
437
432
  const htmlPath = join(__dirname, 'index.html');
438
- serveHtml(res, htmlPath, {
439
- 'data-no-api-keys': noApiKeysMode ? 'true' : 'false',
433
+ serveHtml(res, htmlPath, {
434
+ 'data-no-api-keys': 'false',
440
435
  'data-session-id': sessionId
441
436
  });
442
437
  },
@@ -451,7 +446,7 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
451
446
  sendJson(res, 200, {
452
447
  folders: folders,
453
448
  currentDir: currentDir,
454
- noApiKeysMode: noApiKeysMode
449
+ noApiKeysMode: false
455
450
  });
456
451
  },
457
452
 
@@ -700,12 +695,6 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
700
695
  // Update last activity timestamp
701
696
  chatInstance.lastActivity = Date.now();
702
697
 
703
- // Check if API keys are needed but missing
704
- if (chatInstance.noApiKeysMode) {
705
- console.warn(`[WARN] Chat request for session ${chatSessionId} cannot proceed: No API keys configured.`);
706
- return sendError(res, 503, 'Chat service unavailable: API key not configured on server.');
707
- }
708
-
709
698
  // Register this request as active for cancellation
710
699
  registerRequest(chatSessionId, { abort: () => chatInstance.abort() });
711
700
  if (DEBUG) console.log(`[DEBUG] Registered cancellable request for session: ${chatSessionId}`);
@@ -918,9 +907,6 @@ export async function startWebServer(version, hasApiKeys = true, options = {}) {
918
907
  console.log(`Probe Web Interface v${version}`);
919
908
  console.log(`Server running on http://localhost:${PORT}`);
920
909
  console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
921
- if (noApiKeysMode) {
922
- console.log('*** Running in NO API KEYS mode. Chat functionality disabled. ***');
923
- }
924
910
  });
925
911
  }
926
912