claude-simple 0.2.23 → 0.2.24
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/index.html
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
|
6
6
|
<title>Claude Code</title>
|
|
7
|
-
<link rel="stylesheet" href="/style.0.2.
|
|
7
|
+
<link rel="stylesheet" href="/style.0.2.24.min.css">
|
|
8
8
|
<link rel="stylesheet" href="/highlight.min.css">
|
|
9
9
|
<script src="/marked.min.js"></script>
|
|
10
10
|
<script src="/highlight.min.js"></script>
|
|
11
11
|
</head>
|
|
12
12
|
<body class="h-dvh overflow-hidden flex flex-col bg-base-100 text-base-content">
|
|
13
13
|
<div id="root" class="flex flex-col flex-1 overflow-hidden"></div>
|
|
14
|
-
<script type="module" src="/app.0.2.
|
|
14
|
+
<script type="module" src="/app.0.2.24.min.js"></script>
|
|
15
15
|
</body>
|
|
16
16
|
</html>
|
package/package.json
CHANGED
package/src/agents/grok.js
CHANGED
|
@@ -14,6 +14,36 @@ function profileKey(options) {
|
|
|
14
14
|
return `${options.model || ''}\u001f${options.effort || ''}`;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
// JSON-RPC 2.0 error.code must be an integer. Node fs/spawn errors use string
|
|
18
|
+
// codes like "ENOENT"; Grok's Rust client rejects those and logs
|
|
19
|
+
// `invalid type: string "ENOENT", expected i32`.
|
|
20
|
+
export function jsonRpcErrorCode(error) {
|
|
21
|
+
const code = error?.code;
|
|
22
|
+
if (typeof code === 'number' && Number.isInteger(code)) return code;
|
|
23
|
+
return -32000;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** ACP paths must be absolute; resolve relatives against the session cwd, not the edge process cwd. */
|
|
27
|
+
export function resolveFsPath(filePath, cwd) {
|
|
28
|
+
const raw = String(filePath || '').trim();
|
|
29
|
+
if (!raw) {
|
|
30
|
+
const err = new Error('path is required');
|
|
31
|
+
err.code = -32602;
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
return path.resolve(cwd || process.cwd(), raw);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function selectPermissionOption(options) {
|
|
38
|
+
const list = Array.isArray(options) ? options : [];
|
|
39
|
+
const allow = list.find(o => o?.kind === 'allow_always')
|
|
40
|
+
|| list.find(o => o?.kind === 'allow_once')
|
|
41
|
+
|| list.find(o => typeof o?.kind === 'string' && String(o.kind).startsWith('allow'))
|
|
42
|
+
|| list[0];
|
|
43
|
+
if (!allow?.optionId) return { outcome: 'cancelled' };
|
|
44
|
+
return { outcome: 'selected', optionId: allow.optionId };
|
|
45
|
+
}
|
|
46
|
+
|
|
17
47
|
function envFromParams(envList) {
|
|
18
48
|
const env = { ...process.env };
|
|
19
49
|
if (!Array.isArray(envList)) return env;
|
|
@@ -164,6 +194,7 @@ class GrokACPClient {
|
|
|
164
194
|
this.child = spawn(cliPath || 'grok', args, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
165
195
|
this.pending = new Map();
|
|
166
196
|
this.listeners = new Map();
|
|
197
|
+
this.sessionCwd = new Map();
|
|
167
198
|
// High ids avoid colliding with agent-originated request ids (often 0..N).
|
|
168
199
|
this.nextID = 100000;
|
|
169
200
|
this.terminals = new TerminalHost();
|
|
@@ -198,13 +229,19 @@ class GrokACPClient {
|
|
|
198
229
|
return init;
|
|
199
230
|
}
|
|
200
231
|
|
|
232
|
+
fsCwd(params) {
|
|
233
|
+
return (params?.sessionId && this.sessionCwd.get(params.sessionId)) || process.cwd();
|
|
234
|
+
}
|
|
235
|
+
|
|
201
236
|
async handleClientRequest(msg) {
|
|
202
237
|
const method = msg.method;
|
|
203
238
|
const params = msg.params || {};
|
|
204
239
|
try {
|
|
205
240
|
let result = {};
|
|
206
|
-
if (method === '
|
|
207
|
-
|
|
241
|
+
if (method === 'session/request_permission') {
|
|
242
|
+
result = { outcome: selectPermissionOption(params.options) };
|
|
243
|
+
} else if (method === 'fs/read_text_file') {
|
|
244
|
+
const filePath = resolveFsPath(params.path, this.fsCwd(params));
|
|
208
245
|
const content = await fs.promises.readFile(filePath, 'utf8');
|
|
209
246
|
const limit = Number.isFinite(params.limit) ? params.limit : null;
|
|
210
247
|
const line = Number.isFinite(params.line) ? params.line : null;
|
|
@@ -217,11 +254,13 @@ class GrokACPClient {
|
|
|
217
254
|
result = { content };
|
|
218
255
|
}
|
|
219
256
|
} else if (method === 'fs/write_text_file') {
|
|
220
|
-
const filePath =
|
|
257
|
+
const filePath = resolveFsPath(params.path, this.fsCwd(params));
|
|
258
|
+
const content = params.content == null ? '' : String(params.content);
|
|
221
259
|
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
|
|
222
|
-
await fs.promises.writeFile(filePath,
|
|
260
|
+
await fs.promises.writeFile(filePath, content, 'utf8');
|
|
223
261
|
result = {};
|
|
224
262
|
} else if (method === 'terminal/create') {
|
|
263
|
+
if (!params.cwd) params = { ...params, cwd: this.fsCwd(params) };
|
|
225
264
|
result = this.terminals.create(params);
|
|
226
265
|
} else if (method === 'terminal/output') {
|
|
227
266
|
result = this.terminals.output(params.terminalId);
|
|
@@ -244,7 +283,10 @@ class GrokACPClient {
|
|
|
244
283
|
this.write({
|
|
245
284
|
jsonrpc: '2.0',
|
|
246
285
|
id: msg.id,
|
|
247
|
-
error: {
|
|
286
|
+
error: {
|
|
287
|
+
code: jsonRpcErrorCode(error),
|
|
288
|
+
message: error.message || 'Client request failed',
|
|
289
|
+
},
|
|
248
290
|
});
|
|
249
291
|
}
|
|
250
292
|
}
|
|
@@ -291,20 +333,23 @@ class GrokACPClient {
|
|
|
291
333
|
|
|
292
334
|
async ensureSession(options) {
|
|
293
335
|
await this.ready;
|
|
336
|
+
const cwd = options.cwd || process.cwd();
|
|
294
337
|
if (options.sessionId) {
|
|
295
338
|
try {
|
|
296
|
-
await this.request('session/load', { sessionId: options.sessionId, cwd
|
|
339
|
+
await this.request('session/load', { sessionId: options.sessionId, cwd, mcpServers: [] });
|
|
297
340
|
} catch {
|
|
298
|
-
await this.request('session/resume', { sessionId: options.sessionId, cwd
|
|
341
|
+
await this.request('session/resume', { sessionId: options.sessionId, cwd, mcpServers: [] });
|
|
299
342
|
}
|
|
343
|
+
this.sessionCwd.set(options.sessionId, cwd);
|
|
300
344
|
return options.sessionId;
|
|
301
345
|
}
|
|
302
346
|
const result = await this.request('session/new', {
|
|
303
|
-
cwd
|
|
347
|
+
cwd,
|
|
304
348
|
mcpServers: [],
|
|
305
349
|
_meta: { yoloMode: true },
|
|
306
350
|
});
|
|
307
351
|
if (!result.sessionId) throw new Error('Grok ACP did not return a session id');
|
|
352
|
+
this.sessionCwd.set(result.sessionId, cwd);
|
|
308
353
|
return result.sessionId;
|
|
309
354
|
}
|
|
310
355
|
}
|
package/src/agents/sessions.js
CHANGED
|
@@ -910,12 +910,16 @@ function geminiJournalPath(sessionId, geminiHome) {
|
|
|
910
910
|
return path.join(geminiUiSessionsRoot(geminiHome), `${sessionId}.jsonl`);
|
|
911
911
|
}
|
|
912
912
|
|
|
913
|
-
// agy keeps
|
|
914
|
-
//
|
|
915
|
-
//
|
|
916
|
-
function
|
|
913
|
+
// agy keeps both a compact transport log and a lossless transcript. The
|
|
914
|
+
// compact log replaces large fields with `<truncated N bytes>`; always prefer
|
|
915
|
+
// the full file when it is available so chat history never loses message text.
|
|
916
|
+
function geminiNativeTranscriptPaths(sessionId, geminiHome) {
|
|
917
917
|
const home = geminiHome || path.join(os.homedir(), '.gemini');
|
|
918
|
-
|
|
918
|
+
const logs = path.join(home, 'antigravity-cli', 'brain', sessionId, '.system_generated', 'logs');
|
|
919
|
+
return [
|
|
920
|
+
path.join(logs, 'transcript_full.jsonl'),
|
|
921
|
+
path.join(logs, 'transcript.jsonl'),
|
|
922
|
+
];
|
|
919
923
|
}
|
|
920
924
|
|
|
921
925
|
function geminiPathFromUri(uri) {
|
|
@@ -1039,8 +1043,10 @@ async function findGeminiJournal(sessionId, geminiHome) {
|
|
|
1039
1043
|
}
|
|
1040
1044
|
|
|
1041
1045
|
async function findGeminiNativeTranscript(sessionId, geminiHome) {
|
|
1042
|
-
const file
|
|
1043
|
-
|
|
1046
|
+
for (const file of geminiNativeTranscriptPaths(sessionId, geminiHome)) {
|
|
1047
|
+
try { await fs.access(file); return file; } catch { /* try the compact fallback */ }
|
|
1048
|
+
}
|
|
1049
|
+
return null;
|
|
1044
1050
|
}
|
|
1045
1051
|
|
|
1046
1052
|
function geminiUserText(content) {
|
|
@@ -1571,7 +1577,8 @@ export async function loadSessionJsonl(sessionId, agent, { claudeConfigDirs, cod
|
|
|
1571
1577
|
let file;
|
|
1572
1578
|
if (a === 'codex') file = await findCodexSessionFile(sessionId, codexHome);
|
|
1573
1579
|
else if (a === 'cursor') file = await findCursorJournal(sessionId, cursorHome);
|
|
1574
|
-
else if (a === 'gemini') file = await
|
|
1580
|
+
else if (a === 'gemini') file = await findGeminiNativeTranscript(sessionId, geminiHome)
|
|
1581
|
+
|| await findGeminiJournal(sessionId, geminiHome);
|
|
1575
1582
|
else if (a === 'grok') {
|
|
1576
1583
|
const dir = await findGrokSessionDir(sessionId, grokHome);
|
|
1577
1584
|
file = dir ? path.join(dir, 'chat_history.jsonl') : null;
|
|
File without changes
|
|
File without changes
|