@probelabs/probe 0.6.0-rc127 → 0.6.0-rc129

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc127",
3
+ "version": "0.6.0-rc129",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -80,7 +80,7 @@
80
80
  "@opentelemetry/sdk-node": "^0.203.0",
81
81
  "@opentelemetry/sdk-trace-base": "^1.30.0",
82
82
  "@opentelemetry/semantic-conventions": "^1.36.0",
83
- "@probelabs/maid": "^0.0.13",
83
+ "@probelabs/maid": "^0.0.15",
84
84
  "ai": "^5.0.0",
85
85
  "axios": "^1.8.3",
86
86
  "fs-extra": "^11.1.1",
@@ -1152,11 +1152,28 @@ When troubleshooting:
1152
1152
  }
1153
1153
 
1154
1154
  // Initialize conversation with existing history + new user message
1155
- let currentMessages = [
1156
- { role: 'system', content: systemMessage },
1157
- ...this.history, // Include previous conversation history
1158
- userMessage
1159
- ];
1155
+ // If history already contains a system message (from session cloning), reuse it for cache efficiency
1156
+ // Otherwise add a fresh system message
1157
+ const hasSystemMessage = this.history.length > 0 && this.history[0].role === 'system';
1158
+ let currentMessages;
1159
+
1160
+ if (hasSystemMessage) {
1161
+ // Reuse existing system message from history for cache efficiency
1162
+ currentMessages = [
1163
+ ...this.history,
1164
+ userMessage
1165
+ ];
1166
+ if (this.debug) {
1167
+ console.log('[DEBUG] Reusing existing system message from history for cache efficiency');
1168
+ }
1169
+ } else {
1170
+ // Add fresh system message (first call or empty history)
1171
+ currentMessages = [
1172
+ { role: 'system', content: systemMessage },
1173
+ ...this.history, // Include previous conversation history
1174
+ userMessage
1175
+ ];
1176
+ }
1160
1177
 
1161
1178
  let currentIteration = 0;
1162
1179
  let completionAttempted = false;
@@ -2147,6 +2164,163 @@ Convert your previous response content into actual JSON data that follows this s
2147
2164
  }
2148
2165
  }
2149
2166
 
