create-claude-workspace 1.1.132 → 1.1.134
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/scripts/autonomous.mjs +42 -2
- package/dist/scripts/lib/tui.mjs +13 -15
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// ─── Autonomous development loop ───
|
|
3
3
|
// Headless runner for Claude Code orchestrator using Agent SDK.
|
|
4
4
|
import { resolve } from 'node:path';
|
|
5
|
-
import { existsSync, writeFileSync, unlinkSync, readFileSync } from 'node:fs';
|
|
5
|
+
import { existsSync, writeFileSync, unlinkSync, readFileSync, readdirSync } from 'node:fs';
|
|
6
6
|
import { execSync } from 'node:child_process';
|
|
7
7
|
import { DEFAULTS } from './lib/types.mjs';
|
|
8
8
|
import { emptyCheckpoint, readCheckpoint, writeCheckpoint } from './lib/state.mjs';
|
|
@@ -250,6 +250,33 @@ function isProjectComplete(memory, dir) {
|
|
|
250
250
|
return false;
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
+
function loadAgents(dir) {
|
|
254
|
+
const agentsDir = resolve(dir, '.claude', 'agents');
|
|
255
|
+
const agents = {};
|
|
256
|
+
if (!existsSync(agentsDir))
|
|
257
|
+
return agents;
|
|
258
|
+
for (const file of readdirSync(agentsDir)) {
|
|
259
|
+
if (!file.endsWith('.md'))
|
|
260
|
+
continue;
|
|
261
|
+
const name = file.replace('.md', '');
|
|
262
|
+
const content = readFileSync(resolve(agentsDir, file), 'utf-8');
|
|
263
|
+
// Parse YAML frontmatter
|
|
264
|
+
let description = name;
|
|
265
|
+
let model;
|
|
266
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
267
|
+
if (fmMatch) {
|
|
268
|
+
const fm = fmMatch[1];
|
|
269
|
+
const descMatch = fm.match(/description:\s*["']?(.*?)["']?\s*$/m);
|
|
270
|
+
if (descMatch)
|
|
271
|
+
description = descMatch[1];
|
|
272
|
+
const modelMatch = fm.match(/model:\s*(\S+)/m);
|
|
273
|
+
if (modelMatch)
|
|
274
|
+
model = modelMatch[1];
|
|
275
|
+
}
|
|
276
|
+
agents[name] = { description, prompt: content, model };
|
|
277
|
+
}
|
|
278
|
+
return agents;
|
|
279
|
+
}
|
|
253
280
|
function gitPull(dir) {
|
|
254
281
|
try {
|
|
255
282
|
execSync('git fetch --quiet && git pull --ff-only --quiet', { cwd: dir, timeout: 30_000, stdio: 'pipe' });
|
|
@@ -383,13 +410,26 @@ async function main() {
|
|
|
383
410
|
resumeOpts.continue = true;
|
|
384
411
|
opts.resume = false;
|
|
385
412
|
}
|
|
413
|
+
const agents = loadAgents(opts.projectDir);
|
|
414
|
+
// Load project CLAUDE.md as system prompt context (don't use settingSources
|
|
415
|
+
// which adds built-in agents like general-purpose, Explore, Plan)
|
|
416
|
+
let claudeMd = '';
|
|
417
|
+
const claudeMdPath = resolve(opts.projectDir, 'CLAUDE.md');
|
|
418
|
+
const dotClaudeMdPath = resolve(opts.projectDir, '.claude', 'CLAUDE.md');
|
|
419
|
+
if (existsSync(claudeMdPath))
|
|
420
|
+
claudeMd = readFileSync(claudeMdPath, 'utf-8');
|
|
421
|
+
else if (existsSync(dotClaudeMdPath))
|
|
422
|
+
claudeMd = readFileSync(dotClaudeMdPath, 'utf-8');
|
|
386
423
|
const queryOptions = {
|
|
387
|
-
|
|
424
|
+
agents,
|
|
388
425
|
agent: 'orchestrator',
|
|
389
426
|
model: 'claude-opus-4-6',
|
|
390
427
|
maxTurns: opts.maxTurns,
|
|
391
428
|
cwd: opts.projectDir,
|
|
392
429
|
};
|
|
430
|
+
if (claudeMd) {
|
|
431
|
+
queryOptions.systemPrompt = { type: 'preset', preset: 'claude_code', append: claudeMd };
|
|
432
|
+
}
|
|
393
433
|
if (opts.skipPermissions) {
|
|
394
434
|
queryOptions.permissionMode = 'bypassPermissions';
|
|
395
435
|
queryOptions.allowDangerouslySkipPermissions = true;
|
package/dist/scripts/lib/tui.mjs
CHANGED
|
@@ -43,7 +43,6 @@ export class TUI {
|
|
|
43
43
|
// Render state
|
|
44
44
|
pendingLines = [];
|
|
45
45
|
renderTimer = null;
|
|
46
|
-
lastStatusLen = 0;
|
|
47
46
|
// Stats
|
|
48
47
|
loopStart = Date.now();
|
|
49
48
|
iteration_ = 0;
|
|
@@ -61,26 +60,25 @@ export class TUI {
|
|
|
61
60
|
this.interactive = interactive && process.stdin.isTTY === true;
|
|
62
61
|
if (this.interactive) {
|
|
63
62
|
this.setupInput();
|
|
64
|
-
//
|
|
65
|
-
this.renderTimer = setInterval(() => this.render(),
|
|
63
|
+
// 60 fps render loop
|
|
64
|
+
this.renderTimer = setInterval(() => this.render(), 16);
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
// ─── Render loop ───
|
|
69
68
|
render() {
|
|
70
69
|
const out = process.stdout;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
const hasPending = this.pendingLines.length > 0;
|
|
71
|
+
// Erase current status line
|
|
72
|
+
out.write('\r\x1b[2K');
|
|
73
|
+
// Flush pending log lines — each gets its own line
|
|
74
|
+
if (hasPending) {
|
|
75
|
+
for (const line of this.pendingLines) {
|
|
76
|
+
out.write(line + '\n');
|
|
77
|
+
}
|
|
78
|
+
this.pendingLines = [];
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const status = this.buildStatus();
|
|
82
|
-
out.write(status);
|
|
83
|
-
this.lastStatusLen = strip(status).length;
|
|
80
|
+
// Redraw status bar (no \n — stays on current line, overwritable by next render)
|
|
81
|
+
out.write(this.buildStatus());
|
|
84
82
|
}
|
|
85
83
|
buildStatus() {
|
|
86
84
|
const elapsed = fmtDur(Date.now() - this.loopStart);
|