blits-bridge 0.1.2 → 0.1.3
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/dist/bridge.d.ts +4 -4
- package/dist/bridge.js +73 -20
- package/dist/cli.js +1 -6
- package/package.json +1 -1
package/dist/bridge.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BlitsBridge connects to the Blits server via WebSocket,
|
|
3
3
|
* receives Claude API requests, executes them locally using
|
|
4
|
-
* the
|
|
4
|
+
* the Claude CLI (which uses the user's subscription).
|
|
5
5
|
*/
|
|
6
6
|
export declare class BlitsBridge {
|
|
7
7
|
private wsUrl;
|
|
8
8
|
private sessionToken;
|
|
9
|
-
private
|
|
9
|
+
private _oauthToken;
|
|
10
10
|
private ws;
|
|
11
11
|
private reconnecting;
|
|
12
12
|
private shouldReconnect;
|
|
13
13
|
private heartbeatTimer;
|
|
14
14
|
private activeRequests;
|
|
15
|
-
constructor(wsUrl: string, sessionToken: string,
|
|
15
|
+
constructor(wsUrl: string, sessionToken: string, _oauthToken: string);
|
|
16
16
|
connect(): void;
|
|
17
17
|
disconnect(): void;
|
|
18
18
|
private send;
|
|
19
19
|
private handleRequest;
|
|
20
|
-
private
|
|
20
|
+
private callClaudeCLI;
|
|
21
21
|
private scheduleReconnect;
|
|
22
22
|
private startHeartbeat;
|
|
23
23
|
private stopHeartbeat;
|
package/dist/bridge.js
CHANGED
|
@@ -5,27 +5,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.BlitsBridge = void 0;
|
|
7
7
|
const ws_1 = __importDefault(require("ws"));
|
|
8
|
-
const
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
9
|
const RECONNECT_DELAY = 5000;
|
|
10
10
|
const HEARTBEAT_INTERVAL = 30000;
|
|
11
11
|
/**
|
|
12
12
|
* BlitsBridge connects to the Blits server via WebSocket,
|
|
13
13
|
* receives Claude API requests, executes them locally using
|
|
14
|
-
* the
|
|
14
|
+
* the Claude CLI (which uses the user's subscription).
|
|
15
15
|
*/
|
|
16
16
|
class BlitsBridge {
|
|
17
17
|
wsUrl;
|
|
18
18
|
sessionToken;
|
|
19
|
-
|
|
19
|
+
_oauthToken;
|
|
20
20
|
ws = null;
|
|
21
21
|
reconnecting = false;
|
|
22
22
|
shouldReconnect = true;
|
|
23
23
|
heartbeatTimer = null;
|
|
24
24
|
activeRequests = 0;
|
|
25
|
-
constructor(wsUrl, sessionToken,
|
|
25
|
+
constructor(wsUrl, sessionToken, _oauthToken) {
|
|
26
26
|
this.wsUrl = wsUrl;
|
|
27
27
|
this.sessionToken = sessionToken;
|
|
28
|
-
this.
|
|
28
|
+
this._oauthToken = _oauthToken;
|
|
29
29
|
}
|
|
30
30
|
connect() {
|
|
31
31
|
const url = `${this.wsUrl}?token=${encodeURIComponent(this.sessionToken)}`;
|
|
@@ -96,7 +96,7 @@ class BlitsBridge {
|
|
|
96
96
|
const startTime = Date.now();
|
|
97
97
|
console.log(`📨 Задача ${req.id.slice(0, 8)}... (модель: ${req.payload.model})`);
|
|
98
98
|
try {
|
|
99
|
-
const response = await this.
|
|
99
|
+
const response = await this.callClaudeCLI(req.payload);
|
|
100
100
|
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
101
101
|
const result = {
|
|
102
102
|
id: req.id,
|
|
@@ -117,21 +117,74 @@ class BlitsBridge {
|
|
|
117
117
|
}
|
|
118
118
|
this.activeRequests--;
|
|
119
119
|
}
|
|
120
|
-
async
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
120
|
+
async callClaudeCLI(payload) {
|
|
121
|
+
// Build the last user message as prompt for claude CLI
|
|
122
|
+
const lastUserMsg = [...payload.messages].reverse().find(m => m.role === 'user');
|
|
123
|
+
const prompt = typeof lastUserMsg?.content === 'string'
|
|
124
|
+
? lastUserMsg.content
|
|
125
|
+
: JSON.stringify(lastUserMsg?.content ?? '');
|
|
126
|
+
const args = [
|
|
127
|
+
'-p',
|
|
128
|
+
'--output-format', 'json',
|
|
129
|
+
'--model', payload.model,
|
|
130
|
+
'--no-session-persistence',
|
|
131
|
+
];
|
|
132
|
+
if (payload.system) {
|
|
133
|
+
args.push('--system-prompt', payload.system);
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
// Disable all tools for simple completion (agent school tasks)
|
|
136
|
+
args.push('--tools', '');
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
const proc = (0, child_process_1.spawn)('claude', args, {
|
|
139
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
140
|
+
env: { ...process.env },
|
|
141
|
+
});
|
|
142
|
+
let stdout = '';
|
|
143
|
+
let stderr = '';
|
|
144
|
+
proc.stdout.on('data', (chunk) => { stdout += chunk.toString(); });
|
|
145
|
+
proc.stderr.on('data', (chunk) => { stderr += chunk.toString(); });
|
|
146
|
+
proc.stdin.write(prompt);
|
|
147
|
+
proc.stdin.end();
|
|
148
|
+
proc.on('close', (code) => {
|
|
149
|
+
if (code !== 0) {
|
|
150
|
+
reject(new Error(`Claude CLI exited with code ${code}: ${stderr.slice(0, 300)}`));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const parsed = JSON.parse(stdout);
|
|
155
|
+
// Claude CLI --output-format json returns { type, subtype, cost_usd, duration_ms, duration_api_ms, is_error, num_turns, result, session_id, total_cost_usd }
|
|
156
|
+
// Convert to Anthropic API-like response format
|
|
157
|
+
const response = {
|
|
158
|
+
id: `cli-${Date.now()}`,
|
|
159
|
+
type: 'message',
|
|
160
|
+
role: 'assistant',
|
|
161
|
+
content: [{ type: 'text', text: parsed.result ?? stdout }],
|
|
162
|
+
model: payload.model,
|
|
163
|
+
stop_reason: parsed.is_error ? 'error' : 'end_turn',
|
|
164
|
+
usage: {
|
|
165
|
+
input_tokens: 0,
|
|
166
|
+
output_tokens: 0,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
resolve(response);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// If not JSON, treat raw stdout as text response
|
|
173
|
+
resolve({
|
|
174
|
+
id: `cli-${Date.now()}`,
|
|
175
|
+
type: 'message',
|
|
176
|
+
role: 'assistant',
|
|
177
|
+
content: [{ type: 'text', text: stdout }],
|
|
178
|
+
model: payload.model,
|
|
179
|
+
stop_reason: 'end_turn',
|
|
180
|
+
usage: { input_tokens: 0, output_tokens: 0 },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
proc.on('error', (err) => {
|
|
185
|
+
reject(new Error(`Failed to spawn claude CLI: ${err.message}`));
|
|
186
|
+
});
|
|
187
|
+
});
|
|
135
188
|
}
|
|
136
189
|
scheduleReconnect() {
|
|
137
190
|
if (this.reconnecting)
|
package/dist/cli.js
CHANGED
|
@@ -61,16 +61,11 @@ async function main() {
|
|
|
61
61
|
}
|
|
62
62
|
console.log('');
|
|
63
63
|
}
|
|
64
|
-
const oauthToken = await auth.getToken();
|
|
65
|
-
if (!oauthToken) {
|
|
66
|
-
console.error('❌ Не удалось получить OAuth токен. Перезапустите: claude auth login');
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
64
|
console.log('✅ Claude CLI авторизован');
|
|
70
65
|
// Step 2: Connect to Blits
|
|
71
66
|
const wsUrl = server || BLITS_WS_URL;
|
|
72
67
|
console.log(`🌐 Подключаюсь к ${wsUrl}...`);
|
|
73
|
-
const bridge = new bridge_1.BlitsBridge(wsUrl, token,
|
|
68
|
+
const bridge = new bridge_1.BlitsBridge(wsUrl, token, '');
|
|
74
69
|
bridge.connect();
|
|
75
70
|
// Graceful shutdown
|
|
76
71
|
const shutdown = () => {
|