2167
+ /**
2168
+ * Clone this agent's session to create a new agent with shared conversation history
2169
+ * @param {Object} options - Clone options
2170
+ * @param {string} [options.sessionId] - Session ID for the cloned agent (defaults to new UUID)
2171
+ * @param {boolean} [options.stripInternalMessages=true] - Remove internal messages (schema reminders, mermaid fixes, etc.)
2172
+ * @param {boolean} [options.keepSystemMessage=true] - Keep the system message in cloned history
2173
+ * @param {boolean} [options.deepCopy=true] - Deep copy messages to prevent mutations
2174
+ * @param {Object} [options.overrides] - Override any ProbeAgent constructor options
2175
+ * @returns {ProbeAgent} New agent instance with cloned history
2176
+ */
2177
+ clone(options = {}) {
2178
+ const {
2179
+ sessionId = randomUUID(),
2180
+ stripInternalMessages = true,
2181
+ keepSystemMessage = true,
2182
+ deepCopy = true,
2183
+ overrides = {}
2184
+ } = options;
2185
+
2186
+ // Clone the history
2187
+ let clonedHistory = deepCopy
2188
+ ? JSON.parse(JSON.stringify(this.history))
2189
+ : [...this.history];
2190
+
2191
+ // Strip internal messages if requested
2192
+ if (stripInternalMessages) {
2193
+ clonedHistory = this._stripInternalMessages(clonedHistory, keepSystemMessage);
2194
+ }
2195
+
2196
+ // Create new agent with same configuration
2197
+ const clonedAgent = new ProbeAgent({
2198
+ // Copy current agent's config
2199
+ customPrompt: this.customPrompt,
2200
+ promptType: this.promptType,
2201
+ allowEdit: this.allowEdit,
2202
+ path: this.allowedFolders[0], // Use first allowed folder as primary path
2203
+ allowedFolders: [...this.allowedFolders],
2204
+ provider: this.clientApiProvider,
2205
+ model: this.modelName,
2206
+ debug: this.debug,
2207
+ outline: this.outline,
2208
+ maxResponseTokens: this.maxResponseTokens,
2209
+ maxIterations: this.maxIterations,
2210
+ disableMermaidValidation: this.disableMermaidValidation,
2211
+ enableMcp: !!this.mcpBridge,
2212
+ mcpConfig: this.mcpConfig,
2213
+ enableBash: this.enableBash,
2214
+ bashConfig: this.bashConfig,
2215
+ storageAdapter: this.storageAdapter,
2216
+ // Override with any provided options
2217
+ sessionId,
2218
+ ...overrides
2219
+ });
2220
+
2221
+ // Set the cloned history directly (before initialization to avoid overwriting)
2222
+ clonedAgent.history = clonedHistory;
2223
+
2224
+ if (this.debug) {
2225
+ console.log(`[DEBUG] Cloned session ${this.sessionId} -> ${sessionId}`);
2226
+ console.log(`[DEBUG] Cloned ${clonedHistory.length} messages (stripInternal: ${stripInternalMessages})`);
2227
+ }
2228
+
2229
+ return clonedAgent;
2230
+ }
2231
+
2232
+ /**
2233
+ * Internal method to strip internal/temporary messages from history
2234
+ * Removes: schema reminders, mermaid fix prompts, tool use reminders, etc.
2235
+ * Keeps: system message, user messages, assistant responses, tool results
2236
+ * @private
2237
+ */
2238
+ _stripInternalMessages(history, keepSystemMessage = true) {
2239
+ const filtered = [];
2240
+
2241
+ for (let i = 0; i < history.length; i++) {
2242
+ const message = history[i];
2243
+
2244
+ // Handle system message
2245
+ if (message.role === 'system') {
2246
+ if (keepSystemMessage) {
2247
+ filtered.push(message);
2248
+ } else if (this.debug) {
2249
+ console.log(`[DEBUG] Removing system message at index ${i}`);
2250
+ }
2251
+ continue;
2252
+ }
2253
+
2254
+ // Check if this is an internal message that should be stripped
2255
+ if (this._isInternalMessage(message, i, history)) {
2256
+ if (this.debug) {
2257
+ console.log(`[DEBUG] Stripping internal message at index ${i}: ${message.role}`);
2258
+ }
2259
+ continue;
2260
+ }
2261
+
2262
+ // Keep this message
2263
+ filtered.push(message);
2264
+ }
2265
+
2266
+ return filtered;
2267
+ }
2268
+
2269
+ /**
2270
+ * Determine if a message is an internal/temporary message
2271
+ * @private
2272
+ */
2273
+ _isInternalMessage(message, index, history) {
2274
+ if (message.role !== 'user') {
2275
+ return false; // Only user messages can be internal reminders
2276
+ }
2277
+
2278
+ // Handle null/undefined content
2279
+ if (!message.content) {
2280
+ return false;
2281
+ }
2282
+
2283
+ const content = typeof message.content === 'string'
2284
+ ? message.content
2285
+ : JSON.stringify(message.content);
2286
+
2287
+ // Schema reminder messages
2288
+ if (content.includes('IMPORTANT: A schema was provided') ||
2289
+ content.includes('You MUST respond with data that matches this schema') ||
2290
+ content.includes('Your response must conform to this schema:')) {
2291
+ return true;
2292
+ }
2293
+
2294
+ // Tool use reminder messages
2295
+ if (content.includes('Please use one of the available tools') &&
2296
+ content.includes('or use attempt_completion') &&
2297
+ content.includes('Remember: Use proper XML format')) {
2298
+ return true;
2299
+ }
2300
+
2301
+ // Mermaid fix prompts
2302
+ if (content.includes('The mermaid diagram in your response has syntax errors') ||
2303
+ content.includes('Please fix the mermaid syntax errors') ||
2304
+ content.includes('Here is the corrected version:')) {
2305
+ return true;
2306
+ }
2307
+
2308
+ // JSON correction prompts
2309
+ if (content.includes('Your response does not match the expected JSON schema') ||
2310
+ content.includes('Please provide a valid JSON response') ||
2311
+ content.includes('Schema validation error:')) {
2312
+ return true;
2313
+ }
2314
+
2315
+ // Empty attempt_complete reminders
2316
+ if (content.includes('When using <attempt_complete>') &&
2317
+ content.includes('this must be the ONLY content in your response')) {
2318
+ return true;
2319
+ }
2320
+
2321
+ return false;
2322
+ }
2323
+
2150
2324
  /**
2151
2325
  * Clean up resources (including MCP connections)
2152
2326
  */