@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,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
package/index.d.ts ADDED
@@ -0,0 +1,401 @@
1
+ // TypeScript definitions for ProbeAgent SDK
2
+ import { EventEmitter } from 'events';
3
+
4
+ /**
5
+ * Configuration options for creating a ProbeAgent instance
6
+ */
7
+ export interface ProbeAgentOptions {
8
+ /** Optional session ID for the agent */
9
+ sessionId?: string;
10
+ /** Custom system prompt to replace the default system message */
11
+ customPrompt?: string;
12
+ /** Predefined prompt type (persona) */
13
+ promptType?: 'code-explorer' | 'engineer' | 'code-review' | 'support' | 'architect';
14
+ /** Allow the use of the 'implement' tool for code editing */
15
+ allowEdit?: boolean;
16
+ /** Search directory path */
17
+ path?: string;
18
+ /** Force specific AI provider */
19
+ provider?: 'anthropic' | 'openai' | 'google';
20
+ /** Override model name */
21
+ model?: string;
22
+ /** Enable debug mode */
23
+ debug?: boolean;
24
+ /** Optional telemetry tracer instance */
25
+ tracer?: any;
26
+ /** Enable MCP (Model Context Protocol) tool integration */
27
+ enableMcp?: boolean;
28
+ /** Path to MCP configuration file */
29
+ mcpConfigPath?: string;
30
+ /** MCP configuration object (overrides mcpConfigPath) */
31
+ mcpConfig?: any;
32
+ /** @deprecated Use mcpConfig instead */
33
+ mcpServers?: any[];
34
+ }
35
+
36
+ /**
37
+ * Tool execution event data
38
+ */
39
+ export interface ToolCallEvent {
40
+ /** Unique tool call identifier */
41
+ id: string;
42
+ /** Name of the tool being called */
43
+ name: string;
44
+ /** Current execution status */
45
+ status: 'pending' | 'in_progress' | 'completed' | 'failed';
46
+ /** Tool parameters */
47
+ params?: any;
48
+ /** Tool execution result (when completed) */
49
+ result?: any;
50
+ /** Error information (when failed) */
51
+ error?: string;
52
+ /** Session ID */
53
+ sessionId?: string;
54
+ /** Execution start time */
55
+ startTime?: number;
56
+ /** Execution end time */
57
+ endTime?: number;
58
+ /** Execution duration in milliseconds */
59
+ duration?: number;
60
+ }
61
+
62
+ /**
63
+ * Token usage statistics
64
+ */
65
+ export interface TokenUsage {
66
+ /** Size of the context window */
67
+ contextWindow?: number;
68
+ /** Request tokens used */
69
+ request?: number;
70
+ /** Response tokens generated */
71
+ response?: number;
72
+ /** Total tokens (request + response) */
73
+ total?: number;
74
+ /** Cache read tokens */
75
+ cacheRead?: number;
76
+ /** Cache write tokens */
77
+ cacheWrite?: number;
78
+ /** Total request tokens across all calls */
79
+ totalRequest?: number;
80
+ /** Total response tokens across all calls */
81
+ totalResponse?: number;
82
+ /** Total tokens across all calls */
83
+ totalTokens?: number;
84
+ /** Total cache read tokens across all calls */
85
+ totalCacheRead?: number;
86
+ /** Total cache write tokens across all calls */
87
+ totalCacheWrite?: number;
88
+ }
89
+
90
+ /**
91
+ * Chat message structure
92
+ */
93
+ export interface ChatMessage {
94
+ /** Message role */
95
+ role: 'user' | 'assistant' | 'system';
96
+ /** Message content */
97
+ content: string;
98
+ /** Optional message metadata */
99
+ metadata?: any;
100
+ }
101
+
102
+ /**
103
+ * Answer options
104
+ */
105
+ export interface AnswerOptions {
106
+ /** Response schema for structured output */
107
+ schema?: string;
108
+ /** Additional context or constraints */
109
+ context?: string;
110
+ /** Maximum number of tool iterations */
111
+ maxIterations?: number;
112
+ }
113
+
114
+ /**
115
+ * ProbeAgent class - AI-powered code exploration and interaction
116
+ */
117
+ export declare class ProbeAgent {
118
+ /** Unique session identifier */
119
+ readonly sessionId: string;
120
+
121
+ /** Current chat history */
122
+ history: ChatMessage[];
123
+
124
+ /** Event emitter for tool execution updates */
125
+ readonly events: EventEmitter & ProbeAgentEvents;
126
+
127
+ /** Whether the agent allows code editing */
128
+ readonly allowEdit: boolean;
129
+
130
+ /** Allowed search folders */
131
+ readonly allowedFolders: string[];
132
+
133
+ /** Debug mode status */
134
+ readonly debug: boolean;
135
+
136
+ /** Whether operations have been cancelled */
137
+ cancelled: boolean;
138
+
139
+ /**
140
+ * Create a new ProbeAgent instance
141
+ */
142
+ constructor(options?: ProbeAgentOptions);
143
+
144
+ /**
145
+ * Answer a question with optional image attachments
146
+ * @param message - The question or prompt
147
+ * @param images - Optional array of image data or paths
148
+ * @param options - Additional options for the response
149
+ * @returns Promise resolving to the AI response
150
+ */
151
+ answer(message: string, images?: any[], options?: AnswerOptions): Promise<string>;
152
+
153
+ /**
154
+ * Get token usage statistics
155
+ * @returns Current token usage information
156
+ */
157
+ getTokenUsage(): TokenUsage;
158
+
159
+ /**
160
+ * Cancel any ongoing operations
161
+ */
162
+ cancel(): void;
163
+
164
+ /**
165
+ * Clear the conversation history
166
+ */
167
+ clearHistory(): void;
168
+
169
+ /**
170
+ * Add a message to the conversation history
171
+ * @param message - Message to add
172
+ */
173
+ addMessage(message: ChatMessage): void;
174
+
175
+ /**
176
+ * Set the conversation history
177
+ * @param messages - Array of chat messages
178
+ */
179
+ setHistory(messages: ChatMessage[]): void;
180
+ }
181
+
182
+ /**
183
+ * Search tool configuration options
184
+ */
185
+ export interface SearchOptions {
186
+ /** Session identifier */
187
+ sessionId?: string;
188
+ /** Debug mode */
189
+ debug?: boolean;
190
+ /** Default search path */
191
+ defaultPath?: string;
192
+ /** Allowed search folders */
193
+ allowedFolders?: string[];
194
+ }
195
+
196
+ /**
197
+ * Search parameters
198
+ */
199
+ export interface SearchParams {
200
+ /** Search query */
201
+ query: string;
202
+ /** Path to search in */
203
+ path?: string;
204
+ /** Maximum number of results */
205
+ maxResults?: number;
206
+ /** Search timeout in seconds */
207
+ timeout?: number;
208
+ /** Allow test files in results */
209
+ allowTests?: boolean;
210
+ /** Session ID */
211
+ sessionId?: string;
212
+ }
213
+
214
+ /**
215
+ * Query tool parameters for structural code search
216
+ */
217
+ export interface QueryParams {
218
+ /** AST-grep pattern */
219
+ pattern: string;
220
+ /** Path to search in */
221
+ path?: string;
222
+ /** Programming language */
223
+ language?: string;
224
+ /** Maximum number of results */
225
+ maxResults?: number;
226
+ /** Session ID */
227
+ sessionId?: string;
228
+ }
229
+
230
+ /**
231
+ * Extract tool parameters
232
+ */
233
+ export interface ExtractParams {
234
+ /** Files and line numbers or symbols to extract */
235
+ files: string[];
236
+ /** Path to search in */
237
+ path?: string;
238
+ /** Number of context lines */
239
+ contextLines?: number;
240
+ /** Output format */
241
+ format?: 'markdown' | 'plain' | 'json';
242
+ /** Session ID */
243
+ sessionId?: string;
244
+ }
245
+
246
+ /**
247
+ * Tool execution result
248
+ */
249
+ export interface ToolResult {
250
+ /** Whether the operation was successful */
251
+ success: boolean;
252
+ /** Result data */
253
+ result?: any;
254
+ /** Error message if failed */
255
+ error?: string;
256
+ /** Execution metadata */
257
+ metadata?: any;
258
+ }
259
+
260
+ /**
261
+ * Search tool function type
262
+ */
263
+ export type SearchTool = (options?: SearchOptions) => {
264
+ execute(params: SearchParams): Promise<ToolResult>;
265
+ };
266
+
267
+ /**
268
+ * Query tool function type
269
+ */
270
+ export type QueryTool = (options?: SearchOptions) => {
271
+ execute(params: QueryParams): Promise<ToolResult>;
272
+ };
273
+
274
+ /**
275
+ * Extract tool function type
276
+ */
277
+ export type ExtractTool = (options?: SearchOptions) => {
278
+ execute(params: ExtractParams): Promise<ToolResult>;
279
+ };
280
+
281
+ /**
282
+ * Main probe search function
283
+ */
284
+ export declare function search(
285
+ query: string,
286
+ path?: string,
287
+ options?: {
288
+ maxResults?: number;
289
+ timeout?: number;
290
+ allowTests?: boolean;
291
+ }
292
+ ): Promise<any>;
293
+
294
+ /**
295
+ * Structural code query using ast-grep
296
+ */
297
+ export declare function query(
298
+ pattern: string,
299
+ path?: string,
300
+ options?: {
301
+ language?: string;
302
+ maxResults?: number;
303
+ }
304
+ ): Promise<any>;
305
+
306
+ /**
307
+ * Extract code blocks from files
308
+ */
309
+ export declare function extract(
310
+ files: string[],
311
+ path?: string,
312
+ options?: {
313
+ contextLines?: number;
314
+ format?: 'markdown' | 'plain' | 'json';
315
+ }
316
+ ): Promise<any>;
317
+
318
+ /**
319
+ * Create search tool instance
320
+ */
321
+ export declare function searchTool(options?: SearchOptions): ReturnType<SearchTool>;
322
+
323
+ /**
324
+ * Create query tool instance
325
+ */
326
+ export declare function queryTool(options?: SearchOptions): ReturnType<QueryTool>;
327
+
328
+ /**
329
+ * Create extract tool instance
330
+ */
331
+ export declare function extractTool(options?: SearchOptions): ReturnType<ExtractTool>;
332
+
333
+ /**
334
+ * Get the path to the probe binary
335
+ */
336
+ export declare function getBinaryPath(): string;
337
+
338
+ /**
339
+ * Set the path to the probe binary
340
+ */
341
+ export declare function setBinaryPath(path: string): void;
342
+
343
+ /**
344
+ * List files by directory level
345
+ */
346
+ export declare function listFilesByLevel(
347
+ path?: string,
348
+ options?: {
349
+ maxLevel?: number;
350
+ includeHidden?: boolean;
351
+ }
352
+ ): Promise<any>;
353
+
354
+ /**
355
+ * Default system message for AI interactions
356
+ */
357
+ export declare const DEFAULT_SYSTEM_MESSAGE: string;
358
+
359
+ /**
360
+ * Schema definitions
361
+ */
362
+ export declare const searchSchema: any;
363
+ export declare const querySchema: any;
364
+ export declare const extractSchema: any;
365
+ export declare const attemptCompletionSchema: any;
366
+
367
+ /**
368
+ * Tool definitions for AI frameworks
369
+ */
370
+ export declare const searchToolDefinition: any;
371
+ export declare const queryToolDefinition: any;
372
+ export declare const extractToolDefinition: any;
373
+ export declare const attemptCompletionToolDefinition: any;
374
+
375
+ /**
376
+ * Parse XML tool calls
377
+ */
378
+ export declare function parseXmlToolCall(xmlString: string): any;
379
+
380
+ /**
381
+ * Legacy tools object (deprecated - use individual tool functions instead)
382
+ * @deprecated Use searchTool, queryTool, extractTool functions instead
383
+ */
384
+ export declare const tools: {
385
+ search: ReturnType<SearchTool>;
386
+ query: ReturnType<QueryTool>;
387
+ extract: ReturnType<ExtractTool>;
388
+ };
389
+
390
+ /**
391
+ * ProbeAgent Events interface
392
+ */
393
+ export interface ProbeAgentEvents {
394
+ on(event: 'toolCall', listener: (event: ToolCallEvent) => void): this;
395
+ emit(event: 'toolCall', event: ToolCallEvent): boolean;
396
+ removeListener(event: 'toolCall', listener: (event: ToolCallEvent) => void): this;
397
+ removeAllListeners(event?: 'toolCall'): this;
398
+ }
399
+
400
+ // Default export for ES modules
401
+ export { ProbeAgent as default };
package/package.json ADDED
@@ -0,0 +1,114 @@
1
+ {
2
+ "name": "@probelabs/probe",
3
+ "version": "0.6.0-rc100",
4
+ "description": "Node.js wrapper for the probe code search tool",
5
+ "main": "src/index.js",
6
+ "module": "src/index.js",
7
+ "types": "index.d.ts",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./index.d.ts",
12
+ "import": "./src/index.js",
13
+ "require": "./cjs/index.cjs"
14
+ },
15
+ "./agent": {
16
+ "types": "./src/agent/ProbeAgent.d.ts",
17
+ "import": "./src/agent/ProbeAgent.js",
18
+ "require": "./cjs/agent/ProbeAgent.cjs"
19
+ },
20
+ "./telemetry": {
21
+ "import": "./src/agent/simpleTelemetry.js",
22
+ "require": "./cjs/agent/simpleTelemetry.cjs"
23
+ },
24
+ "./agent/mcp": {
25
+ "import": "./src/agent/mcp/index.js"
26
+ }
27
+ },
28
+ "bin": {
29
+ "probe": "bin/probe"
30
+ },
31
+ "files": [
32
+ "src/**/*",
33
+ "cjs/**/*",
34
+ "*.d.ts",
35
+ "src/**/*.d.ts",
36
+ "bin/probe",
37
+ "bin/probe-binary",
38
+ "bin/probe.exe",
39
+ "bin/.gitkeep",
40
+ "scripts/postinstall.js",
41
+ "build/**/*",
42
+ "MERMAID_SUPPORT_SUMMARY.md",
43
+ "GITHUB_MERMAID_COMPATIBILITY.md"
44
+ ],
45
+ "scripts": {
46
+ "postinstall": "node scripts/postinstall.js",
47
+ "build:mcp": "node scripts/build-mcp.cjs",
48
+ "build:agent": "node scripts/build-agent.cjs",
49
+ "build:types": "echo 'TypeScript definitions already manually created'",
50
+ "build:cjs": "node scripts/build-cjs.js",
51
+ "build": "npm run build:types && npm run build:cjs && npm run build:mcp && npm run build:agent",
52
+ "prepack": "npm run build",
53
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
54
+ "test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch",
55
+ "test:coverage": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
56
+ "test:verbose": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --verbose"
57
+ },
58
+ "keywords": [
59
+ "probe",
60
+ "code-search",
61
+ "search",
62
+ "ast",
63
+ "code-analysis",
64
+ "ai",
65
+ "llm",
66
+ "tools"
67
+ ],
68
+ "author": "probelabs",
69
+ "license": "ISC",
70
+ "dependencies": {
71
+ "@ai-sdk/anthropic": "^2.0.8",
72
+ "@ai-sdk/google": "^2.0.14",
73
+ "@ai-sdk/openai": "^2.0.10",
74
+ "@modelcontextprotocol/sdk": "^1.0.0",
75
+ "@opentelemetry/api": "^1.9.0",
76
+ "@opentelemetry/core": "^1.30.1",
77
+ "@opentelemetry/exporter-trace-otlp-http": "^0.203.0",
78
+ "@opentelemetry/resources": "^2.0.1",
79
+ "@opentelemetry/sdk-node": "^0.203.0",
80
+ "@opentelemetry/sdk-trace-base": "^1.30.0",
81
+ "@opentelemetry/semantic-conventions": "^1.36.0",
82
+ "ai": "^5.0.0",
83
+ "axios": "^1.8.3",
84
+ "fs-extra": "^11.1.1",
85
+ "dotenv": "^16.4.7",
86
+ "glob": "^10.3.10",
87
+ "tar": "^6.2.0",
88
+ "tiktoken": "^1.0.20",
89
+ "zod": "^3.24.2"
90
+ },
91
+ "devDependencies": {
92
+ "@jest/globals": "^29.7.0",
93
+ "@types/fs-extra": "^11.0.4",
94
+ "@types/node": "^20.17.19",
95
+ "cross-env": "^7.0.3",
96
+ "esbuild": "^0.25.9",
97
+ "jest": "^29.7.0",
98
+ "typescript": "^5.9.2"
99
+ },
100
+ "peerDependencies": {
101
+ "ai": "^5.0.0"
102
+ },
103
+ "engines": {
104
+ "node": ">=14.16.0"
105
+ },
106
+ "repository": {
107
+ "type": "git",
108
+ "url": "git+https://github.com/probelabs/probe.git"
109
+ },
110
+ "bugs": {
111
+ "url": "https://github.com/probelabs/probe/issues"
112
+ },
113
+ "homepage": "https://github.com/probelabs/probe#readme"
114
+ }
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-install script for the probe package
5
+ *
6
+ * This script is executed after the package is installed.
7
+ * It downloads the probe binary and replaces the placeholder binary with the actual one.
8
+ */
9
+
10
+ import fs from 'fs-extra';
11
+ import path from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { downloadProbeBinary } from '../src/downloader.js';
14
+
15
+ // Get the directory of the current module
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+
19
+ // Path to the bin directory (relative to this script)
20
+ const binDir = path.resolve(__dirname, '..', 'bin');
21
+
22
+ /**
23
+ * Main function
24
+ */
25
+ async function main() {
26
+ try {
27
+ // Skip postinstall if binary already exists (for CI or development)
28
+ const isWindows = process.platform === 'win32';
29
+ const targetBinaryName = isWindows ? 'probe.exe' : 'probe-binary';
30
+ const targetBinaryPath = path.join(binDir, targetBinaryName);
31
+
32
+ if (await fs.pathExists(targetBinaryPath)) {
33
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
34
+ console.log(`Probe binary already exists at ${targetBinaryPath}, skipping download`);
35
+ }
36
+ return;
37
+ }
38
+
39
+ // Create the bin directory if it doesn't exist
40
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
41
+ console.log(`Creating bin directory at: ${binDir}`);
42
+ }
43
+ await fs.ensureDir(binDir);
44
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
45
+ console.log('Bin directory created successfully');
46
+ }
47
+
48
+ // Create a README file in the bin directory
49
+ const readmePath = path.join(binDir, 'README.md');
50
+ const readmeContent = `# Probe Binary Directory
51
+
52
+ This directory is used to store the downloaded probe binary.
53
+
54
+ The binary is automatically downloaded during package installation.
55
+ If you encounter any issues with the download, you can manually place the probe binary in this directory.
56
+
57
+ Binary name should be:
58
+ - \`probe\` (on Linux/macOS)
59
+ - \`probe.exe\` (on Windows)
60
+
61
+ You can download the binary from: https://github.com/probelabs/probe/releases
62
+ `;
63
+
64
+ await fs.writeFile(readmePath, readmeContent);
65
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
66
+ console.log('Created README file in bin directory');
67
+ }
68
+
69
+ // Create a .gitignore file to ignore binaries but keep the directory
70
+ const gitignorePath = path.join(binDir, '.gitignore');
71
+ const gitignoreContent = `# Ignore all files in this directory
72
+ *
73
+ # Except these files
74
+ !.gitignore
75
+ !.gitkeep
76
+ !README.md
77
+ !probe
78
+ `;
79
+
80
+ await fs.writeFile(gitignorePath, gitignoreContent);
81
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
82
+ console.log('Created .gitignore file in bin directory');
83
+ }
84
+
85
+ // Download the probe binary
86
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
87
+ console.log('Downloading probe binary...');
88
+ }
89
+ try {
90
+ // Try to get the package version
91
+ let packageVersion = '0.0.0';
92
+ const possiblePaths = [
93
+ path.resolve(__dirname, '..', 'package.json'), // When installed from npm: scripts/../package.json
94
+ path.resolve(__dirname, '..', '..', 'package.json') // In development: scripts/../../package.json
95
+ ];
96
+
97
+ for (const packageJsonPath of possiblePaths) {
98
+ try {
99
+ if (fs.existsSync(packageJsonPath)) {
100
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
101
+ console.log(`Found package.json at: ${packageJsonPath}`);
102
+ }
103
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
104
+ if (packageJson.version) {
105
+ packageVersion = packageJson.version;
106
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
107
+ console.log(`Using version from package.json: ${packageVersion}`);
108
+ }
109
+ break;
110
+ }
111
+ }
112
+ } catch (err) {
113
+ console.error(`Error reading package.json at ${packageJsonPath}:`, err);
114
+ }
115
+ }
116
+
117
+ // Download the binary (it will be placed at the correct location automatically)
118
+ const binaryPath = await downloadProbeBinary(packageVersion);
119
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
120
+ console.log(`Successfully downloaded probe binary to: ${binaryPath}`);
121
+ }
122
+
123
+ // Get the path to the target binary (preserve the Node.js wrapper script)
124
+ // (variables already declared at the beginning of main function)
125
+
126
+ // Copy the downloaded binary to the correct location
127
+ if (binaryPath !== targetBinaryPath) {
128
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
129
+ console.log(`Copying binary to ${targetBinaryPath} from ${binaryPath}`);
130
+ }
131
+ await fs.copyFile(binaryPath, targetBinaryPath);
132
+ await fs.chmod(targetBinaryPath, 0o755); // Make it executable
133
+ }
134
+
135
+ // On macOS, try to remove quarantine attributes that might prevent execution
136
+ if (process.platform === 'darwin') {
137
+ try {
138
+ await exec(`xattr -d com.apple.quarantine "${targetBinaryPath}" 2>/dev/null || true`);
139
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
140
+ console.log('Removed quarantine attributes from binary');
141
+ }
142
+ } catch (error) {
143
+ // Ignore errors - this is just a precaution
144
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
145
+ console.log('Note: Could not remove quarantine attributes (this is usually fine)');
146
+ }
147
+ }
148
+ }
149
+
150
+ if (process.env.DEBUG === '1' || process.env.VERBOSE === '1') {
151
+ console.log('\nProbe binary was successfully downloaded and installed during installation.');
152
+ console.log('You can now use the probe command directly from the command line.');
153
+ }
154
+ } catch (error) {
155
+ console.error('Error downloading probe binary:', error);
156
+ console.error('\nNote: The probe binary will need to be downloaded when you first use the package.');
157
+ console.error('If you encounter any issues, you can manually place the binary in the bin directory.');
158
+ console.error('You can download it from: https://github.com/probelabs/probe/releases');
159
+
160
+ // Don't fail the installation, just warn the user
161
+ return;
162
+ }
163
+ } catch (error) {
164
+ console.error(`Error in postinstall script: ${error.message}`);
165
+ console.error('You may need to manually create the bin directory or run with elevated privileges.');
166
+ }
167
+ }
168
+
169
+ // Execute the main function
170
+ main().catch(error => {
171
+ console.error('Unexpected error during postinstall:', error);
172
+ });