claude-remote-agent 0.1.2 → 0.2.0
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/agent.js +53 -3
- package/package.json +1 -1
package/agent.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const crypto = require('crypto');
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const WebSocket = require('ws');
|
|
4
|
-
const { spawn } = require('child_process');
|
|
4
|
+
const { spawn, execSync } = require('child_process');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const readline = require('readline');
|
|
7
7
|
const path = require('path');
|
|
@@ -213,6 +213,9 @@ async function handleRequest(msg) {
|
|
|
213
213
|
let data;
|
|
214
214
|
if (action === 'list-conversations') data = await listConversations();
|
|
215
215
|
else if (action === 'get-conversation') data = await getConversation(params.file);
|
|
216
|
+
else if (action === 'delete-conversation') data = deleteConversation(params.file);
|
|
217
|
+
else if (action === 'get-settings') data = getSettings();
|
|
218
|
+
else if (action === 'set-model') data = setModel(params.model);
|
|
216
219
|
else { sendResponse(reqId, null, 'Unknown action'); return; }
|
|
217
220
|
sendResponse(reqId, data);
|
|
218
221
|
} catch (err) {
|
|
@@ -352,6 +355,44 @@ async function getConversation(file) {
|
|
|
352
355
|
return { title: aiTitle, messages };
|
|
353
356
|
}
|
|
354
357
|
|
|
358
|
+
function deleteConversation(file) {
|
|
359
|
+
const filePath = path.join(CLAUDE_PROJECTS, file);
|
|
360
|
+
if (!filePath.startsWith(CLAUDE_PROJECTS)) throw new Error('Invalid path');
|
|
361
|
+
if (!fs.existsSync(filePath)) throw new Error('Not found');
|
|
362
|
+
fs.unlinkSync(filePath);
|
|
363
|
+
return { ok: true };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ── Settings ──
|
|
367
|
+
|
|
368
|
+
const CLAUDE_SETTINGS = path.join(process.env.HOME, '.claude', 'settings.json');
|
|
369
|
+
const AVAILABLE_MODELS = [
|
|
370
|
+
{ id: 'sonnet', name: 'Claude Sonnet', description: 'Fast and capable' },
|
|
371
|
+
{ id: 'opus', name: 'Claude Opus', description: 'Most intelligent' },
|
|
372
|
+
{ id: 'haiku', name: 'Claude Haiku', description: 'Fastest, lightweight' },
|
|
373
|
+
];
|
|
374
|
+
|
|
375
|
+
function getSettings() {
|
|
376
|
+
let settings = {};
|
|
377
|
+
try { settings = JSON.parse(fs.readFileSync(CLAUDE_SETTINGS, 'utf-8')); } catch {}
|
|
378
|
+
let version = '';
|
|
379
|
+
try { version = execSync('claude --version', { encoding: 'utf-8', timeout: 5000 }).trim(); } catch {}
|
|
380
|
+
return {
|
|
381
|
+
model: settings.model || 'sonnet',
|
|
382
|
+
version,
|
|
383
|
+
availableModels: AVAILABLE_MODELS,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function setModel(model) {
|
|
388
|
+
if (!AVAILABLE_MODELS.some(m => m.id === model)) throw new Error('Invalid model');
|
|
389
|
+
let settings = {};
|
|
390
|
+
try { settings = JSON.parse(fs.readFileSync(CLAUDE_SETTINGS, 'utf-8')); } catch {}
|
|
391
|
+
settings.model = model;
|
|
392
|
+
fs.writeFileSync(CLAUDE_SETTINGS, JSON.stringify(settings, null, 2) + '\n');
|
|
393
|
+
return { ok: true, model };
|
|
394
|
+
}
|
|
395
|
+
|
|
355
396
|
// ── Chat sessions (structured JSON mode) ──
|
|
356
397
|
|
|
357
398
|
const chatSessions = new Map();
|
|
@@ -407,6 +448,8 @@ function handleChatMessage(sessionId, text, images) {
|
|
|
407
448
|
});
|
|
408
449
|
|
|
409
450
|
let buffer = '';
|
|
451
|
+
let lastTextLen = 0;
|
|
452
|
+
let sentToolIds = new Set();
|
|
410
453
|
|
|
411
454
|
proc.stdout.on('data', (chunk) => {
|
|
412
455
|
buffer += chunk.toString();
|
|
@@ -421,13 +464,20 @@ function handleChatMessage(sessionId, text, images) {
|
|
|
421
464
|
session.claudeSessionId = obj.session_id;
|
|
422
465
|
console.log(`[${ts()}] Chat ${sessionId.slice(0, 8)} got claude session: ${obj.session_id.slice(0, 8)}`);
|
|
423
466
|
}
|
|
467
|
+
let fullText = '';
|
|
424
468
|
for (const block of obj.message.content) {
|
|
425
469
|
if (block.type === 'text') {
|
|
426
|
-
|
|
427
|
-
} else if (block.type === 'tool_use') {
|
|
470
|
+
fullText += block.text;
|
|
471
|
+
} else if (block.type === 'tool_use' && !sentToolIds.has(block.id)) {
|
|
472
|
+
sentToolIds.add(block.id);
|
|
428
473
|
send({ type: 'chat-tool', sessionId, tool: block.name, input: block.input });
|
|
429
474
|
}
|
|
430
475
|
}
|
|
476
|
+
if (fullText.length > lastTextLen) {
|
|
477
|
+
const delta = fullText.slice(lastTextLen);
|
|
478
|
+
lastTextLen = fullText.length;
|
|
479
|
+
send({ type: 'chat-text', sessionId, text: delta, done: false });
|
|
480
|
+
}
|
|
431
481
|
} else if (obj.type === 'result') {
|
|
432
482
|
if (obj.session_id && !session.claudeSessionId) {
|
|
433
483
|
session.claudeSessionId = obj.session_id;
|