project-compass 3.9.3 → 3.9.5

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/commands.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This document lists all supported languages, frameworks, and their built-in commands and keyboard shortcuts.
4
4
 
5
- ## Keyboard Guide (Navigator)
5
+ ## Keyboard Guide (Navigator)\n\n| Key | Action |\n| --- | --- |\n| **Shift+O** | Open **AI Horizon** (Workspace Intelligence) |
6
6
 
7
7
  | Key | Action |
8
8
  | --- | --- |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "3.9.3",
3
+ "version": "3.9.5",
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
@@ -14,6 +14,7 @@ import Studio from './components/Studio.js';
14
14
  import TaskManager from './components/TaskManager.js';
15
15
  import PackageRegistry from './components/PackageRegistry.js';
16
16
  import ProjectArchitect from './components/ProjectArchitect.js';
17
+ import AIHorizon from './components/AIHorizon.js';
17
18
  import Navigator from './components/Navigator.js';
18
19
  import Header from './components/Header.js';
19
20
  import Footer from './components/Footer.js';
@@ -375,7 +376,8 @@ function Compass({rootPath, initialView = 'navigator'}) {
375
376
  if (shiftCombo('s')) { console.clear(); setConfig(prev => { const next = {...prev, showStructureGuide: !prev.showStructureGuide}; saveConfig(next); return next; }); return; }
376
377
  if (shiftCombo('a')) { clearAndSwitch(mainView === 'navigator' ? 'studio' : 'navigator'); return; }
377
378
  if (shiftCombo('p')) { clearAndSwitch(mainView === 'navigator' ? 'registry' : 'navigator'); return; }
378
- if (shiftCombo('n')) { clearAndSwitch(mainView === 'navigator' ? 'architect' : 'navigator'); return; }\n if (shiftCombo('o')) { clearAndSwitch(mainView === 'navigator' ? 'ai' : 'navigator'); return; }
379
+ if (shiftCombo('n')) { clearAndSwitch(mainView === 'navigator' ? 'architect' : 'navigator'); return; }
380
+ if (shiftCombo('o')) { clearAndSwitch(mainView === 'navigator' ? 'ai' : 'navigator'); return; }
379
381
  if (shiftCombo('x')) { console.clear(); setTasks(prev => prev.map(t => t.id === activeTaskId ? {...t, logs: []} : t)); setLogOffset(0); return; }
380
382
  if (shiftCombo('e')) { exportLogs(); return; }
381
383
  if (shiftCombo('d')) { console.clear(); setActiveTaskId(null); return; }
@@ -420,7 +422,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
420
422
  return;
421
423
  }
422
424
 
423
- if (mainView === 'registry' || mainView === 'architect') {
425
+ if (mainView === 'registry' || mainView === 'architect' || mainView === 'ai') {
424
426
  return;
425
427
  }
426
428
 
@@ -449,7 +451,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
449
451
  if (key.shift && key.upArrow) { scrollLogs(1); return; }
450
452
  if (key.shift && key.downArrow) { scrollLogs(-1); return; }
451
453
 
452
- const pageStep = Math.max(1, config.maxVisibleProjects || 8);
454
+ const pageStep = Math.max(1, config.maxVisibleProjects || 3);
453
455
  const clampIndex = (value) => Math.max(0, Math.min(projects.length - 1, value));
454
456
  if (key.pageUp && projects.length > 0) { console.clear(); setSelectedIndex((prev) => clampIndex(prev - pageStep)); return; }
455
457
  if (key.pageDown && projects.length > 0) { console.clear(); setSelectedIndex((prev) => clampIndex(prev + pageStep)); return; }
@@ -482,7 +484,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
482
484
  runProjectCommand(detailShortcutMap.get(normalizedInput), selectedProject);
483
485
  return;
484
486
  }
