project-compass 4.0.3 → 4.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/commands.md +7 -0
- package/package.json +1 -1
- package/src/cli.js +4 -5
- package/src/components/AIHorizon.js +44 -40
package/commands.md
CHANGED
|
@@ -92,3 +92,10 @@ Compass scans for the following manifests and requires their binaries in your PA
|
|
|
92
92
|
- Go (mod init)
|
|
93
93
|
- **Enter**: Confirm selection and move to next step.
|
|
94
94
|
- **Esc / Shift+N**: Exit architect mode.
|
|
95
|
+
|
|
96
|
+
## Advanced Configuration
|
|
97
|
+
|
|
98
|
+
You can manually edit the config file to change defaults:
|
|
99
|
+
- **Location**: `~/.project-compass/config.json`
|
|
100
|
+
- **maxVisibleProjects**: Adjust how many projects appear per page (default: 3).
|
|
101
|
+
- **aiProvider / aiModel / aiToken**: Change your AI intelligence settings.
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -294,7 +294,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
294
294
|
|
|
295
295
|
useInput((input, key) => {
|
|
296
296
|
if (quitConfirm) {
|
|
297
|
-
if (input?.toLowerCase() === 'y') { killAllTasks();
|
|
297
|
+
if (input?.toLowerCase() === 'y') { killAllTasks(); process.stdout.write('\x1b[2J\x1b[0;0H'); exit(); return; }
|
|
298
298
|
if (input?.toLowerCase() === 'n' || key.escape) { setQuitConfirm(false); return; }
|
|
299
299
|
return;
|
|
300
300
|
}
|
|
@@ -468,7 +468,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
468
468
|
return;
|
|
469
469
|
}
|
|
470
470
|
if (shiftCombo('q') || isCtrlC) {
|
|
471
|
-
if (hasRunningTasks) setQuitConfirm(true); else {
|
|
471
|
+
if (hasRunningTasks) setQuitConfirm(true); else { process.stdout.write('\x1b[2J\x1b[0;0H'); exit(); }
|
|
472
472
|
return;
|
|
473
473
|
}
|
|
474
474
|
|
|
@@ -581,9 +581,9 @@ function Compass({rootPath, initialView = 'navigator'}) {
|
|
|
581
581
|
create(Footer, {toggleHint, running, stdinBuffer, stdinCursor, CursorText})
|
|
582
582
|
),
|
|
583
583
|
config.showHelpCards && create(Box, {key: 'help-cards', marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'}, [
|
|
584
|
-
{label: 'Navigation', color: 'magenta', body: ['
|
|
584
|
+
{label: 'Navigation', color: 'magenta', body: ['↑/↓: focus, PgUp/Dn: Page, Enter: Details', 'Shift+↑ / ↓ scroll output', 'Shift+H toggle help cards', 'Shift+D detach from task']},
|
|
585
585
|
{label: 'Management', color: 'cyan', body: ['Shift+P Package Registry', 'Shift+N Project Architect', 'Shift+X clear / Shift+E export']},
|
|
586
|
-
{label: 'Orbit & AI', color: 'yellow', body: ['Shift+T
|
|
586
|
+
{label: 'Orbit & AI', color: 'yellow', body: ['Shift+T: Tasks, Shift+O: AI, 0: Analyze', '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
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.'))
|
|
@@ -622,7 +622,6 @@ async function main() {
|
|
|
622
622
|
return;
|
|
623
623
|
}
|
|
624
624
|
if (args.help) {
|
|
625
|
-
console.clear();
|
|
626
625
|
console.log(kleur.bold(kleur.magenta('🧭 Project Compass · Premium Developer Cockpit')));
|
|
627
626
|
console.log(kleur.dim('───────────────────────────────────────────────────'));
|
|
628
627
|
console.log('');
|
|
@@ -5,10 +5,10 @@ import {Box, Text, useInput} from 'ink';
|
|
|
5
5
|
const create = React.createElement;
|
|
6
6
|
|
|
7
7
|
const AI_PROVIDERS = [
|
|
8
|
-
{ id: 'openrouter', name: 'OpenRouter', endpoint: 'https://openrouter.ai/api/v1'
|
|
9
|
-
{ id: 'gemini', name: 'Google Gemini', endpoint: 'https://generativelanguage.googleapis.com'
|
|
10
|
-
{ id: 'claude', name: 'Anthropic Claude', endpoint: 'https://api.anthropic.com'
|
|
11
|
-
{ id: 'ollama', name: 'Ollama (Local)', endpoint: 'http://localhost:11434'
|
|
8
|
+
{ id: 'openrouter', name: 'OpenRouter', endpoint: 'https://openrouter.ai/api/v1' },
|
|
9
|
+
{ id: 'gemini', name: 'Google Gemini', endpoint: 'https://generativelanguage.googleapis.com' },
|
|
10
|
+
{ id: 'claude', name: 'Anthropic Claude', endpoint: 'https://api.anthropic.com' },
|
|
11
|
+
{ id: 'ollama', name: 'Ollama (Local)', endpoint: 'http://localhost:11434' }
|
|
12
12
|
];
|
|
13
13
|
|
|
14
14
|
const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveConfig}) => {
|
|
@@ -18,6 +18,7 @@ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveCon
|
|
|
18
18
|
const [token, setToken] = useState(config?.aiToken || '');
|
|
19
19
|
const [cursor, setCursor] = useState(0);
|
|
20
20
|
const [status, setStatus] = useState('ready');
|
|
21
|
+
const [suggestions, setSuggestions] = useState([]);
|
|
21
22
|
|
|
22
23
|
useInput((input, key) => {
|
|
23
24
|
if (step === 'provider') {
|
|
@@ -25,18 +26,14 @@ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveCon
|
|
|
25
26
|
if (key.downArrow) setProviderIdx(p => (p + 1) % AI_PROVIDERS.length);
|
|
26
27
|
if (key.return) {
|
|
27
28
|
const nextConfig = { ...config, aiProvider: AI_PROVIDERS[providerIdx].id };
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
setStep('model');
|
|
31
|
-
setCursor(model.length);
|
|
29
|
+
setConfig(nextConfig); saveConfig(nextConfig);
|
|
30
|
+
setStep('model'); setCursor(model.length);
|
|
32
31
|
}
|
|
33
32
|
} else if (step === 'model') {
|
|
34
33
|
if (key.return) {
|
|
35
34
|
const nextConfig = { ...config, aiModel: model };
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
setStep('token');
|
|
39
|
-
setCursor(token.length);
|
|
35
|
+
setConfig(nextConfig); saveConfig(nextConfig);
|
|
36
|
+
setStep('token'); setCursor(token.length);
|
|
40
37
|
}
|
|
41
38
|
if (key.escape) setStep('provider');
|
|
42
39
|
if (key.backspace || key.delete) {
|
|
@@ -47,8 +44,7 @@ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveCon
|
|
|
47
44
|
} else if (step === 'token') {
|
|
48
45
|
if (key.return) {
|
|
49
46
|
const nextConfig = { ...config, aiToken: token };
|
|
50
|
-
|
|
51
|
-
if (saveConfig) saveConfig(nextConfig);
|
|
47
|
+
setConfig(nextConfig); saveConfig(nextConfig);
|
|
52
48
|
setStep('analyze');
|
|
53
49
|
}
|
|
54
50
|
if (key.escape) setStep('model');
|
|
@@ -61,31 +57,39 @@ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveCon
|
|
|
61
57
|
if (key.return && status === 'ready' && selectedProject) {
|
|
62
58
|
setStatus('busy');
|
|
63
59
|
setTimeout(() => {
|
|
60
|
+
// REAL DNA MAPPING: Check project scripts and suggest real matches
|
|
61
|
+
const scripts = selectedProject.metadata?.scripts || {};
|
|
62
|
+
const suggested = [];
|
|
63
|
+
|
|
64
|
+
if (scripts.build) suggested.push({ label: 'AI Build', command: ['npm', 'run', 'build'] });
|
|
65
|
+
if (scripts.start || scripts.dev) suggested.push({ label: 'AI Run', command: ['npm', 'run', scripts.dev ? 'dev' : 'start'] });
|
|
66
|
+
if (scripts.test) suggested.push({ label: 'AI Test', command: ['npm', 'test'] });
|
|
67
|
+
|
|
68
|
+
// If no scripts found, suggest generic ones based on type
|
|
69
|
+
if (suggested.length === 0) {
|
|
70
|
+
if (selectedProject.type === 'Node.js') suggested.push({ label: 'AI Init', command: ['npm', 'install'] });
|
|
71
|
+
else if (selectedProject.type === 'Python') suggested.push({ label: 'AI Run', command: ['python', 'main.py'] });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setSuggestions(suggested);
|
|
64
75
|
const projectKey = selectedProject.path;
|
|
65
76
|
const currentCustom = config.customCommands?.[projectKey] || [];
|
|
66
77
|
const nextConfig = {
|
|
67
78
|
...config,
|
|
68
|
-
customCommands: {
|
|
69
|
-
...config.customCommands,
|
|
70
|
-
[projectKey]: [...currentCustom, { label: 'AI: Optimized Run', command: ['npm', 'run', 'dev'] }]
|
|
71
|
-
}
|
|
79
|
+
customCommands: { ...config.customCommands, [projectKey]: [...currentCustom, ...suggested] }
|
|
72
80
|
};
|
|
73
|
-
|
|
74
|
-
if (saveConfig) saveConfig(nextConfig);
|
|
81
|
+
setConfig(nextConfig); saveConfig(nextConfig);
|
|
75
82
|
setStatus('done');
|
|
76
|
-
},
|
|
83
|
+
}, 1200);
|
|
77
84
|
}
|
|
78
85
|
if (input === 'r') {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
if (saveConfig) saveConfig(resetConfig);
|
|
86
|
+
const nextConfig = { ...config, aiToken: '' };
|
|
87
|
+
setConfig(nextConfig); saveConfig(nextConfig);
|
|
82
88
|
setStep('provider');
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
});
|
|
86
92
|
|
|
87
|
-
const currentProvider = AI_PROVIDERS[providerIdx];
|
|
88
|
-
|
|
89
93
|
return create(
|
|
90
94
|
Box,
|
|
91
95
|
{flexDirection: 'column', borderStyle: 'double', borderColor: 'magenta', padding: 1, width: '100%'},
|
|
@@ -95,7 +99,7 @@ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveCon
|
|
|
95
99
|
Box,
|
|
96
100
|
{flexDirection: 'column'},
|
|
97
101
|
create(Text, {bold: true, marginBottom: 1}, 'Step 1: Select AI Infrastructure'),
|
|
98
|
-
...AI_PROVIDERS.map((p, i) => create(Text, {key: p.id, color: i === providerIdx ? 'cyan' : 'white'}, (i === providerIdx ? '→ ' : ' ') + p.name
|
|
102
|
+
...AI_PROVIDERS.map((p, i) => create(Text, {key: p.id, color: i === providerIdx ? 'cyan' : 'white'}, (i === providerIdx ? '→ ' : ' ') + p.name)),
|
|
99
103
|
create(Text, {dimColor: true, marginTop: 1}, 'Enter: Save & Next')
|
|
100
104
|
),
|
|
101
105
|
|
|
@@ -107,36 +111,36 @@ const AIHorizon = memo(({selectedProject, CursorText, config, setConfig, saveCon
|
|
|
107
111
|
create(Text, null, 'Model ID: '),
|
|
108
112
|
create(CursorText, {value: model, cursorIndex: cursor})
|
|
109
113
|
),
|
|
110
|
-
create(Text, {dimColor: true, marginTop: 1}, 'Enter: Save, Esc: Back')
|
|
114
|
+
create(Text, {dimColor: true, marginTop: 1}, 'Enter: Save Model, Esc: Back')
|
|
111
115
|
),
|
|
112
116
|
|
|
113
117
|
step === 'token' && create(
|
|
114
118
|
Box,
|
|
115
119
|
{flexDirection: 'column'},
|
|
116
|
-
create(Text, {bold: true, color: 'red', marginBottom: 1}, 'Step 3:
|
|
117
|
-
create(
|
|
118
|
-
|
|
119
|
-
create(Text, null, 'API Token: '),
|
|
120
|
+
create(Text, {bold: true, color: 'red', marginBottom: 1}, 'Step 3: API Token Authorization'),
|
|
121
|
+
create(Box, {flexDirection: 'row'},
|
|
122
|
+
create(Text, null, 'Token: '),
|
|
120
123
|
create(CursorText, {value: '*'.repeat(token.length), cursorIndex: cursor})
|
|
121
124
|
),
|
|
122
|
-
create(Text, {dimColor: true, marginTop: 1}, 'Enter:
|
|
125
|
+
create(Text, {dimColor: true, marginTop: 1}, 'Enter: Save Token, Esc: Back')
|
|
123
126
|
),
|
|
124
127
|
|
|
125
128
|
step === 'analyze' && create(
|
|
126
129
|
Box,
|
|
127
130
|
{flexDirection: 'column'},
|
|
128
|
-
create(Text, {bold: true, color: 'cyan', marginBottom: 1}, '
|
|
129
|
-
create(Text, {dimColor: true}, '
|
|
131
|
+
create(Text, {bold: true, color: 'cyan', marginBottom: 1}, 'Ready to analyze: ' + (selectedProject ? selectedProject.name : 'No project selected')),
|
|
132
|
+
create(Text, {dimColor: true}, 'Active: ' + config.aiProvider + ' (' + config.aiModel + ')'),
|
|
133
|
+
|
|
130
134
|
create(Box, {marginTop: 1, flexDirection: 'column'},
|
|
131
|
-
status === 'ready' && create(Text, null, 'Press Enter to
|
|
132
|
-
status === 'busy' && create(Text, {color: 'yellow'}, ' ⏳
|
|
135
|
+
status === 'ready' && create(Text, null, 'Press Enter to map project DNA and auto-configure macros.'),
|
|
136
|
+
status === 'busy' && create(Text, {color: 'yellow'}, ' ⏳ Reading manifests... identifying build patterns...'),
|
|
133
137
|
status === 'done' && create(Box, {flexDirection: 'column'},
|
|
134
138
|
create(Text, {color: 'green', bold: true}, ' ✅ DNA Mapped!'),
|
|
135
|
-
create(Text, null, '
|
|
136
|
-
create(Text, {dimColor: true, marginTop: 1}, '
|
|
139
|
+
create(Text, null, ' Identified ' + suggestions.length + ' valid commands based on your workspace structure.'),
|
|
140
|
+
create(Text, {dimColor: true, marginTop: 1}, 'Return to Navigator to use BRIT shortcuts.')
|
|
137
141
|
)
|
|
138
142
|
),
|
|
139
|
-
create(Text, {dimColor: true, marginTop: 1}, 'Esc:
|
|
143
|
+
create(Text, {dimColor: true, marginTop: 1}, 'Esc: Return, R: Reset Credentials')
|
|
140
144
|
)
|
|
141
145
|
);
|
|
142
146
|
});
|