@probelabs/probe 0.6.0-rc147 → 0.6.0-rc149
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/bin/probe +12 -3
- package/build/agent/ProbeAgent.js +1 -3
- package/build/agent/index.js +58 -477
- package/build/extract.js +1 -1
- package/build/index.js +1 -7
- package/build/mcp/index.js +3 -3
- package/build/mcp/index.ts +3 -3
- package/build/tools/common.js +58 -49
- package/cjs/agent/ProbeAgent.cjs +699 -770
- package/cjs/index.cjs +650 -1347
- package/package.json +1 -12
- package/src/agent/ProbeAgent.js +1 -3
- package/src/extract.js +1 -1
- package/src/index.js +1 -7
- package/src/mcp/index.ts +3 -3
- package/src/tools/common.js +58 -49
- package/bin/binaries/probe-v0.6.0-rc147-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-aarch64-unknown-linux-gnu.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-x86_64-unknown-linux-gnu.tar.gz +0 -0
- package/build/agent/appTracer.js +0 -360
- package/build/agent/fileSpanExporter.js +0 -167
- package/build/agent/telemetry.js +0 -219
- package/cjs/agent/telemetry.cjs +0 -358
- package/src/agent/appTracer.js +0 -360
- package/src/agent/fileSpanExporter.js +0 -167
- package/src/agent/telemetry.js +0 -219
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@probelabs/probe",
|
|
3
|
-
"version": "0.6.0-
|
|
3
|
+
"version": "0.6.0-rc149",
|
|
4
4
|
"description": "Node.js wrapper for the probe code search tool",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -21,10 +21,6 @@
|
|
|
21
21
|
"import": "./src/agent/simpleTelemetry.js",
|
|
22
22
|
"require": "./cjs/agent/simpleTelemetry.cjs"
|
|
23
23
|
},
|
|
24
|
-
"./telemetry/full": {
|
|
25
|
-
"import": "./src/agent/telemetry.js",
|
|
26
|
-
"require": "./cjs/agent/telemetry.cjs"
|
|
27
|
-
},
|
|
28
24
|
"./agent/mcp": {
|
|
29
25
|
"import": "./src/agent/mcp/index.js"
|
|
30
26
|
}
|
|
@@ -79,13 +75,6 @@
|
|
|
79
75
|
"@ai-sdk/google": "^2.0.14",
|
|
80
76
|
"@ai-sdk/openai": "^2.0.10",
|
|
81
77
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
82
|
-
"@opentelemetry/api": "^1.9.0",
|
|
83
|
-
"@opentelemetry/core": "^1.30.1",
|
|
84
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.203.0",
|
|
85
|
-
"@opentelemetry/resources": "^2.0.1",
|
|
86
|
-
"@opentelemetry/sdk-node": "^0.203.0",
|
|
87
|
-
"@opentelemetry/sdk-trace-base": "^1.30.0",
|
|
88
|
-
"@opentelemetry/semantic-conventions": "^1.36.0",
|
|
89
78
|
"@probelabs/maid": "^0.0.16",
|
|
90
79
|
"ai": "^5.0.0",
|
|
91
80
|
"axios": "^1.8.3",
|
package/src/agent/ProbeAgent.js
CHANGED
package/src/extract.js
CHANGED
|
@@ -48,7 +48,7 @@ export async function extract(options) {
|
|
|
48
48
|
const hasContent = options.content !== undefined && options.content !== null;
|
|
49
49
|
|
|
50
50
|
if (!hasFiles && !hasInputFile && !hasContent) {
|
|
51
|
-
throw new Error('
|
|
51
|
+
throw new Error('Extract requires one of: "files" (array of file paths), "inputFile" (path to input file), or "content" (string/buffer for stdin)');
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// Get the binary path
|
package/src/index.js
CHANGED
|
@@ -39,8 +39,6 @@ import { searchTool, queryTool, extractTool, delegateTool } from './tools/vercel
|
|
|
39
39
|
import { bashTool } from './tools/bash.js';
|
|
40
40
|
import { ProbeAgent } from './agent/ProbeAgent.js';
|
|
41
41
|
import { SimpleTelemetry, SimpleAppTracer, initializeSimpleTelemetryFromOptions } from './agent/simpleTelemetry.js';
|
|
42
|
-
import { TelemetryConfig, initializeTelemetryFromOptions } from './agent/telemetry.js';
|
|
43
|
-
import { AppTracer } from './agent/appTracer.js';
|
|
44
42
|
import { listFilesToolInstance, searchFilesToolInstance } from './agent/probeTool.js';
|
|
45
43
|
import { StorageAdapter, InMemoryStorageAdapter } from './agent/storage/index.js';
|
|
46
44
|
import { HookManager, HOOK_TYPES } from './agent/hooks/index.js';
|
|
@@ -64,14 +62,10 @@ export {
|
|
|
64
62
|
// Export hooks
|
|
65
63
|
HookManager,
|
|
66
64
|
HOOK_TYPES,
|
|
67
|
-
// Export simple telemetry classes (no
|
|
65
|
+
// Export simple telemetry classes (lightweight, no heavy dependencies)
|
|
68
66
|
SimpleTelemetry,
|
|
69
67
|
SimpleAppTracer,
|
|
70
68
|
initializeSimpleTelemetryFromOptions,
|
|
71
|
-
// Export full OpenTelemetry telemetry classes
|
|
72
|
-
TelemetryConfig,
|
|
73
|
-
AppTracer,
|
|
74
|
-
initializeTelemetryFromOptions,
|
|
75
69
|
// Export tool generators directly
|
|
76
70
|
searchTool,
|
|
77
71
|
queryTool,
|
package/src/mcp/index.ts
CHANGED
|
@@ -199,18 +199,18 @@ class ProbeServer {
|
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
name: 'extract_code',
|
|
202
|
-
description: "Extract code from files
|
|
202
|
+
description: "Extract code blocks from files using tree-sitter AST parsing. Each file path can include optional line numbers or symbol names to extract specific code blocks.",
|
|
203
203
|
inputSchema: {
|
|
204
204
|
type: 'object',
|
|
205
205
|
properties: {
|
|
206
206
|
path: {
|
|
207
207
|
type: 'string',
|
|
208
|
-
description: 'Absolute path to the project directory',
|
|
208
|
+
description: 'Absolute path to the project root directory (used as working directory for relative file paths)',
|
|
209
209
|
},
|
|
210
210
|
files: {
|
|
211
211
|
type: 'array',
|
|
212
212
|
items: { type: 'string' },
|
|
213
|
-
description: 'Array of file paths
|
|
213
|
+
description: 'Array of file paths to extract from. Formats: "file.js" (entire file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Line numbers and symbols are part of the path string, not separate parameters. Paths can be absolute or relative to the project directory.',
|
|
214
214
|
}
|
|
215
215
|
},
|
|
216
216
|
required: ['path', 'files'],
|
package/src/tools/common.js
CHANGED
|
@@ -7,13 +7,8 @@ import { z } from 'zod';
|
|
|
7
7
|
|
|
8
8
|
// Common schemas for tool parameters (used for internal execution after XML parsing)
|
|
9
9
|
export const searchSchema = z.object({
|
|
10
|
-
query: z.string().describe('Search query with Elasticsearch syntax. Use
|
|
11
|
-
path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
|
|
12
|
-
allow_tests: z.boolean().optional().default(false).describe('Allow test files in search results'),
|
|
13
|
-
exact: z.boolean().optional().default(false).describe('Perform exact search without tokenization (case-insensitive)'),
|
|
14
|
-
maxResults: z.number().optional().describe('Maximum number of results to return'),
|
|
15
|
-
maxTokens: z.number().optional().default(10000).describe('Maximum number of tokens to return'),
|
|
16
|
-
language: z.string().optional().describe('Limit search to files of a specific programming language')
|
|
10
|
+
query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
|
|
11
|
+
path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
|
|
17
12
|
});
|
|
18
13
|
|
|
19
14
|
export const querySchema = z.object({
|
|
@@ -24,13 +19,8 @@ export const querySchema = z.object({
|
|
|
24
19
|
});
|
|
25
20
|
|
|
26
21
|
export const extractSchema = z.object({
|
|
27
|
-
targets: z.string().optional().describe('File paths or symbols to extract from.
|
|
28
|
-
input_content: z.string().optional().describe('Text content to extract file paths from')
|
|
29
|
-
line: z.number().optional().describe('Start line number to extract a specific code block'),
|
|
30
|
-
end_line: z.number().optional().describe('End line number for extracting a range of lines'),
|
|
31
|
-
allow_tests: z.boolean().optional().default(false).describe('Allow test files and test code blocks'),
|
|
32
|
-
context_lines: z.number().optional().default(10).describe('Number of context lines to include'),
|
|
33
|
-
format: z.string().optional().default('plain').describe('Output format (plain, markdown, json, xml, color, outline-xml, outline-diff)')
|
|
22
|
+
targets: z.string().optional().describe('File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (symbol). Multiple targets separated by spaces.'),
|
|
23
|
+
input_content: z.string().optional().describe('Text content to extract file paths from (alternative to targets)')
|
|
34
24
|
});
|
|
35
25
|
|
|
36
26
|
export const delegateSchema = z.object({
|
|
@@ -120,13 +110,8 @@ You need to focus on main keywords when constructing the query, and always use e
|
|
|
120
110
|
- Once data is returned, it's cached and won't return on next runs (this is expected behavior)
|
|
121
111
|
|
|
122
112
|
Parameters:
|
|
123
|
-
- query: (required) Search query with Elasticsearch syntax.
|
|
124
|
-
- path: (
|
|
125
|
-
- allow_tests: (optional, default: false) Allow test files in search results (true/false).
|
|
126
|
-
- exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
|
|
127
|
-
- maxResults: (optional) Maximum number of results to return (number).
|
|
128
|
-
- maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
|
|
129
|
-
- language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
|
|
113
|
+
- query: (required) Search query with Elasticsearch syntax. Use quotes for exact matches ("functionName"), AND/OR for boolean logic, - for negation, + for important terms.
|
|
114
|
+
- path: (optional, default: '.') Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc.
|
|
130
115
|
|
|
131
116
|
**Workflow:** Always start with search, then use extract for detailed context when needed.
|
|
132
117
|
|
|
@@ -148,30 +133,24 @@ User: How to calculate the total amount in the payments module?
|
|
|
148
133
|
<search>
|
|
149
134
|
<query>calculate AND payment</query>
|
|
150
135
|
<path>src/utils</path>
|
|
151
|
-
<allow_tests>false</allow_tests>
|
|
152
136
|
</search>
|
|
153
137
|
|
|
154
138
|
User: How do the user authentication and authorization work?
|
|
155
139
|
<search>
|
|
156
|
-
<query>+user
|
|
140
|
+
<query>+user AND (authentication OR authorization OR authz)</query>
|
|
157
141
|
<path>.</path>
|
|
158
|
-
<allow_tests>true</allow_tests>
|
|
159
|
-
<language>go</language>
|
|
160
142
|
</search>
|
|
161
143
|
|
|
162
144
|
User: Find all react imports in the project.
|
|
163
145
|
<search>
|
|
164
|
-
<query>import
|
|
146
|
+
<query>"import" AND "react"</query>
|
|
165
147
|
<path>.</path>
|
|
166
|
-
<exact>true</exact>
|
|
167
|
-
<language>js</language>
|
|
168
148
|
</search>
|
|
169
149
|
|
|
170
|
-
User: Find how
|
|
150
|
+
User: Find how decompound library works?
|
|
171
151
|
<search>
|
|
172
|
-
<query>
|
|
152
|
+
<query>decompound</query>
|
|
173
153
|
<path>/dep/rust/decompound</path>
|
|
174
|
-
<language>rust</language>
|
|
175
154
|
</search>
|
|
176
155
|
|
|
177
156
|
</examples>
|
|
@@ -208,11 +187,9 @@ Full file extraction should be the LAST RESORT! Always prefer search.
|
|
|
208
187
|
**Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
|
|
209
188
|
|
|
210
189
|
Parameters:
|
|
211
|
-
- targets: (required) File paths or symbols to extract from.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
- end_line: (optional) End line number for extracting a range of lines.
|
|
215
|
-
- allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
|
|
190
|
+
- targets: (required) File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Multiple targets separated by spaces.
|
|
191
|
+
- input_content: (optional) Text content to extract file paths from (alternative to targets for processing diffs/logs).
|
|
192
|
+
|
|
216
193
|
Usage Example:
|
|
217
194
|
|
|
218
195
|
<examples>
|
|
@@ -239,9 +216,7 @@ User: Lets read the whole file
|
|
|
239
216
|
|
|
240
217
|
User: Read the first 10 lines of the file
|
|
241
218
|
<extract>
|
|
242
|
-
<targets>src/search/ranking.rs</targets>
|
|
243
|
-
<line>1</line>
|
|
244
|
-
<end_line>10</end_line>
|
|
219
|
+
<targets>src/search/ranking.rs:1-10</targets>
|
|
245
220
|
</extract>
|
|
246
221
|
|
|
247
222
|
User: Read file inside the dependency
|
|
@@ -349,7 +324,7 @@ export const bashDescription = 'Execute bash commands for system exploration and
|
|
|
349
324
|
// Valid tool names that should be parsed as tool calls
|
|
350
325
|
const DEFAULT_VALID_TOOLS = [
|
|
351
326
|
'search',
|
|
352
|
-
'query',
|
|
327
|
+
'query',
|
|
353
328
|
'extract',
|
|
354
329
|
'delegate',
|
|
355
330
|
'listFiles',
|
|
@@ -358,6 +333,43 @@ const DEFAULT_VALID_TOOLS = [
|
|
|
358
333
|
'attempt_completion'
|
|
359
334
|
];
|
|
360
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Get valid parameter names for a specific tool from its schema
|
|
338
|
+
* @param {string} toolName - Name of the tool
|
|
339
|
+
* @returns {string[]} - Array of valid parameter names for this tool
|
|
340
|
+
*/
|
|
341
|
+
function getValidParamsForTool(toolName) {
|
|
342
|
+
// Map tool names to their schemas
|
|
343
|
+
const schemaMap = {
|
|
344
|
+
search: searchSchema,
|
|
345
|
+
query: querySchema,
|
|
346
|
+
extract: extractSchema,
|
|
347
|
+
delegate: delegateSchema,
|
|
348
|
+
bash: bashSchema,
|
|
349
|
+
attempt_completion: attemptCompletionSchema
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const schema = schemaMap[toolName];
|
|
353
|
+
if (!schema) {
|
|
354
|
+
// For tools without schema (listFiles, searchFiles, implement), return common params
|
|
355
|
+
// These are the shared params that appear across multiple tools
|
|
356
|
+
return ['path', 'directory', 'pattern', 'recursive', 'includeHidden', 'task', 'files', 'autoCommits', 'result'];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// For attempt_completion, it has custom validation, just return 'result'
|
|
360
|
+
if (toolName === 'attempt_completion') {
|
|
361
|
+
return ['result'];
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Extract keys from Zod schema
|
|
365
|
+
if (schema && schema._def && schema._def.shape) {
|
|
366
|
+
return Object.keys(schema._def.shape());
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Fallback: return empty array if we can't extract schema keys
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
372
|
+
|
|
361
373
|
// Simple XML parser helper - safer string-based approach
|
|
362
374
|
export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
363
375
|
// Look for each valid tool name specifically using string search
|
|
@@ -387,15 +399,12 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
|
387
399
|
|
|
388
400
|
const params = {};
|
|
389
401
|
|
|
402
|
+
// Get valid parameters for this specific tool from its schema
|
|
403
|
+
const validParams = getValidParamsForTool(toolName);
|
|
404
|
+
|
|
390
405
|
// Parse parameters using string-based approach for better safety
|
|
391
|
-
//
|
|
392
|
-
|
|
393
|
-
const commonParams = ['query', 'file_path', 'line', 'end_line', 'path', 'recursive', 'includeHidden',
|
|
394
|
-
'max_results', 'maxResults', 'result', 'command', 'description', 'task', 'param', 'pattern',
|
|
395
|
-
'allow_tests', 'exact', 'maxTokens', 'language', 'input_content',
|
|
396
|
-
'context_lines', 'format', 'directory', 'autoCommits', 'files', 'targets'];
|
|
397
|
-
|
|
398
|
-
for (const paramName of commonParams) {
|
|
406
|
+
// Only look for parameters that are valid for this specific tool
|
|
407
|
+
for (const paramName of validParams) {
|
|
399
408
|
const paramOpenTag = `<${paramName}>`;
|
|
400
409
|
const paramCloseTag = `</${paramName}>`;
|
|
401
410
|
|
|
@@ -410,7 +419,7 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
|
410
419
|
if (paramCloseIndex === -1) {
|
|
411
420
|
// Find the next opening tag after this parameter
|
|
412
421
|
let nextTagIndex = innerContent.length;
|
|
413
|
-
for (const nextParam of
|
|
422
|
+
for (const nextParam of validParams) {
|
|
414
423
|
const nextOpenTag = `<${nextParam}>`;
|
|
415
424
|
const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
|
|
416
425
|
if (nextIndex !== -1 && nextIndex < nextTagIndex) {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/build/agent/appTracer.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import { trace, context, SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Application-specific tracing layer for probe-agent
|
|
5
|
-
* Provides higher-level tracing functions for AI operations and tool calls
|
|
6
|
-
*/
|
|
7
|
-
export class AppTracer {
|
|
8
|
-
constructor(telemetryConfig, sessionId = null) {
|
|
9
|
-
this.telemetryConfig = telemetryConfig;
|
|
10
|
-
this.tracer = telemetryConfig?.getTracer();
|
|
11
|
-
this.sessionId = sessionId || this.generateSessionId();
|
|
12
|
-
this.traceId = this.generateTraceId();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Generate a unique session ID
|
|
17
|
-
*/
|
|
18
|
-
generateSessionId() {
|
|
19
|
-
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Generate trace ID from session ID for consistent tracing
|
|
24
|
-
*/
|
|
25
|
-
generateTraceId() {
|
|
26
|
-
if (!this.sessionId) return null;
|
|
27
|
-
|
|
28
|
-
// Create a deterministic trace ID from session ID
|
|
29
|
-
const hash = this.hashString(this.sessionId);
|
|
30
|
-
return hash.padEnd(32, '0').substring(0, 32);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Simple hash function for session ID
|
|
35
|
-
*/
|
|
36
|
-
hashString(str) {
|
|
37
|
-
let hash = 0;
|
|
38
|
-
for (let i = 0; i < str.length; i++) {
|
|
39
|
-
const char = str.charCodeAt(i);
|
|
40
|
-
hash = ((hash << 5) - hash) + char;
|
|
41
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
42
|
-
}
|
|
43
|
-
return Math.abs(hash).toString(16);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Check if tracing is enabled
|
|
48
|
-
*/
|
|
49
|
-
isEnabled() {
|
|
50
|
-
return this.tracer !== null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Create a root span for the agent session
|
|
55
|
-
*/
|
|
56
|
-
createSessionSpan(attributes = {}) {
|
|
57
|
-
if (!this.isEnabled()) return null;
|
|
58
|
-
|
|
59
|
-
return this.tracer.startSpan('agent.session', {
|
|
60
|
-
attributes: {
|
|
61
|
-
'session.id': this.sessionId,
|
|
62
|
-
'trace.id': this.traceId,
|
|
63
|
-
...attributes,
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Create a span for AI model requests
|
|
70
|
-
*/
|
|
71
|
-
createAISpan(modelName, provider, attributes = {}) {
|
|
72
|
-
if (!this.isEnabled()) return null;
|
|
73
|
-
|
|
74
|
-
return this.tracer.startSpan('ai.request', {
|
|
75
|
-
attributes: {
|
|
76
|
-
'ai.model': modelName,
|
|
77
|
-
'ai.provider': provider,
|
|
78
|
-
'session.id': this.sessionId,
|
|
79
|
-
...attributes,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Create a span for tool calls
|
|
86
|
-
*/
|
|
87
|
-
createToolSpan(toolName, attributes = {}) {
|
|
88
|
-
if (!this.isEnabled()) return null;
|
|
89
|
-
|
|
90
|
-
return this.tracer.startSpan('tool.call', {
|
|
91
|
-
attributes: {
|
|
92
|
-
'tool.name': toolName,
|
|
93
|
-
'session.id': this.sessionId,
|
|
94
|
-
...attributes,
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Create a span for code search operations
|
|
101
|
-
*/
|
|
102
|
-
createSearchSpan(query, attributes = {}) {
|
|
103
|
-
if (!this.isEnabled()) return null;
|
|
104
|
-
|
|
105
|
-
return this.tracer.startSpan('search.query', {
|
|
106
|
-
attributes: {
|
|
107
|
-
'search.query': query,
|
|
108
|
-
'session.id': this.sessionId,
|
|
109
|
-
...attributes,
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Create a span for code extraction operations
|
|
116
|
-
*/
|
|
117
|
-
createExtractSpan(files, attributes = {}) {
|
|
118
|
-
if (!this.isEnabled()) return null;
|
|
119
|
-
|
|
120
|
-
return this.tracer.startSpan('extract.files', {
|
|
121
|
-
attributes: {
|
|
122
|
-
'extract.file_count': Array.isArray(files) ? files.length : 1,
|
|
123
|
-
'extract.files': Array.isArray(files) ? files.join(',') : files,
|
|
124
|
-
'session.id': this.sessionId,
|
|
125
|
-
...attributes,
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Create a span for agent iterations
|
|
132
|
-
*/
|
|
133
|
-
createIterationSpan(iteration, attributes = {}) {
|
|
134
|
-
if (!this.isEnabled()) return null;
|
|
135
|
-
|
|
136
|
-
return this.tracer.startSpan('agent.iteration', {
|
|
137
|
-
attributes: {
|
|
138
|
-
'iteration.number': iteration,
|
|
139
|
-
'session.id': this.sessionId,
|
|
140
|
-
...attributes,
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Create a span for delegation operations
|
|
147
|
-
*/
|
|
148
|
-
createDelegationSpan(task, attributes = {}) {
|
|
149
|
-
if (!this.isEnabled()) return null;
|
|
150
|
-
|
|
151
|
-
return this.tracer.startSpan('agent.delegation', {
|
|
152
|
-
attributes: {
|
|
153
|
-
'delegation.task': task.substring(0, 200) + (task.length > 200 ? '...' : ''),
|
|
154
|
-
'delegation.task_length': task.length,
|
|
155
|
-
'session.id': this.sessionId,
|
|
156
|
-
...attributes,
|
|
157
|
-
},
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Create a span for JSON validation operations
|
|
163
|
-
*/
|
|
164
|
-
createJsonValidationSpan(responseLength, attributes = {}) {
|
|
165
|
-
if (!this.isEnabled()) return null;
|
|
166
|
-
|
|
167
|
-
return this.tracer.startSpan('validation.json', {
|
|
168
|
-
attributes: {
|
|
169
|
-
'validation.response_length': responseLength,
|
|
170
|
-
'session.id': this.sessionId,
|
|
171
|
-
...attributes,
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Create a span for Mermaid validation operations
|
|
178
|
-
*/
|
|
179
|
-
createMermaidValidationSpan(diagramCount, attributes = {}) {
|
|
180
|
-
if (!this.isEnabled()) return null;
|
|
181
|
-
|
|
182
|
-
return this.tracer.startSpan('validation.mermaid', {
|
|
183
|
-
attributes: {
|
|
184
|
-
'validation.diagram_count': diagramCount,
|
|
185
|
-
'session.id': this.sessionId,
|
|
186
|
-
...attributes,
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Create a span for schema processing operations
|
|
193
|
-
*/
|
|
194
|
-
createSchemaProcessingSpan(schemaType, attributes = {}) {
|
|
195
|
-
if (!this.isEnabled()) return null;
|
|
196
|
-
|
|
197
|
-
return this.tracer.startSpan('schema.processing', {
|
|
198
|
-
attributes: {
|
|
199
|
-
'schema.type': schemaType,
|
|
200
|
-
'session.id': this.sessionId,
|
|
201
|
-
...attributes,
|
|
202
|
-
},
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Record delegation events
|
|
208
|
-
*/
|
|
209
|
-
recordDelegationEvent(eventType, data = {}) {
|
|
210
|
-
if (!this.isEnabled()) return;
|
|
211
|
-
|
|
212
|
-
this.addEvent(`delegation.${eventType}`, {
|
|
213
|
-
'session.id': this.sessionId,
|
|
214
|
-
...data
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Record JSON validation events
|
|
220
|
-
*/
|
|
221
|
-
recordJsonValidationEvent(eventType, data = {}) {
|
|
222
|
-
if (!this.isEnabled()) return;
|
|
223
|
-
|
|
224
|
-
this.addEvent(`json_validation.${eventType}`, {
|
|
225
|
-
'session.id': this.sessionId,
|
|
226
|
-
...data
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Record Mermaid validation events
|
|
232
|
-
*/
|
|
233
|
-
recordMermaidValidationEvent(eventType, data = {}) {
|
|
234
|
-
if (!this.isEnabled()) return;
|
|
235
|
-
|
|
236
|
-
this.addEvent(`mermaid_validation.${eventType}`, {
|
|
237
|
-
'session.id': this.sessionId,
|
|
238
|
-
...data
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Add an event to the current or most recent span
|
|
244
|
-
*/
|
|
245
|
-
addEvent(name, attributes = {}) {
|
|
246
|
-
if (!this.isEnabled()) return;
|
|
247
|
-
|
|
248
|
-
// Try to add to the current span in context
|
|
249
|
-
const activeSpan = trace.getActiveSpan();
|
|
250
|
-
if (activeSpan) {
|
|
251
|
-
activeSpan.addEvent(name, {
|
|
252
|
-
'session.id': this.sessionId,
|
|
253
|
-
...attributes,
|
|
254
|
-
});
|
|
255
|
-
} else {
|
|
256
|
-
// Fallback: log as structured data if no active span
|
|
257
|
-
if (this.telemetryConfig?.enableConsole) {
|
|
258
|
-
console.log(`[Event] ${name}:`, attributes);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Set attributes on the current span
|
|
265
|
-
*/
|
|
266
|
-
setAttributes(attributes) {
|
|
267
|
-
if (!this.isEnabled()) return;
|
|
268
|
-
|
|
269
|
-
const activeSpan = trace.getActiveSpan();
|
|
270
|
-
if (activeSpan) {
|
|
271
|
-
activeSpan.setAttributes({
|
|
272
|
-
'session.id': this.sessionId,
|
|
273
|
-
...attributes,
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Wrap a function with automatic span creation
|
|
280
|
-
*/
|
|
281
|
-
wrapFunction(spanName, fn, attributes = {}) {
|
|
282
|
-
if (!this.isEnabled()) {
|
|
283
|
-
return fn;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return async (...args) => {
|
|
287
|
-
const span = this.tracer.startSpan(spanName, {
|
|
288
|
-
attributes: {
|
|
289
|
-
'session.id': this.sessionId,
|
|
290
|
-
...attributes,
|
|
291
|
-
},
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
try {
|
|
295
|
-
const result = await context.with(trace.setSpan(context.active(), span), () => fn(...args));
|
|
296
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
297
|
-
return result;
|
|
298
|
-
} catch (error) {
|
|
299
|
-
span.setStatus({
|
|
300
|
-
code: SpanStatusCode.ERROR,
|
|
301
|
-
message: error.message,
|
|
302
|
-
});
|
|
303
|
-
span.recordException(error);
|
|
304
|
-
throw error;
|
|
305
|
-
} finally {
|
|
306
|
-
span.end();
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Execute a function within a span context
|
|
313
|
-
*/
|
|
314
|
-
async withSpan(spanName, fn, attributes = {}) {
|
|
315
|
-
if (!this.isEnabled()) {
|
|
316
|
-
return fn();
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const span = this.tracer.startSpan(spanName, {
|
|
320
|
-
attributes: {
|
|
321
|
-
'session.id': this.sessionId,
|
|
322
|
-
...attributes,
|
|
323
|
-
},
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
try {
|
|
327
|
-
const result = await context.with(trace.setSpan(context.active(), span), () => fn());
|
|
328
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
329
|
-
return result;
|
|
330
|
-
} catch (error) {
|
|
331
|
-
span.setStatus({
|
|
332
|
-
code: SpanStatusCode.ERROR,
|
|
333
|
-
message: error.message,
|
|
334
|
-
});
|
|
335
|
-
span.recordException(error);
|
|
336
|
-
throw error;
|
|
337
|
-
} finally {
|
|
338
|
-
span.end();
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Force flush all pending spans
|
|
345
|
-
*/
|
|
346
|
-
async flush() {
|
|
347
|
-
if (this.telemetryConfig) {
|
|
348
|
-
await this.telemetryConfig.forceFlush();
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Shutdown tracing
|
|
354
|
-
*/
|
|
355
|
-
async shutdown() {
|
|
356
|
-
if (this.telemetryConfig) {
|
|
357
|
-
await this.telemetryConfig.shutdown();
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|