project-compass 4.0.2 → 4.0.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "description": "Futuristic project navigator and runner for Node, Python, Rust, and Go",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -498,10 +498,10 @@ function Compass({rootPath, initialView = 'navigator'}) {
498
498
  }
499
499
  });
500
500
 
501
- const projectCountLabel = useMemo(() => `${projects.length} project\${projects.length === 1 ? '' : 's'}`, [projects.length]);
501
+ const projectCountLabel = useMemo(() => `${projects.length} project${projects.length === 1 ? '' : 's'}`, [projects.length]);
502
502
  const toggleHint = config.showHelpCards ? 'Shift+H hide help' : 'Shift+H show help';
503
- const statusHint = activeTask ? `[\${activeTask.status.toUpperCase()}] \${activeTask.name}` : 'Idle Navigator';
504
- const orbitHint = mainView === 'tasks' ? 'Tasks View' : `Orbit: \${tasks.length} tasks`;
503
+ const statusHint = activeTask ? `[${activeTask.status.toUpperCase()}] ${activeTask.name}` : 'Idle Navigator';
504
+ const orbitHint = mainView === 'tasks' ? 'Tasks View' : `Orbit: ${tasks.length} tasks`;
505
505
  const artHint = config.showArtBoard ? 'Shift+B hide art' : 'Shift+B show art';
506
506
 
