@c0mpute/code 0.4.1 → 0.5.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/cli.mjs +36 -6
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -26,6 +26,9 @@ const MAX_STEPS = Number(process.env.C0MPUTE_MAX_STEPS || 40);
|
|
|
26
26
|
const CWD = process.cwd();
|
|
27
27
|
const ROOT = CWD; // the project boundary: the agent may not touch files outside this without approval
|
|
28
28
|
const AUTO = process.env.C0MPUTE_YOLO === '1';
|
|
29
|
+
// ── workspace: a persistent per-project .c0mpute/ dir the agent keeps across sessions ──
|
|
30
|
+
const WS_DIR = join(ROOT, '.c0mpute');
|
|
31
|
+
const WS_JOURNAL = join(WS_DIR, 'journal.md');
|
|
29
32
|
|
|
30
33
|
// ── ansi ──
|
|
31
34
|
const e = (n) => (s) => `\x1b[${n}m${s}\x1b[0m`;
|
|
@@ -89,6 +92,29 @@ function loadProjectNotes() {
|
|
|
89
92
|
return null;
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
// ── workspace memory: continuity across sessions ──
|
|
96
|
+
// A running journal of completed tasks in .c0mpute/journal.md. Loaded into context at
|
|
97
|
+
// startup so the agent remembers what it already did in this project; appended after
|
|
98
|
+
// every verified coding task. Per-project, plain markdown, no deps. The user can commit
|
|
99
|
+
// it to share project history with the team, or .gitignore it to keep it local.
|
|
100
|
+
function loadWorkspace() {
|
|
101
|
+
try {
|
|
102
|
+
const lines = readFileSync(WS_JOURNAL, 'utf8').split('\n').filter(l => l.trimStart().startsWith('- '));
|
|
103
|
+
return lines.length ? lines.slice(-15).join('\n') : null;
|
|
104
|
+
} catch { return null; }
|
|
105
|
+
}
|
|
106
|
+
function recordWork(task, summary) {
|
|
107
|
+
try {
|
|
108
|
+
const day = new Date().toISOString().slice(0, 10);
|
|
109
|
+
const note = String(summary || task).replace(/\s+/g, ' ').trim().slice(0, 160);
|
|
110
|
+
if (!note) return;
|
|
111
|
+
mkdirSync(WS_DIR, { recursive: true });
|
|
112
|
+
let prior = ''; try { prior = readFileSync(WS_JOURNAL, 'utf8'); } catch {}
|
|
113
|
+
if (!prior) prior = '# c0mpute workspace — work journal\n# Persistent across sessions; the agent reads recent entries for continuity.\n\n';
|
|
114
|
+
writeFileSync(WS_JOURNAL, prior + `- ${day} ${note}\n`);
|
|
115
|
+
} catch {}
|
|
116
|
+
}
|
|
117
|
+
|
|
92
118
|
// ── streaming over the network ──
|
|
93
119
|
const PULSE = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '▇', '▆', '▅', '▄', '▃', '▂']; // compute pulse
|
|
94
120
|
async function think(messages) {
|
|
@@ -292,7 +318,7 @@ const LABELS = { read: 'Read', list: 'List', search: 'Search', edit: 'Update', w
|
|
|
292
318
|
async function runTask(task, history) {
|
|
293
319
|
console.log('');
|
|
294
320
|
history.push({ role: 'user', content: task });
|
|
295
|
-
let ran = false, nudges = 0, lastRunFailed = false, doneNudges = 0;
|
|
321
|
+
let ran = false, nudges = 0, lastRunFailed = false, doneNudges = 0, doneSummary = '';
|
|
296
322
|
busy = true; interrupted = false;
|
|
297
323
|
// is this a coding task (enforce actions) or chat/greeting (a prose reply is fine)?
|
|
298
324
|
const isCoding = /\b(fix|bug|error|fail|implement|add|refactor|test|debug|rename|update|create|build|install|broken|crash|exception|traceback|function|class|import|run)\b/i.test(task) || /[\w./-]+\.\w{1,5}\b/.test(task);
|
|
@@ -315,7 +341,7 @@ async function runTask(task, history) {
|
|
|
315
341
|
if (verb === 'done') {
|
|
316
342
|
// don't accept "done" while the last command was still failing — that's a false finish
|
|
317
343
|
if (lastRunFailed && doneNudges < 2) { doneNudges++; history.push({ role: 'user', content: 'The last command reported failures/errors, so the task is NOT verified. Keep fixing and re-run the test until it passes. If you are genuinely stuck, say plainly what is still broken instead of using `done`.' }); continue; }
|
|
318
|
-
ran = true; break;
|
|
344
|
+
ran = true; doneSummary = act.body.split('\n').map(s => s.trim()).filter(Boolean)[0] || ''; break;
|
|
319
345
|
}
|
|
320
346
|
const path0 = arg.split(/\s+/)[0] || '';
|
|
321
347
|
const shown = verb === 'search' ? arg : (verb === 'run' ? (arg || act.body.split('\n')[0]) : path0);
|
|
@@ -347,7 +373,7 @@ async function runTask(task, history) {
|
|
|
347
373
|
}
|
|
348
374
|
} finally { busy = false; }
|
|
349
375
|
if (interrupted) { interrupted = false; console.log(c.dim(' ⊘ stopped.') + '\n'); }
|
|
350
|
-
else if (ran) console.log(MARK + ' ' + c.dim('done') + '\n');
|
|
376
|
+
else if (ran) { if (isCoding) recordWork(task, doneSummary); console.log(MARK + ' ' + c.dim('done') + '\n'); }
|
|
351
377
|
else console.log('');
|
|
352
378
|
}
|
|
353
379
|
|
|
@@ -392,14 +418,17 @@ async function main() {
|
|
|
392
418
|
if (a !== 'y' && a !== 'yes') { console.log(c.dim(' exiting — cd into your project and run again.')); RL?.close(); return; }
|
|
393
419
|
}
|
|
394
420
|
const notes = loadProjectNotes();
|
|
421
|
+
const ws = loadWorkspace();
|
|
395
422
|
console.log('\n' + box([
|
|
396
423
|
`${MARK} ${c.b('c0mpute code')}${VERSION ? c.gry(' v' + VERSION) : ''}`,
|
|
397
424
|
c.dim('your coding agent, running on the c0mpute network'),
|
|
398
425
|
'',
|
|
399
426
|
`${c.dim('model')} ${MODEL} ${c.dim('cwd')} ${CWD.replace(homedir(), '~')} ${c.dim(isGit ? 'git · diffs on' : 'no git')}`,
|
|
400
|
-
c.dim(`edits ask first · reads run automatically${notes ? ` · memory ${notes.name}` : ''} · /help`),
|
|
427
|
+
c.dim(`edits ask first · reads run automatically${notes ? ` · memory ${notes.name}` : ''}${ws ? ' · workspace' : ''} · /help`),
|
|
401
428
|
]));
|
|
402
|
-
const sysmsg = SYSTEM
|
|
429
|
+
const sysmsg = SYSTEM
|
|
430
|
+
+ (notes ? `\n\nPROJECT NOTES (from ${notes.name}, treat as authoritative project context):\n${notes.text}` : '')
|
|
431
|
+
+ (ws ? `\n\nRECENT WORK (your journal from past sessions in this project, oldest first — for continuity; don't redo finished work):\n${ws}` : '');
|
|
403
432
|
const history = [{ role: 'system', content: sysmsg }];
|
|
404
433
|
const fin = () => { if (redactCount) console.log(c.dim(` ${redactCount} secret${redactCount > 1 ? 's' : ''} redacted before leaving your machine`)); };
|
|
405
434
|
// ctrl-c: interrupt a running task; at an idle prompt, exit cleanly
|
|
@@ -414,7 +443,8 @@ async function main() {
|
|
|
414
443
|
if (task === '/exit' || task === '/quit') { fin(); break; }
|
|
415
444
|
if (task === '/login') { await setupKey(); continue; }
|
|
416
445
|
if (task === '/init') { await initProject(); continue; }
|
|
417
|
-
if (task === '/
|
|
446
|
+
if (task === '/workspace') { const j = loadWorkspace(); console.log(j ? '\n' + MARK + ' ' + c.dim(`workspace journal (${WS_JOURNAL.replace(homedir(), '~')}):`) + '\n' + j.split('\n').map(l => ' ' + c.dim(l)).join('\n') : c.dim(' no workspace yet — it starts after your first completed task.')); continue; }
|
|
447
|
+
if (task === '/help') { console.log(c.dim(' describe a coding task; I locate, read, edit, and run tests to verify.\n reads auto-run · edits/commands ask first · files outside this dir always ask.\n /init write project memory · /workspace show project journal · /login set key · /exit quit · ctrl-c interrupt')); continue; }
|
|
418
448
|
try { await runTask(task, history); } catch (x) { console.log(c.red(' ! ' + x.message)); }
|
|
419
449
|
}
|
|
420
450
|
RL?.close();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c0mpute/code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Decentralized coding agent — thinking runs on the c0mpute network, file edits and commands run locally under your approval. Claude Code-style UX, no single provider.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|