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 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 user's OAuth token, and sends results back.
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 oauthToken;
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, oauthToken: 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 callClaudeAPI;
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 ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';
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 user's OAuth token, and sends results back.
14
+ * the Claude CLI (which uses the user's subscription).
15
15
  */
16
16
  class BlitsBridge {
17
17
  wsUrl;
18
18
  sessionToken;
19
- oauthToken;
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, oauthToken) {
25
+ constructor(wsUrl, sessionToken, _oauthToken) {
26
26
  this.wsUrl = wsUrl;
27
27
  this.sessionToken = sessionToken;
28
- this.oauthToken = oauthToken;
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.callClaudeAPI(req.payload);
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 callClaudeAPI(payload) {
121
- const res = await fetch(ANTHROPIC_API_URL, {
122
- method: 'POST',
123
- headers: {
124
- 'Authorization': `Bearer ${this.oauthToken}`,
125
- 'anthropic-version': '2023-06-01',
126
- 'content-type': 'application/json',
127
- },
128
- body: JSON.stringify(payload),
129
- });
130
- if (!res.ok) {
131
- const errText = await res.text().catch(() => '');
132
- throw new Error(`Claude API ${res.status}: ${errText.slice(0, 200)}`);
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
- return res.json();
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, oauthToken);
68
+ const bridge = new bridge_1.BlitsBridge(wsUrl, token, '');
74
69
  bridge.connect();
75
70
  // Graceful shutdown
76
71
  const shutdown = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blits-bridge",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Bridge between Blits platform and local Claude CLI. Runs Claude API calls through your subscription.",
5
5
  "bin": {
6
6
  "blits-bridge": "./dist/cli.js"