507
507
  const detailContent = useMemo(() => {
@@ -511,28 +511,28 @@ function Compass({rootPath, initialView = 'navigator'}) {
511
511
 
512
512
  const content = [
513
513
  create(Box, {key: 'title-row', flexDirection: 'row'},
514
- create(Text, {color: 'cyan', bold: true}, `\${selectedProject.icon} \${selectedProject.name}`),
514
+ create(Text, {color: 'cyan', bold: true}, `${selectedProject.icon} ${selectedProject.name}`),
515
515
  selectedProject.missingBinaries && selectedProject.missingBinaries.length > 0 && create(Text, {color: 'red', bold: true}, ' ⚠️ MISSING RUNTIME')
516
516
  ),
517
- create(Text, {key: 'manifest', dimColor: true}, `\${selectedProject.type} · \${selectedProject.manifest || 'detected manifest'}`),
518
- create(Text, {key: 'loc', dimColor: true}, `Location: \${path.relative(rootPath, selectedProject.path) || '.'}`)
517
+ create(Text, {key: 'manifest', dimColor: true}, `${selectedProject.type} · ${selectedProject.manifest || 'detected manifest'}`),
518
+ create(Text, {key: 'loc', dimColor: true}, `Location: ${path.relative(rootPath, selectedProject.path) || '.'}`)
519
519
  ];
520
520
  if (selectedProject.description) content.push(create(Text, {key: 'desc'}, selectedProject.description));
521
- const frameworks = (selectedProject.frameworks || []).map((lib) => `\${lib.icon} \${lib.name}`).join(', ');
522
- if (frameworks) content.push(create(Text, {key: 'frames', dimColor: true}, `Frameworks: \${frameworks}`));
521
+ const frameworks = (selectedProject.frameworks || []).map((lib) => `${lib.icon} ${lib.name}`).join(', ');
522
+ if (frameworks) content.push(create(Text, {key: 'frames', dimColor: true}, `Frameworks: ${frameworks}`));
523
523
 
524
524
  if (selectedProject.missingBinaries && selectedProject.missingBinaries.length > 0) {
525
525
  content.push(
526
526
  create(Text, {key: 'm-t', color: 'red', bold: true, marginTop: 1}, 'MISSING BINARIES:'),
527
- create(Text, {key: 'm-l', color: 'red'}, `Please install: \${selectedProject.missingBinaries.join(', ')}`)
527
+ create(Text, {key: 'm-l', color: 'red'}, `Please install: ${selectedProject.missingBinaries.join(', ')}`)
528
528
  );
529
529
  }
530
530
 
531
531
  content.push(create(Text, {key: 'cmd-header', bold: true, marginTop: 1}, 'Commands'));
532
532
  detailedIndexed.forEach((command) => {
533
533
  content.push(
534
- create(Text, {key: `d-\${command.shortcut}`}, `\${command.shortcut}. \${command.label} \${command.source === 'custom' ? kleur.magenta('(custom)') : command.source === 'framework' ? kleur.cyan('(framework)') : ''}`),
535
- create(Text, {key: `dl-\${command.shortcut}`, dimColor: true}, ` ↳ \${command.command.join(' ')}`)
534
+ create(Text, {key: `d-${command.shortcut}`}, `${command.shortcut}. ${command.label} ${command.source === 'custom' ? kleur.magenta('(custom)') : command.source === 'framework' ? kleur.cyan('(framework)') : ''}`),
535
+ create(Text, {key: `dl-${command.shortcut}`, dimColor: true}, ` ↳ ${command.command.join(' ')}`)
536
536
  );
537
537
  });
538
538
  content.push(create(Text, {key: 'h-l', dimColor: true, marginTop: 1}, 'Press Shift+C → label|cmd to save custom actions, Enter to close detail view.'));
@@ -540,17 +540,17 @@ function Compass({rootPath, initialView = 'navigator'}) {
540
540
  }, [viewMode, selectedProject, rootPath, detailedIndexed]);
541
541
 
542
542
  const artTileNodes = useMemo(() => [
543
- {label: 'Pulse', detail: projectCountLabel, accent: 'magenta', icon: '●', subtext: `Workspace · \${path.basename(rootPath) || rootPath}`},
544
- {label: 'Focus', detail: selectedProject?.name || 'Selection', accent: 'cyan', icon: '◆', subtext: `\${selectedProject?.type || 'Stack'}`},
545
- {label: 'Orbit', detail: `\${tasks.length} tasks`, accent: 'yellow', icon: '■', subtext: running ? 'Busy streaming...' : 'Idle'}
543
+ {label: 'Pulse', detail: projectCountLabel, accent: 'magenta', icon: '●', subtext: `Workspace · ${path.basename(rootPath) || rootPath}`},
544
+ {label: 'Focus', detail: selectedProject?.name || 'Selection', accent: 'cyan', icon: '◆', subtext: `${selectedProject?.type || 'Stack'}`},
545
+ {label: 'Orbit', detail: `${tasks.length} tasks`, accent: 'yellow', icon: '■', subtext: running ? 'Busy streaming...' : 'Idle'}
546
546
  ].map(tile => create(Box, {key: tile.label, flexDirection: 'column', padding: 1, marginRight: 1, borderStyle: 'single', borderColor: tile.accent, minWidth: 24},
547
- create(Text, {color: tile.accent, bold: true}, `\${tile.icon} \${tile.label}`),
547
+ create(Text, {color: tile.accent, bold: true}, `${tile.icon} ${tile.label}`),
548
548
  create(Text, {bold: true}, tile.detail),
549
549
  create(Text, {dimColor: true}, tile.subtext)
550
550
  )), [projectCountLabel, rootPath, selectedProject, tasks.length, running]);
551
551
 
552
552
  if (quitConfirm) {
553
- return create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'red', padding: 1}, create(Text, {bold: true, color: 'red'}, '⚠️ Confirm Exit'), create(Text, null, `There are \${tasks.filter(t=>t.status==='running').length} tasks still running in the background.`), create(Text, null, 'Are you sure you want to quit and stop all processes?'), create(Text, {marginTop: 1}, kleur.bold('Y') + ' to Quit, ' + kleur.bold('N') + ' to Cancel'));
553
+ return create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'red', padding: 1}, create(Text, {bold: true, color: 'red'}, '⚠️ Confirm Exit'), create(Text, null, `There are ${tasks.filter(t=>t.status==='running').length} tasks still running in the background.`), create(Text, null, 'Are you sure you want to quit and stop all processes?'), create(Text, {marginTop: 1}, kleur.bold('Y') + ' to Quit, ' + kleur.bold('N') + ' to Cancel'));
554
554
  }
555
555
 
556
556
  const renderView = () => {
@@ -576,7 +576,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
576
576
  create(Box, {flexGrow: 1.3, flexBasis: 0, minWidth: DETAILS_MIN_WIDTH, borderStyle: 'round', borderColor: 'cyan', padding: 1, flexDirection: 'column'}, create(Text, {bold: true, color: 'cyan'}, 'Details'), ...detailContent)
577
577
  ),
578
578
  create(Box, {key: 'output-row', marginTop: 1, flexDirection: 'column'},
579
- create(Box, {flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {bold: true, color: 'yellow'}, `Output: \${activeTask?.name || 'None'}`), create(Text, {dimColor: true}, logOffset ? `Scrolled \${logOffset} lines` : 'Live log view')),
579
+ create(Box, {flexDirection: 'row', justifyContent: 'space-between'}, create(Text, {bold: true, color: 'yellow'}, `Output: ${activeTask?.name || 'None'}`), create(Text, {dimColor: true}, logOffset ? `Scrolled ${logOffset} lines` : 'Live log view')),
580
580
  create(OutputPanel, {activeTask, logOffset}),
581
581
  create(Footer, {toggleHint, running, stdinBuffer, stdinCursor, CursorText})
582
582
  ),
