writethevision 7.0.3 → 7.0.4
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/package.json +1 -1
- package/src/cli.js +72 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "writethevision",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.4",
|
|
4
4
|
"description": "Write The Vision (WTV): vision-driven development with the Habakkuk workflow. 10 agents + 21 skills for Claude Code, Codex CLI, and OpenCode.",
|
|
5
5
|
"author": "Christopher Hogg",
|
|
6
6
|
"license": "MIT",
|
package/src/cli.js
CHANGED
|
@@ -402,13 +402,71 @@ function getAgentLocations() {
|
|
|
402
402
|
return locations;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
|
|
406
|
-
|
|
405
|
+
const BLOCK_FONT_3X5 = {
|
|
406
|
+
A: ['███', '█ █', '███', '█ █', '█ █'],
|
|
407
|
+
B: ['██ ', '█ █', '██ ', '█ █', '██ '],
|
|
408
|
+
C: ['███', '█ ', '█ ', '█ ', '███'],
|
|
409
|
+
D: ['██ ', '█ █', '█ █', '█ █', '██ '],
|
|
410
|
+
E: ['███', '█ ', '██ ', '█ ', '███'],
|
|
411
|
+
F: ['███', '█ ', '██ ', '█ ', '█ '],
|
|
412
|
+
G: ['███', '█ ', '█ █', '█ █', '███'],
|
|
413
|
+
H: ['█ █', '█ █', '███', '█ █', '█ █'],
|
|
414
|
+
I: ['███', ' █ ', ' █ ', ' █ ', '███'],
|
|
415
|
+
J: [' ██', ' █', ' █', '█ █', '██ '],
|
|
416
|
+
K: ['█ █', '█ █', '██ ', '█ █', '█ █'],
|
|
417
|
+
L: ['█ ', '█ ', '█ ', '█ ', '███'],
|
|
418
|
+
M: ['█ █', '███', '███', '█ █', '█ █'],
|
|
419
|
+
N: ['█ █', '███', '███', '███', '█ █'],
|
|
420
|
+
O: ['███', '█ █', '█ █', '█ █', '███'],
|
|
421
|
+
P: ['███', '█ █', '███', '█ ', '█ '],
|
|
422
|
+
Q: ['███', '█ █', '█ █', '███', ' █'],
|
|
423
|
+
R: ['███', '█ █', '███', '█ █', '█ █'],
|
|
424
|
+
S: ['███', '█ ', '███', ' █', '███'],
|
|
425
|
+
T: ['███', ' █ ', ' █ ', ' █ ', ' █ '],
|
|
426
|
+
U: ['█ █', '█ █', '█ █', '█ █', '███'],
|
|
427
|
+
V: ['█ █', '█ █', '█ █', '█ █', ' █ '],
|
|
428
|
+
W: ['█ █', '█ █', '███', '███', '█ █'],
|
|
429
|
+
X: ['█ █', '█ █', ' █ ', '█ █', '█ █'],
|
|
430
|
+
Y: ['█ █', '█ █', ' █ ', ' █ ', ' █ '],
|
|
431
|
+
Z: ['███', ' █', ' █ ', '█ ', '███'],
|
|
432
|
+
' ': [' ', ' ', ' ', ' ', ' '],
|
|
433
|
+
'-': [' ', ' ', '███', ' ', ' '],
|
|
434
|
+
'?': ['███', ' █', ' ██', ' ', ' █ '],
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
function renderBlockText(text, { maxWidth = null, color = null, bold = false } = {}) {
|
|
438
|
+
const normalized = String(text || '').toUpperCase();
|
|
439
|
+
const glyphWidth = 3;
|
|
440
|
+
const letterGap = 1;
|
|
441
|
+
const maxCharsPerLine = maxWidth
|
|
442
|
+
? Math.max(1, Math.floor((maxWidth + letterGap) / (glyphWidth + letterGap)))
|
|
443
|
+
: normalized.length;
|
|
444
|
+
|
|
445
|
+
const chunks = [];
|
|
446
|
+
for (let i = 0; i < normalized.length; i += maxCharsPerLine) {
|
|
447
|
+
chunks.push(normalized.slice(i, i + maxCharsPerLine));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const renderedLines = [];
|
|
451
|
+
for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
|
|
452
|
+
const chunk = chunks[chunkIndex];
|
|
453
|
+
for (let row = 0; row < 5; row++) {
|
|
454
|
+
const rowText = chunk
|
|
455
|
+
.split('')
|
|
456
|
+
.map(ch => (BLOCK_FONT_3X5[ch] ? BLOCK_FONT_3X5[ch][row] : BLOCK_FONT_3X5['?']?.[row] || '???'))
|
|
457
|
+
.join(' '.repeat(letterGap));
|
|
458
|
+
|
|
459
|
+
const prefix = color ? (bold ? color + c.bold : color) : '';
|
|
460
|
+
const suffix = color ? c.reset : '';
|
|
461
|
+
renderedLines.push(prefix + rowText + suffix);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (chunkIndex !== chunks.length - 1) {
|
|
465
|
+
renderedLines.push('');
|
|
466
|
+
}
|
|
467
|
+
}
|
|
407
468
|
|
|
408
|
-
return
|
|
409
|
-
.split('\n')
|
|
410
|
-
.map(line => line.replace(/[^\s]/g, '█'))
|
|
411
|
-
.join('\n');
|
|
469
|
+
return renderedLines.join('\n');
|
|
412
470
|
}
|
|
413
471
|
|
|
414
472
|
function parseAgentFile(filePath) {
|
|
@@ -453,7 +511,7 @@ function parseAgentFile(filePath) {
|
|
|
453
511
|
let asciiArt = '';
|
|
454
512
|
const asciiMatch = content.match(/```text\n([\s\S]+?)\n```/);
|
|
455
513
|
if (asciiMatch) {
|
|
456
|
-
asciiArt =
|
|
514
|
+
asciiArt = asciiMatch[1];
|
|
457
515
|
}
|
|
458
516
|
|
|
459
517
|
return {
|
|
@@ -1685,11 +1743,7 @@ async function meetTheTeam() {
|
|
|
1685
1743
|
console.log(` ${c.bold}${c.yellow}PAUL — THE MASTERBUILDER${c.reset}`);
|
|
1686
1744
|
console.log(` ${c.dim}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
|
|
1687
1745
|
const paulAgent = parseAgentFile(join(TEMPLATES_DIR, 'agents', 'paul.md'));
|
|
1688
|
-
|
|
1689
|
-
console.log(paulAgent.asciiArt);
|
|
1690
|
-
} else {
|
|
1691
|
-
console.log(AVATARS.paul);
|
|
1692
|
-
}
|
|
1746
|
+
console.log(AVATARS.paul || (paulAgent && paulAgent.asciiArt ? paulAgent.asciiArt : ''));
|
|
1693
1747
|
await sleep(shortPause);
|
|
1694
1748
|
console.log(`
|
|
1695
1749
|
${c.cyan}"According to the grace of God which is given unto me,${c.reset}
|
|
@@ -1719,11 +1773,7 @@ async function meetTheTeam() {
|
|
|
1719
1773
|
console.log(` ${artisan.color}${c.bold}${artisan.name}${c.reset}`);
|
|
1720
1774
|
const templatePath = join(TEMPLATES_DIR, 'agents', artisan.file);
|
|
1721
1775
|
const agent = parseAgentFile(templatePath);
|
|
1722
|
-
|
|
1723
|
-
console.log(agent.asciiArt);
|
|
1724
|
-
} else {
|
|
1725
|
-
console.log(AVATARS[artisan.id]);
|
|
1726
|
-
}
|
|
1776
|
+
console.log(AVATARS[artisan.id] || (agent && agent.asciiArt ? agent.asciiArt : ''));
|
|
1727
1777
|
console.log(` ${c.dim}${artisan.domain}${c.reset}`);
|
|
1728
1778
|
if (artisan.verse) {
|
|
1729
1779
|
console.log(` ${c.dim}${artisan.verse.ref}${c.reset} ${c.dim}"${artisan.verse.text}"${c.reset}`);
|
|
@@ -3522,13 +3572,15 @@ async function agentsInteractive() {
|
|
|
3522
3572
|
if (agent.wantsGlobal) statusText += c.blue + 'Global ' + c.reset;
|
|
3523
3573
|
if (!agent.wantsLocal && !agent.wantsGlobal) statusText = c.dim + 'None' + c.reset;
|
|
3524
3574
|
|
|
3575
|
+
const terminalWidth = process.stdout.columns || 80;
|
|
3576
|
+
const detailWidth = Math.max(20, terminalWidth - detailStartX - 1);
|
|
3577
|
+
const nameBanner = renderBlockText(agent.name, { maxWidth: detailWidth, color: c.magenta, bold: true });
|
|
3578
|
+
|
|
3525
3579
|
const details = [
|
|
3526
|
-
|
|
3580
|
+
nameBanner,
|
|
3527
3581
|
`Status: ${statusText}`,
|
|
3528
3582
|
'',
|
|
3529
3583
|
`${c.dim}${agent.description}${c.reset}`,
|
|
3530
|
-
'',
|
|
3531
|
-
agent.asciiArt ? agent.asciiArt : `${c.dim}[ No Portrait ]${c.reset}`
|
|
3532
3584
|
];
|
|
3533
3585
|
|
|
3534
3586
|
// Draw details
|