@lmnr-ai/claude-code-proxy 0.1.1-alpha.1
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/README.md +5 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +141 -0
- package/dist/lmnr-claude-code-proxy.node +0 -0
- package/package.json +44 -0
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Laminar Claude Code Proxy - TypeScript/JavaScript bindings for HTTP proxy server
|
|
3
|
+
*/
|
|
4
|
+
export interface SpanContext {
|
|
5
|
+
traceId: string;
|
|
6
|
+
spanId: string;
|
|
7
|
+
projectApiKey: string;
|
|
8
|
+
spanIdsPath?: string[];
|
|
9
|
+
spanPath?: string[];
|
|
10
|
+
laminarUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Set the current trace context by sending an HTTP request to the running proxy server.
|
|
14
|
+
*
|
|
15
|
+
* @param context - The span context containing trace information
|
|
16
|
+
* @throws Error if the HTTP request fails
|
|
17
|
+
*/
|
|
18
|
+
export declare function setCurrentTrace(context: SpanContext): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Run the proxy server in a background thread with health monitoring.
|
|
21
|
+
*
|
|
22
|
+
* A background monitor will check the server health every HEALTH_CHECK_INTERVAL ms
|
|
23
|
+
* and automatically restart it if it dies.
|
|
24
|
+
*
|
|
25
|
+
* @param url - The target URL to proxy requests to
|
|
26
|
+
* @param port - The port to listen on (default: 45667)
|
|
27
|
+
*/
|
|
28
|
+
export declare function runServer(url: string, port?: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* Stop the proxy server and its health monitoring.
|
|
31
|
+
*/
|
|
32
|
+
export declare function stopServer(): void;
|
|
33
|
+
export declare const run: any, stop: any;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Laminar Claude Code Proxy - TypeScript/JavaScript bindings for HTTP proxy server
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.stop = exports.run = void 0;
|
|
7
|
+
exports.setCurrentTrace = setCurrentTrace;
|
|
8
|
+
exports.runServer = runServer;
|
|
9
|
+
exports.stopServer = stopServer;
|
|
10
|
+
// Import native functions from the NAPI module
|
|
11
|
+
// When built, this will be in dist/index.js and the native module will be in dist/
|
|
12
|
+
// NAPI-RS generates the binding files in the same directory
|
|
13
|
+
const native = require('./lmnr-claude-code-proxy');
|
|
14
|
+
const HEALTH_CHECK_INTERVAL = 1000;
|
|
15
|
+
// Module-level variables to track the server state
|
|
16
|
+
let serverPort = 45667;
|
|
17
|
+
let targetUrl = '';
|
|
18
|
+
let monitorInterval = null;
|
|
19
|
+
/**
|
|
20
|
+
* Set the current trace context by sending an HTTP request to the running proxy server.
|
|
21
|
+
*
|
|
22
|
+
* @param context - The span context containing trace information
|
|
23
|
+
* @throws Error if the HTTP request fails
|
|
24
|
+
*/
|
|
25
|
+
async function setCurrentTrace(context) {
|
|
26
|
+
const { traceId, spanId, projectApiKey, spanIdsPath = [], spanPath = [], laminarUrl = 'https://api.lmnr.ai', } = context;
|
|
27
|
+
// Prepare the JSON payload
|
|
28
|
+
const payload = {
|
|
29
|
+
trace_id: traceId,
|
|
30
|
+
span_id: spanId,
|
|
31
|
+
project_api_key: projectApiKey,
|
|
32
|
+
span_ids_path: spanIdsPath,
|
|
33
|
+
span_path: spanPath,
|
|
34
|
+
laminar_url: laminarUrl,
|
|
35
|
+
};
|
|
36
|
+
// Send POST request to the internal endpoint
|
|
37
|
+
const url = `http://127.0.0.1:${serverPort}/lmnr-internal/span-context`;
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetch(url, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(payload),
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error(`HTTP ${response.status}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new Error(`Failed to set trace context: ${error}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Background function that monitors server health and restarts if needed.
|
|
56
|
+
* Polls every HEALTH_CHECK_INTERVAL ms.
|
|
57
|
+
*/
|
|
58
|
+
async function healthCheckMonitor() {
|
|
59
|
+
const url = `http://127.0.0.1:${serverPort}/lmnr-internal/health`;
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
// Force new connection for each health check to avoid interfering with streaming
|
|
63
|
+
headers: {
|
|
64
|
+
'Connection': 'close'
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
if (response.status === 200) {
|
|
68
|
+
// Server is healthy
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
// Server is not responding, try to restart
|
|
74
|
+
console.warn(`Server health check failed: ${error}. Attempting to restart...`);
|
|
75
|
+
try {
|
|
76
|
+
// Try to stop the existing server (it might be stuck)
|
|
77
|
+
try {
|
|
78
|
+
native.stop();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Server might already be dead
|
|
82
|
+
}
|
|
83
|
+
// Wait a bit before restarting
|
|
84
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
85
|
+
// Restart the server
|
|
86
|
+
native.run(targetUrl, serverPort);
|
|
87
|
+
console.info('Server restarted successfully');
|
|
88
|
+
}
|
|
89
|
+
catch (restartError) {
|
|
90
|
+
console.error(`Failed to restart server: ${restartError}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Run the proxy server in a background thread with health monitoring.
|
|
96
|
+
*
|
|
97
|
+
* A background monitor will check the server health every HEALTH_CHECK_INTERVAL ms
|
|
98
|
+
* and automatically restart it if it dies.
|
|
99
|
+
*
|
|
100
|
+
* @param url - The target URL to proxy requests to
|
|
101
|
+
* @param port - The port to listen on (default: 45667)
|
|
102
|
+
*/
|
|
103
|
+
function runServer(url, port = 45667) {
|
|
104
|
+
// Stop any existing monitoring
|
|
105
|
+
if (monitorInterval !== null) {
|
|
106
|
+
clearInterval(monitorInterval);
|
|
107
|
+
monitorInterval = null;
|
|
108
|
+
}
|
|
109
|
+
// Store server configuration
|
|
110
|
+
serverPort = port;
|
|
111
|
+
targetUrl = url;
|
|
112
|
+
// Start the server
|
|
113
|
+
try {
|
|
114
|
+
native.run(url, port);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error(`Error running the proxy server: ${error}`);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
// Start the health check monitor
|
|
121
|
+
monitorInterval = setInterval(() => {
|
|
122
|
+
healthCheckMonitor().catch(() => { });
|
|
123
|
+
}, HEALTH_CHECK_INTERVAL);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Stop the proxy server and its health monitoring.
|
|
127
|
+
*/
|
|
128
|
+
function stopServer() {
|
|
129
|
+
// Stop the monitor
|
|
130
|
+
if (monitorInterval !== null) {
|
|
131
|
+
clearInterval(monitorInterval);
|
|
132
|
+
monitorInterval = null;
|
|
133
|
+
}
|
|
134
|
+
// Stop the server
|
|
135
|
+
try {
|
|
136
|
+
native.stop();
|
|
137
|
+
}
|
|
138
|
+
catch { }
|
|
139
|
+
}
|
|
140
|
+
// Re-export native functions for direct access if needed
|
|
141
|
+
exports.run = native.run, exports.stop = native.stop;
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lmnr-ai/claude-code-proxy",
|
|
3
|
+
"version": "0.1.1-alpha.1",
|
|
4
|
+
"description": "HTTP proxy for Claude Desktop API requests with Laminar observability",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"napi": {
|
|
8
|
+
"binaryName": "lmnr-claude-code-proxy",
|
|
9
|
+
"package": {
|
|
10
|
+
"name": "@lmnr-ai/claude-code-proxy"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"claude",
|
|
18
|
+
"proxy",
|
|
19
|
+
"anthropic",
|
|
20
|
+
"laminar",
|
|
21
|
+
"observability",
|
|
22
|
+
"napi"
|
|
23
|
+
],
|
|
24
|
+
"author": "Laminar AI",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@napi-rs/cli": "^3.0.0",
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"ts-node": "^10.9.0",
|
|
30
|
+
"typescript": "^5.6.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"artifacts": "napi artifacts",
|
|
38
|
+
"build:cargo": "cd ../bin && cargo build --release --features typescript",
|
|
39
|
+
"build:napi": "cd ../bin && napi build --platform --release -o ../ts/dist",
|
|
40
|
+
"build:ts": "tsc",
|
|
41
|
+
"build": "node scripts/build.js",
|
|
42
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
43
|
+
}
|
|
44
|
+
}
|