@@ -585,7 +585,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
585
585
  {label: 'Management', color: 'cyan', body: ['Shift+P Package Registry', 'Shift+N Project Architect', 'Shift+X clear / Shift+E export']},
586
586
  {label: 'Orbit & AI', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+O AI Horizon', 'Shift+S structure / Shift+Q quit']}
587
587
  ].map((card, idx) => create(Box, {key: card.label, flexGrow: 1, flexBasis: 0, minWidth: HELP_CARD_MIN_WIDTH, marginRight: idx < 2 ? 1 : 0, marginBottom: 1, borderStyle: 'round', borderColor: card.color, padding: 1, flexDirection: 'column'}, create(Text, {color: card.color, bold: true, marginBottom: 1}, card.label), ...card.body.map((line, lidx) => create(Text, {key: lidx, dimColor: card.color === 'yellow'}, line))))),
588
- config.showStructureGuide && create(Box, {key: 'structure', flexDirection: 'column', borderStyle: 'round', borderColor: 'blue', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Structure guide · press Shift+S to hide'), ...SCHEMA_GUIDE.map(e => create(Text, {key: e.type, dimColor: true}, `• \${e.icon} \${e.label}: \${e.files.join(', ')}`))),
588
+ config.showStructureGuide && create(Box, {key: 'structure', flexDirection: 'column', borderStyle: 'round', borderColor: 'blue', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Structure guide · press Shift+S to hide'), ...SCHEMA_GUIDE.map(e => create(Text, {key: e.type, dimColor: true}, `• ${e.icon} ${e.label}: ${e.files.join(', ')}`))),
589
589
  showHelp && create(Box, {key: 'overlay', flexDirection: 'column', borderStyle: 'double', borderColor: 'cyan', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Help overlay'), create(Text, null, 'Shift+↑/↓ scrolls logs; Shift+X clears; Shift+E exports; Shift+A Studio; Shift+T Tasks; Shift+D Detach; Shift+B Toggle Art Board; Shift+P Packages; Shift+N Creator; Shift+O AI Horizon.'))
590
590
  ];
591
591
  return create(Box, {flexDirection: 'column'}, ...navigatorBody);
@@ -618,7 +618,7 @@ async function main() {
618
618
  if (args.version) {
619
619
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
620
620
  const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
621
- console.log(`v\${pkg.version}`);
621
+ console.log(`v${pkg.version}`);
622
622
  return;
623
623
  }
624
624
  if (args.help) {
@@ -664,8 +664,8 @@ async function main() {
664
664
  const rootPath = args.root ? path.resolve(args.root) : process.cwd();
665
665
  if (args.mode === 'test') {
666
666
  const projects = await discoverProjects(rootPath);
667
- console.log(`Detected \${projects.length} project(s) under \${rootPath}`);
668
- projects.forEach((project) => { console.log(` • [\${project.type}] \${project.name} (\${project.path})`); });
667
+ console.log(`Detected ${projects.length} project(s) under ${rootPath}`);
668
+ projects.forEach((project) => { console.log(` • [${project.type}] ${project.name} (${project.path})`); });
669
669
  return;
670
670
  }
671
671
 
@@ -1,3 +1,4 @@
1
+ /* global setTimeout */
1
2
  import React, {useState, memo} from 'react';
2
3
  import {Box, Text, useInput} from 'ink';
3
4
 
@@ -10,7 +11,7 @@ const AI_PROVIDERS = [
10
11
  { id: 'ollama', name: 'Ollama (Local)', endpoint: 'http://localhost:11434', keyEnv: 'NONE' }
11
12
  ];
12
13
 
13
- const AIHorizon = memo(({rootPath, selectedProject, onRunCommand, CursorText, config, setConfig, saveConfig}) => {
14
+ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveConfig}) => {
14
15
  const [step, setStep] = useState(config?.aiToken ? 'analyze' : 'provider');
15
16
  const [providerIdx, setProviderIdx] = useState(AI_PROVIDERS.findIndex(p => p.id === (config?.aiProvider || 'openrouter')) || 0);
16
17
  const [model, setModel] = useState(config?.aiModel || 'deepseek/deepseek-r1');