arcroom 0.0.5-beta → 0.0.6-beta
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/mcp.js +24 -7
- package/dist/session.js +9 -5
- package/package.json +1 -1
package/dist/mcp.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Hand-rolled instead of the SDK so it runs from the copied runtime with no node_modules.
|
|
3
3
|
import { git, projectOf } from './git.js';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
5
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
6
6
|
import { hostname } from 'node:os';
|
|
7
|
-
import { relative, resolve } from 'node:path';
|
|
7
|
+
import { join, relative, resolve } from 'node:path';
|
|
8
8
|
import { createInterface } from 'node:readline';
|
|
9
9
|
import { api, isOff, keyRefused, loadConfig } from './home.js';
|
|
10
10
|
import { hooksHere, setUpHere } from './scope.js';
|
|
@@ -229,11 +229,27 @@ const PATHS = {
|
|
|
229
229
|
code_note: '/v1/code/note',
|
|
230
230
|
};
|
|
231
231
|
const sha256 = (file) => createHash('sha256').update(lf(readFileSync(file))).digest('hex');
|
|
232
|
-
|
|
232
|
+
// ponytail: a file added to the folder later is not noticed, only changed or removed ones; hash the listing if that matters
|
|
233
|
+
/** The files in a folder an answer depends on (agents name "feedback/" as often as a file), at most 200, no .git or node_modules. */
|
|
234
|
+
function filesIn(dir, out = []) {
|
|
235
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
236
|
+
if (out.length >= 200)
|
|
237
|
+
break;
|
|
238
|
+
if (e.name === '.git' || e.name === 'node_modules')
|
|
239
|
+
continue;
|
|
240
|
+
if (e.isDirectory())
|
|
241
|
+
filesIn(join(dir, e.name), out);
|
|
242
|
+
else if (e.isFile())
|
|
243
|
+
out.push(join(dir, e.name));
|
|
244
|
+
}
|
|
245
|
+
return out;
|
|
246
|
+
}
|
|
247
|
+
/** {"file:<path>": sha256} for files the answer depends on (a folder: each file in it); a missing file is recorded as "missing". */
|
|
233
248
|
export function fileDeps(paths, cwd) {
|
|
234
|
-
return Object.fromEntries(paths.
|
|
235
|
-
const
|
|
236
|
-
|
|
249
|
+
return Object.fromEntries(paths.flatMap((p) => {
|
|
250
|
+
const full = resolve(cwd, p);
|
|
251
|
+
const files = existsSync(full) && statSync(full).isDirectory() ? filesIn(full) : [full];
|
|
252
|
+
return files.map((f) => [`file:${relative(cwd, f).replaceAll('\\', '/')}`, existsSync(f) ? sha256(f) : 'missing']);
|
|
237
253
|
}));
|
|
238
254
|
}
|
|
239
255
|
/** Paths among depends_on whose current content differs from when the answer was stored. */
|
|
@@ -374,7 +390,8 @@ export async function mcp() {
|
|
|
374
390
|
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: msg.id, result }) + '\n');
|
|
375
391
|
}
|
|
376
392
|
catch (err) {
|
|
377
|
-
|
|
393
|
+
// JSON-RPC codes are numbers: a Node error's "EISDIR" makes Claude Code drop the reply and wait for ever
|
|
394
|
+
const error = { code: Number.isInteger(err?.code) ? err.code : -32603, message: err?.message ?? String(err) };
|
|
378
395
|
process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: msg.id, error }) + '\n');
|
|
379
396
|
}
|
|
380
397
|
}
|
package/dist/session.js
CHANGED
|
@@ -29,13 +29,17 @@ export function lastRunContext(run, now = new Date(), root) {
|
|
|
29
29
|
: `ended ${run.status === 'partial' ? 'PARTIAL: its done-checks were still failing' : run.status}`;
|
|
30
30
|
const lines = [
|
|
31
31
|
`ArcRoom: ${whose} in this project (${ago(run.started_at, now)}, on ${run.machine ?? 'another machine'}${run.branch ? `, branch ${run.branch}` : ''}) ${ended}.`,
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
// the whole ask as captured (at most 1,000 characters): a cut ask loses its last steps, the ones left to do
|
|
33
|
+
`Asked: "${first.slice(0, 1000)}"`,
|
|
34
|
+
last && last !== first ? `Last asked: "${last.slice(0, 1000)}"` : '',
|
|
34
35
|
run.failing_check ? `Still failing: \`${String(run.failing_check).slice(0, 200)}\`` : '',
|
|
35
36
|
edited.length ? `Edited: ${edited.slice(0, 10).join(', ')}${edited.length > 10 ? ` (+${edited.length - 10} more)` : ''}` : '',
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
// a run that never closed has no report: no count rather than a wrong "0 tool calls"
|
|
38
|
+
r.tool_calls == null
|
|
39
|
+
? ''
|
|
40
|
+
: `${r.tool_calls} tool calls` +
|
|
41
|
+
(r.blocked ? `, ${r.blocked} blocked by the loop guard` : '') +
|
|
42
|
+
(memory.find ? `, memory: ${memory.find} lookups, ${memory.complete ?? 0} stored` : ''),
|
|
39
43
|
'Use this to pick up where it left off if the user continues that work; ignore it otherwise.',
|
|
40
44
|
];
|
|
41
45
|
return lines.filter(Boolean).join('\n');
|
package/package.json
CHANGED