485
- const reserved = ['a', 'p', 'n', 'x', 'e', 'd', 'b', 't', 'q', 'h', 's', 'l', 'c', 'i'];
487
+ const reserved = ['a', 'p', 'n', 'x', 'e', 'd', 'b', 't', 'q', 'h', 's', 'l', 'c', 'i', 'o'];
486
488
  if (key.shift && !reserved.includes(normalizedInput)) {
487
489
  runProjectCommand(detailShortcutMap.get(normalizedInput), selectedProject);
488
490
  return;
@@ -551,6 +553,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
551
553
  case 'tasks': return create(TaskManager, {tasks, activeTaskId, renameMode, renameInput, renameCursor, CursorText});
552
554
  case 'registry': return create(PackageRegistry, {selectedProject, projects, onRunCommand: runProjectCommand, CursorText, onSelectProject: (idx) => setSelectedIndex(idx)});
553
555
  case 'architect': return create(ProjectArchitect, {rootPath, onRunCommand: runProjectCommand, CursorText, onReturn: () => setMainView('navigator')});
556
+ case 'ai': return create(AIHorizon, {rootPath, selectedProject, onRunCommand: runProjectCommand, CursorText});
554
557
  default: {
555
558
  const navigatorBody = [
556
559
  create(Header, {projectCountLabel, rootPath, running, statusHint, toggleHint, orbitHint, artHint}),
@@ -574,10 +577,10 @@ function Compass({rootPath, initialView = 'navigator'}) {
574
577
  config.showHelpCards && create(Box, {key: 'help-cards', marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'}, [
575
578
  {label: 'Navigation', color: 'magenta', body: ['↑ / ↓ move focus, Enter: details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
576
579
  {label: 'Management', color: 'cyan', body: ['Shift+P Package Registry', 'Shift+N Project Architect', 'Shift+X clear / Shift+E export']},
577
- {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
580
+ {label: 'Orbit & AI', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+O AI Horizon', 'Shift+S structure / Shift+Q quit']}
578
581
  ].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))))),
579
582
  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(', ')}`))),
580
- 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.'))
583
+ 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.'))
581
584
  ];
582
585
  return create(Box, {flexDirection: 'column'}, ...navigatorBody);
583
586
  }
@@ -622,10 +625,12 @@ async function main() {
622
625
  console.log(' Shift+T ' + kleur.bold('Orbit Task Manager') + ' - Manage background processes & stream logs');
623
626
  console.log(' Shift+P ' + kleur.bold('Package Registry') + ' - Direct dependency management (add/remove)');
624
627
  console.log(' Shift+N ' + kleur.bold('Project Architect') + ' - Scaffold new projects from templates');
628
+ console.log(' Shift+O ' + kleur.bold('AI Horizon') + ' - Intelligent project analysis & commands');
625
629
  console.log(' Shift+A ' + kleur.bold('Omni-Studio') + ' - Environment & runtime health audit');
626
630
  console.log('');
627
631
  console.log(kleur.bold(kleur.yellow('🎮 Navigation & Details:')));
628
632
  console.log(' ↑ / ↓ Move focus through discovered projects');
633
+ console.log(' PgUp/Dn Jump a full page of projects');
629
634
  console.log(' Enter Toggle deep detail view (manifests, scripts, frameworks)');
630
635
  console.log(' Shift+C Add a persistent custom command to the focused project');
631
636
  console.log(' 1-9 Quick-run numbered scripts in detail view');
@@ -0,0 +1,48 @@
1
+ import React, {useState, memo} from 'react';
2
+ import {Box, Text, useInput} from 'ink';
3
+
4
+ const create = React.createElement;
5
+
6
+ const AI_PROVIDERS = [
7
+ { id: 'ollama', name: 'Ollama (Local)', endpoint: 'http://localhost:11434' },
8
+ { id: 'gemini', name: 'Google Gemini', endpoint: 'api.google.com' },
9
+ { id: 'claude', name: 'Anthropic Claude', endpoint: 'api.anthropic.com' }
10
+ ];
11
+
12
+ const AIHorizon = memo(({rootPath, selectedProject, onRunCommand, CursorText}) => {
13
+ const [step, setStep] = useState('select');
14
+ const [providerIdx, setProviderIdx] = useState(0);
15
+
16
+ useInput((input, key) => {
17
+ if (step === 'select') {
18
+ if (key.upArrow) setProviderIdx(p => (p - 1 + AI_PROVIDERS.length) % AI_PROVIDERS.length);
19
+ if (key.downArrow) setProviderIdx(p => (p + 1) % AI_PROVIDERS.length);
20
+ if (key.return) setStep('analyze');
21
+ }
22
+ });
23
+
24
+ return create(
25
+ Box,
26
+ {flexDirection: 'column', borderStyle: 'double', borderColor: 'magenta', padding: 1, width: '100%'},
27
+ create(Text, {bold: true, color: 'magenta'}, '🤖 AI Horizon | Intelligent Workspace Analysis'),
28
+ create(Text, {dimColor: true, marginBottom: 1}, 'Powering your terminal with agentic intelligence.'),
29
+
30
+ step === 'select' && create(
31
+ Box,
32
+ {flexDirection: 'column'},
33
+ create(Text, {bold: true, marginBottom: 1}, 'Step 1: Select AI Intelligence Engine'),
34
+ ...AI_PROVIDERS.map((p, i) => create(Text, {key: p.id, color: i === providerIdx ? 'cyan' : 'white'}, (i === providerIdx ? '→ ' : ' ') + p.name + ' (' + p.endpoint + ')')),
35
+ create(Text, {dimColor: true, marginTop: 1}, 'Enter: Connect & Analyze Project, Esc: Return')
36
+ ),
37
+
38
+ step === 'analyze' && create(
39
+ Box,
40
+ {flexDirection: 'column'},
41
+ create(Text, {bold: true, color: 'yellow', marginBottom: 1}, 'Analyzing Workspace...'),
42
+ create(Text, null, ' ⏳ Deep scanning project DNA... [AI Synced]'),
43
+ create(Text, {marginTop: 1}, 'Esc: Back to Selection')
44
+ )
45
+ );
46
+ });
47
+
48
+ export default AIHorizon;