@probelabs/probe 0.6.0-rc100

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.
Files changed (115) hide show
  1. package/README.md +583 -0
  2. package/bin/.gitkeep +0 -0
  3. package/bin/probe +158 -0
  4. package/bin/probe-binary +0 -0
  5. package/build/agent/ProbeAgent.d.ts +199 -0
  6. package/build/agent/ProbeAgent.js +1486 -0
  7. package/build/agent/acp/README.md +347 -0
  8. package/build/agent/acp/connection.js +237 -0
  9. package/build/agent/acp/connection.test.js +311 -0
  10. package/build/agent/acp/examples/simple-client.js +212 -0
  11. package/build/agent/acp/examples/tool-lifecycle.js +230 -0
  12. package/build/agent/acp/final-test.js +173 -0
  13. package/build/agent/acp/index.js +5 -0
  14. package/build/agent/acp/integration.test.js +385 -0
  15. package/build/agent/acp/manual-test.js +410 -0
  16. package/build/agent/acp/protocol-test.js +190 -0
  17. package/build/agent/acp/server.js +448 -0
  18. package/build/agent/acp/server.test.js +371 -0
  19. package/build/agent/acp/test-runner.js +216 -0
  20. package/build/agent/acp/test-utils/README.md +315 -0
  21. package/build/agent/acp/test-utils/acp-tester.js +484 -0
  22. package/build/agent/acp/test-utils/mock-acp-client.js +434 -0
  23. package/build/agent/acp/tools.js +368 -0
  24. package/build/agent/acp/tools.test.js +334 -0
  25. package/build/agent/acp/types.js +218 -0
  26. package/build/agent/acp/types.test.js +327 -0
  27. package/build/agent/appTracer.js +360 -0
  28. package/build/agent/fileSpanExporter.js +169 -0
  29. package/build/agent/index.js +7426 -0
  30. package/build/agent/mcp/client.js +338 -0
  31. package/build/agent/mcp/config.js +313 -0
  32. package/build/agent/mcp/index.js +64 -0
  33. package/build/agent/mcp/xmlBridge.js +371 -0
  34. package/build/agent/mockProvider.js +53 -0
  35. package/build/agent/probeTool.js +257 -0
  36. package/build/agent/schemaUtils.js +1726 -0
  37. package/build/agent/simpleTelemetry.js +267 -0
  38. package/build/agent/telemetry.js +225 -0
  39. package/build/agent/tokenCounter.js +395 -0
  40. package/build/agent/tools.js +163 -0
  41. package/build/cli.js +49 -0
  42. package/build/delegate.js +267 -0
  43. package/build/directory-resolver.js +237 -0
  44. package/build/downloader.js +750 -0
  45. package/build/extract.js +149 -0
  46. package/build/index.js +70 -0
  47. package/build/mcp/index.js +514 -0
  48. package/build/mcp/index.ts +608 -0
  49. package/build/query.js +116 -0
  50. package/build/search.js +247 -0
  51. package/build/tools/common.js +410 -0
  52. package/build/tools/index.js +40 -0
  53. package/build/tools/langchain.js +88 -0
  54. package/build/tools/system-message.js +121 -0
  55. package/build/tools/vercel.js +271 -0
  56. package/build/utils/file-lister.js +193 -0
  57. package/build/utils.js +128 -0
  58. package/cjs/agent/ProbeAgent.cjs +5829 -0
  59. package/cjs/index.cjs +6217 -0
  60. package/cjs/package.json +3 -0
  61. package/index.d.ts +401 -0
  62. package/package.json +114 -0
  63. package/scripts/postinstall.js +172 -0
  64. package/src/agent/ProbeAgent.d.ts +199 -0
  65. package/src/agent/ProbeAgent.js +1486 -0
  66. package/src/agent/acp/README.md +347 -0
  67. package/src/agent/acp/connection.js +237 -0
  68. package/src/agent/acp/connection.test.js +311 -0
  69. package/src/agent/acp/examples/simple-client.js +212 -0
  70. package/src/agent/acp/examples/tool-lifecycle.js +230 -0
  71. package/src/agent/acp/final-test.js +173 -0
  72. package/src/agent/acp/index.js +5 -0
  73. package/src/agent/acp/integration.test.js +385 -0
  74. package/src/agent/acp/manual-test.js +410 -0
  75. package/src/agent/acp/protocol-test.js +190 -0
  76. package/src/agent/acp/server.js +448 -0
  77. package/src/agent/acp/server.test.js +371 -0
  78. package/src/agent/acp/test-runner.js +216 -0
  79. package/src/agent/acp/test-utils/README.md +315 -0
  80. package/src/agent/acp/test-utils/acp-tester.js +484 -0
  81. package/src/agent/acp/test-utils/mock-acp-client.js +434 -0
  82. package/src/agent/acp/tools.js +368 -0
  83. package/src/agent/acp/tools.test.js +334 -0
  84. package/src/agent/acp/types.js +218 -0
  85. package/src/agent/acp/types.test.js +327 -0
  86. package/src/agent/appTracer.js +360 -0
  87. package/src/agent/fileSpanExporter.js +169 -0
  88. package/src/agent/index.js +813 -0
  89. package/src/agent/mcp/client.js +338 -0
  90. package/src/agent/mcp/config.js +313 -0
  91. package/src/agent/mcp/index.js +64 -0
  92. package/src/agent/mcp/xmlBridge.js +371 -0
  93. package/src/agent/mockProvider.js +53 -0
  94. package/src/agent/probeTool.js +257 -0
  95. package/src/agent/schemaUtils.js +1726 -0
  96. package/src/agent/simpleTelemetry.js +267 -0
  97. package/src/agent/telemetry.js +225 -0
  98. package/src/agent/tokenCounter.js +395 -0
  99. package/src/agent/tools.js +163 -0
  100. package/src/cli.js +49 -0
  101. package/src/delegate.js +267 -0
  102. package/src/directory-resolver.js +237 -0
  103. package/src/downloader.js +750 -0
  104. package/src/extract.js +149 -0
  105. package/src/index.js +70 -0
  106. package/src/mcp/index.ts +608 -0
  107. package/src/query.js +116 -0
  108. package/src/search.js +247 -0
  109. package/src/tools/common.js +410 -0
  110. package/src/tools/index.js +40 -0
  111. package/src/tools/langchain.js +88 -0
  112. package/src/tools/system-message.js +121 -0
  113. package/src/tools/vercel.js +271 -0
  114. package/src/utils/file-lister.js +193 -0
  115. package/src/utils.js +128 -0
@@ -0,0 +1,267 @@
1
+ import { existsSync, mkdirSync, createWriteStream } from 'fs';
2
+ import { dirname } from 'path';
3
+
4
+ /**
5
+ * Simple telemetry implementation for probe-agent
6
+ * This provides basic tracing functionality without complex OpenTelemetry dependencies
7
+ */
8
+ export class SimpleTelemetry {
9
+ constructor(options = {}) {
10
+ this.serviceName = options.serviceName || 'probe-agent';
11
+ this.enableFile = options.enableFile || false;
12
+ this.enableConsole = options.enableConsole || false;
13
+ this.filePath = options.filePath || './traces.jsonl';
14
+ this.stream = null;
15
+
16
+ if (this.enableFile) {
17
+ this.initializeFileExporter();
18
+ }
19
+ }
20
+
21
+ initializeFileExporter() {
22
+ try {
23
+ const dir = dirname(this.filePath);
24
+ if (!existsSync(dir)) {
25
+ mkdirSync(dir, { recursive: true });
26
+ }
27
+
28
+ this.stream = createWriteStream(this.filePath, { flags: 'a' });
29
+ this.stream.on('error', (error) => {
30
+ console.error(`[SimpleTelemetry] Stream error: ${error.message}`);
31
+ });
32
+
33
+ console.log(`[SimpleTelemetry] File exporter initialized: ${this.filePath}`);
34
+ } catch (error) {
35
+ console.error(`[SimpleTelemetry] Failed to initialize file exporter: ${error.message}`);
36
+ }
37
+ }
38
+
39
+ createSpan(name, attributes = {}) {
40
+ const span = {
41
+ traceId: this.generateTraceId(),
42
+ spanId: this.generateSpanId(),
43
+ name,
44
+ startTime: Date.now(),
45
+ attributes: { ...attributes, service: this.serviceName },
46
+ events: [],
47
+ status: 'OK'
48
+ };
49
+
50
+ return {
51
+ ...span,
52
+ addEvent: (eventName, eventAttributes = {}) => {
53
+ span.events.push({
54
+ name: eventName,
55
+ time: Date.now(),
56
+ attributes: eventAttributes
57
+ });
58
+ },
59
+ setAttributes: (attrs) => {
60
+ Object.assign(span.attributes, attrs);
61
+ },
62
+ setStatus: (status) => {
63
+ span.status = status;
64
+ },
65
+ end: () => {
66
+ span.endTime = Date.now();
67
+ span.duration = span.endTime - span.startTime;
68
+ this.exportSpan(span);
69
+ }
70
+ };
71
+ }
72
+
73
+ exportSpan(span) {
74
+ const spanData = {
75
+ ...span,
76
+ timestamp: new Date().toISOString()
77
+ };
78
+
79
+ if (this.enableConsole) {
80
+ console.log('[Trace]', JSON.stringify(spanData, null, 2));
81
+ }
82
+
83
+ if (this.enableFile && this.stream) {
84
+ this.stream.write(JSON.stringify(spanData) + '\n');
85
+ }
86
+ }
87
+
88
+ generateTraceId() {
89
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
90
+ }
91
+
92
+ generateSpanId() {
93
+ return Math.random().toString(36).substring(2, 10);
94
+ }
95
+
96
+ async flush() {
97
+ if (this.stream) {
98
+ return new Promise((resolve) => {
99
+ this.stream.once('drain', resolve);
100
+ if (!this.stream.writableNeedDrain) {
101
+ resolve();
102
+ }
103
+ });
104
+ }
105
+ }
106
+
107
+ async shutdown() {
108
+ if (this.stream) {
109
+ return new Promise((resolve) => {
110
+ this.stream.end(() => {
111
+ console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
112
+ resolve();
113
+ });
114
+ });
115
+ }
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Simple tracer for application-level tracing
121
+ */
122
+ export class SimpleAppTracer {
123
+ constructor(telemetry, sessionId = null) {
124
+ this.telemetry = telemetry;
125
+ this.sessionId = sessionId || this.generateSessionId();
126
+ }
127
+
128
+ generateSessionId() {
129
+ return Math.random().toString(36).substring(2, 15);
130
+ }
131
+
132
+ isEnabled() {
133
+ return this.telemetry !== null;
134
+ }
135
+
136
+ createSessionSpan(attributes = {}) {
137
+ if (!this.isEnabled()) return null;
138
+
139
+ return this.telemetry.createSpan('agent.session', {
140
+ 'session.id': this.sessionId,
141
+ ...attributes
142
+ });
143
+ }
144
+
145
+ createAISpan(modelName, provider, attributes = {}) {
146
+ if (!this.isEnabled()) return null;
147
+
148
+ return this.telemetry.createSpan('ai.request', {
149
+ 'ai.model': modelName,
150
+ 'ai.provider': provider,
151
+ 'session.id': this.sessionId,
152
+ ...attributes
153
+ });
154
+ }
155
+
156
+ createToolSpan(toolName, attributes = {}) {
157
+ if (!this.isEnabled()) return null;
158
+
159
+ return this.telemetry.createSpan('tool.call', {
160
+ 'tool.name': toolName,
161
+ 'session.id': this.sessionId,
162
+ ...attributes
163
+ });
164
+ }
165
+
166
+ addEvent(name, attributes = {}) {
167
+ // For simplicity, just log events when no active span
168
+ if (this.telemetry && this.telemetry.enableConsole) {
169
+ console.log('[Event]', name, attributes);
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Record delegation events
175
+ */
176
+ recordDelegationEvent(eventType, data = {}) {
177
+ if (!this.isEnabled()) return;
178
+
179
+ this.addEvent(`delegation.${eventType}`, {
180
+ 'session.id': this.sessionId,
181
+ ...data
182
+ });
183
+ }
184
+
185
+ /**
186
+ * Record JSON validation events
187
+ */
188
+ recordJsonValidationEvent(eventType, data = {}) {
189
+ if (!this.isEnabled()) return;
190
+
191
+ this.addEvent(`json_validation.${eventType}`, {
192
+ 'session.id': this.sessionId,
193
+ ...data
194
+ });
195
+ }
196
+
197
+ /**
198
+ * Record Mermaid validation events
199
+ */
200
+ recordMermaidValidationEvent(eventType, data = {}) {
201
+ if (!this.isEnabled()) return;
202
+
203
+ this.addEvent(`mermaid_validation.${eventType}`, {
204
+ 'session.id': this.sessionId,
205
+ ...data
206
+ });
207
+ }
208
+
209
+ setAttributes(attributes) {
210
+ // For simplicity, just log attributes when no active span
211
+ if (this.telemetry && this.telemetry.enableConsole) {
212
+ console.log('[Attributes]', attributes);
213
+ }
214
+ }
215
+
216
+ async withSpan(spanName, fn, attributes = {}) {
217
+ if (!this.isEnabled()) {
218
+ return fn();
219
+ }
220
+
221
+ const span = this.telemetry.createSpan(spanName, {
222
+ 'session.id': this.sessionId,
223
+ ...attributes
224
+ });
225
+
226
+ try {
227
+ const result = await fn();
228
+ span.setStatus('OK');
229
+ return result;
230
+ } catch (error) {
231
+ span.setStatus('ERROR');
232
+ span.addEvent('exception', {
233
+ 'exception.message': error.message,
234
+ 'exception.stack': error.stack
235
+ });
236
+ throw error;
237
+ } finally {
238
+ span.end();
239
+ }
240
+ }
241
+
242
+ async flush() {
243
+ if (this.telemetry) {
244
+ await this.telemetry.flush();
245
+ }
246
+ }
247
+
248
+ async shutdown() {
249
+ if (this.telemetry) {
250
+ await this.telemetry.shutdown();
251
+ }
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Initialize simple telemetry from CLI options
257
+ */
258
+ export function initializeSimpleTelemetryFromOptions(options) {
259
+ const telemetry = new SimpleTelemetry({
260
+ serviceName: 'probe-agent',
261
+ enableFile: options.traceFile !== undefined,
262
+ enableConsole: options.traceConsole,
263
+ filePath: options.traceFile || './traces.jsonl'
264
+ });
265
+
266
+ return telemetry;
267
+ }
@@ -0,0 +1,225 @@
1
+ import nodeSDKPkg from '@opentelemetry/sdk-node';
2
+ import resourcesPkg from '@opentelemetry/resources';
3
+ import semanticConventionsPkg from '@opentelemetry/semantic-conventions';
4
+ import { trace, context, SpanStatusCode } from '@opentelemetry/api';
5
+ import otlpPkg from '@opentelemetry/exporter-trace-otlp-http';
6
+ import spanPkg from '@opentelemetry/sdk-trace-base';
7
+
8
+ import { existsSync, mkdirSync } from 'fs';
9
+ import { dirname } from 'path';
10
+ import { FileSpanExporter } from './fileSpanExporter.js';
11
+
12
+ const { NodeSDK } = nodeSDKPkg;
13
+ const { resourceFromAttributes } = resourcesPkg;
14
+ const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = semanticConventionsPkg;
15
+ const { OTLPTraceExporter } = otlpPkg;
16
+ const { BatchSpanProcessor, ConsoleSpanExporter } = spanPkg;
17
+
18
+ /**
19
+ * Custom OpenTelemetry configuration for probe-agent
20
+ */
21
+ export class TelemetryConfig {
22
+ constructor(options = {}) {
23
+ this.serviceName = options.serviceName || 'probe-agent';
24
+ this.serviceVersion = options.serviceVersion || '1.0.0';
25
+ this.enableFile = options.enableFile || false;
26
+ this.enableRemote = options.enableRemote || false;
27
+ this.enableConsole = options.enableConsole || false;
28
+ this.filePath = options.filePath || './traces.jsonl';
29
+ this.remoteEndpoint = options.remoteEndpoint || 'http://localhost:4318/v1/traces';
30
+ this.sdk = null;
31
+ this.tracer = null;
32
+ }
33
+
34
+ /**
35
+ * Initialize OpenTelemetry SDK
36
+ */
37
+ initialize() {
38
+ if (this.sdk) {
39
+ console.warn('Telemetry already initialized');
40
+ return;
41
+ }
42
+
43
+ const resource = resourceFromAttributes({
44
+ [ATTR_SERVICE_NAME]: this.serviceName,
45
+ [ATTR_SERVICE_VERSION]: this.serviceVersion,
46
+ });
47
+
48
+ const spanProcessors = [];
49
+
50
+ // Add file exporter if enabled
51
+ if (this.enableFile) {
52
+ try {
53
+ // Ensure the directory exists
54
+ const dir = dirname(this.filePath);
55
+ if (!existsSync(dir)) {
56
+ mkdirSync(dir, { recursive: true });
57
+ }
58
+
59
+ const fileExporter = new FileSpanExporter(this.filePath);
60
+ spanProcessors.push(new BatchSpanProcessor(fileExporter, {
61
+ maxQueueSize: 2048,
62
+ maxExportBatchSize: 512,
63
+ scheduledDelayMillis: 500,
64
+ exportTimeoutMillis: 30000,
65
+ }));
66
+ console.log(`[Telemetry] File exporter enabled, writing to: ${this.filePath}`);
67
+ } catch (error) {
68
+ console.error(`[Telemetry] Failed to initialize file exporter: ${error.message}`);
69
+ }
70
+ }
71
+
72
+ // Add remote exporter if enabled
73
+ if (this.enableRemote) {
74
+ try {
75
+ const remoteExporter = new OTLPTraceExporter({
76
+ url: this.remoteEndpoint,
77
+ });
78
+ spanProcessors.push(new BatchSpanProcessor(remoteExporter, {
79
+ maxQueueSize: 2048,
80
+ maxExportBatchSize: 512,
81
+ scheduledDelayMillis: 500,
82
+ exportTimeoutMillis: 30000,
83
+ }));
84
+ console.log(`[Telemetry] Remote exporter enabled, endpoint: ${this.remoteEndpoint}`);
85
+ } catch (error) {
86
+ console.error(`[Telemetry] Failed to initialize remote exporter: ${error.message}`);
87
+ }
88
+ }
89
+
90
+ // Add console exporter if enabled (useful for debugging)
91
+ if (this.enableConsole) {
92
+ const consoleExporter = new ConsoleSpanExporter();
93
+ spanProcessors.push(new BatchSpanProcessor(consoleExporter, {
94
+ maxQueueSize: 2048,
95
+ maxExportBatchSize: 512,
96
+ scheduledDelayMillis: 500,
97
+ exportTimeoutMillis: 30000,
98
+ }));
99
+ console.log(`[Telemetry] Console exporter enabled`);
100
+ }
101
+
102
+ if (spanProcessors.length === 0) {
103
+ console.log('[Telemetry] No exporters configured, telemetry will not be collected');
104
+ return;
105
+ }
106
+
107
+ this.sdk = new NodeSDK({
108
+ resource,
109
+ spanProcessors,
110
+ });
111
+
112
+ try {
113
+ this.sdk.start();
114
+ this.tracer = trace.getTracer(this.serviceName, this.serviceVersion);
115
+ console.log(`[Telemetry] OpenTelemetry SDK initialized successfully`);
116
+ } catch (error) {
117
+ console.error(`[Telemetry] Failed to start OpenTelemetry SDK: ${error.message}`);
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Get the tracer instance
123
+ */
124
+ getTracer() {
125
+ return this.tracer;
126
+ }
127
+
128
+ /**
129
+ * Create a span with the given name and attributes
130
+ */
131
+ createSpan(name, attributes = {}) {
132
+ if (!this.tracer) {
133
+ return null;
134
+ }
135
+
136
+ return this.tracer.startSpan(name, {
137
+ attributes,
138
+ });
139
+ }
140
+
141
+ /**
142
+ * Wrap a function to automatically create spans
143
+ */
144
+ wrapFunction(name, fn, attributes = {}) {
145
+ if (!this.tracer) {
146
+ return fn;
147
+ }
148
+
149
+ return async (...args) => {
150
+ const span = this.createSpan(name, attributes);
151
+ if (!span) {
152
+ return fn(...args);
153
+ }
154
+
155
+ try {
156
+ const result = await context.with(trace.setSpan(context.active(), span), () => fn(...args));
157
+ span.setStatus({ code: SpanStatusCode.OK });
158
+ return result;
159
+ } catch (error) {
160
+ span.setStatus({
161
+ code: SpanStatusCode.ERROR,
162
+ message: error.message,
163
+ });
164
+ span.recordException(error);
165
+ throw error;
166
+ } finally {
167
+ span.end();
168
+ }
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Force flush all pending spans
174
+ */
175
+ async forceFlush() {
176
+ if (this.sdk) {
177
+ try {
178
+ const tracerProvider = trace.getTracerProvider();
179
+
180
+ if (tracerProvider && typeof tracerProvider.forceFlush === 'function') {
181
+ await tracerProvider.forceFlush();
182
+ }
183
+
184
+ // Add a small delay to ensure file writes complete
185
+ await new Promise(resolve => setTimeout(resolve, 100));
186
+
187
+ console.log('[Telemetry] OpenTelemetry spans flushed successfully');
188
+ } catch (error) {
189
+ console.error(`[Telemetry] Failed to flush OpenTelemetry spans: ${error.message}`);
190
+ }
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Shutdown telemetry
196
+ */
197
+ async shutdown() {
198
+ if (this.sdk) {
199
+ try {
200
+ await this.sdk.shutdown();
201
+ console.log('[Telemetry] OpenTelemetry SDK shutdown successfully');
202
+ } catch (error) {
203
+ console.error(`[Telemetry] Failed to shutdown OpenTelemetry SDK: ${error.message}`);
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Initialize telemetry from CLI options
211
+ */
212
+ export function initializeTelemetryFromOptions(options) {
213
+ const config = new TelemetryConfig({
214
+ serviceName: 'probe-agent',
215
+ serviceVersion: '1.0.0',
216
+ enableFile: options.traceFile !== undefined,
217
+ enableRemote: options.traceRemote !== undefined,
218
+ enableConsole: options.traceConsole,
219
+ filePath: options.traceFile || './traces.jsonl',
220
+ remoteEndpoint: options.traceRemote || 'http://localhost:4318/v1/traces',
221
+ });
222
+
223
+ config.initialize();
224
+ return config;
225
+ }