@geminilight/mindos 0.6.25 → 0.7.0
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/README.md +19 -3
- package/README_zh.md +19 -3
- package/app/app/api/a2a/discover/route.ts +23 -0
- package/app/components/CreateSpaceModal.tsx +1 -0
- package/app/components/ImportModal.tsx +3 -0
- package/app/components/OnboardingView.tsx +1 -0
- package/app/components/RightAskPanel.tsx +4 -2
- package/app/components/SidebarLayout.tsx +11 -2
- package/app/components/agents/DiscoverAgentModal.tsx +149 -0
- package/app/components/ask/AskContent.tsx +21 -9
- package/app/components/ask/SessionTabBar.tsx +70 -0
- package/app/components/echo/EchoInsightCollapsible.tsx +4 -0
- package/app/components/panels/AgentsPanel.tsx +25 -2
- package/app/components/renderers/workflow/WorkflowRenderer.tsx +5 -0
- package/app/components/settings/AiTab.tsx +1 -0
- package/app/components/settings/KnowledgeTab.tsx +2 -0
- package/app/components/settings/SyncTab.tsx +2 -0
- package/app/components/setup/StepDots.tsx +5 -1
- package/app/hooks/useA2aRegistry.ts +53 -0
- package/app/hooks/useAskSession.ts +44 -25
- package/app/lib/a2a/a2a-tools.ts +212 -0
- package/app/lib/a2a/client.ts +207 -0
- package/app/lib/a2a/index.ts +8 -0
- package/app/lib/a2a/orchestrator.ts +255 -0
- package/app/lib/a2a/types.ts +54 -0
- package/app/lib/agent/tools.ts +6 -4
- package/app/lib/i18n-en.ts +52 -0
- package/app/lib/i18n-zh.ts +52 -0
- package/app/next-env.d.ts +1 -1
- package/bin/cli.js +180 -171
- package/bin/commands/agent.js +110 -18
- package/bin/commands/api.js +5 -3
- package/bin/commands/ask.js +3 -3
- package/bin/commands/file.js +13 -13
- package/bin/commands/search.js +2 -2
- package/bin/commands/space.js +64 -10
- package/bin/lib/command.js +10 -0
- package/package.json +1 -1
package/bin/commands/agent.js
CHANGED
|
@@ -1,18 +1,110 @@
|
|
|
1
|
-
import{bold,dim,cyan,green,red,yellow}from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { bold, dim, cyan, green, red, yellow } from '../lib/colors.js';
|
|
2
|
+
import { MCP_AGENTS, detectAgentPresence } from '../lib/mcp-agents.js';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { output, isJsonMode, EXIT } from '../lib/command.js';
|
|
7
|
+
|
|
8
|
+
function expandHome(p) {
|
|
9
|
+
return p.startsWith('~/') ? resolve(homedir(), p.slice(2)) : p;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const meta = {
|
|
13
|
+
name: 'agent',
|
|
14
|
+
group: 'Knowledge',
|
|
15
|
+
summary: 'AI Agent management (list/info)',
|
|
16
|
+
usage: 'mindos agent <subcommand>',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export async function run(args, flags) {
|
|
20
|
+
const sub = args[0];
|
|
21
|
+
if (!sub || flags.help || flags.h) {
|
|
22
|
+
console.log(bold('mindos agent') + ' — AI Agent management\n');
|
|
23
|
+
console.log('Subcommands:');
|
|
24
|
+
console.log(' list List detected AI agents');
|
|
25
|
+
console.log(' info <agent-key> Show agent details\n');
|
|
26
|
+
console.log('Keys: ' + Object.keys(MCP_AGENTS).join(', '));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (sub === 'list' || sub === 'ls') return agentList(flags);
|
|
30
|
+
if (sub === 'info') return agentInfo(args[1], flags);
|
|
31
|
+
console.error(red('Unknown subcommand: ' + sub));
|
|
32
|
+
process.exit(EXIT.ARGS);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function hasMindosConfig(agent) {
|
|
36
|
+
const paths = [agent.global, agent.project].filter(Boolean).map(expandHome);
|
|
37
|
+
for (const p of paths) {
|
|
38
|
+
try {
|
|
39
|
+
if (!existsSync(p)) continue;
|
|
40
|
+
const raw = readFileSync(p, 'utf-8')
|
|
41
|
+
.replace(/\/\/.*$/gm, '')
|
|
42
|
+
.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
43
|
+
const data = JSON.parse(raw);
|
|
44
|
+
const servers = data[agent.key] || {};
|
|
45
|
+
if (Object.keys(servers).some(k => k.toLowerCase().includes('mindos'))) return true;
|
|
46
|
+
} catch { /* skip */ }
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function agentList(flags) {
|
|
52
|
+
const agents = [];
|
|
53
|
+
for (const [key, agent] of Object.entries(MCP_AGENTS)) {
|
|
54
|
+
if (!detectAgentPresence(key)) continue;
|
|
55
|
+
agents.push({ key, name: agent.name, installed: true, mindosConnected: hasMindosConfig(agent) });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (isJsonMode(flags)) {
|
|
59
|
+
output({ count: agents.length, agents }, flags);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (agents.length === 0) {
|
|
64
|
+
console.log(dim('No AI agents detected.'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log('\n' + bold('Detected Agents (' + agents.length + '):') + '\n');
|
|
69
|
+
for (const a of agents) {
|
|
70
|
+
const st = a.mindosConnected ? green('● connected') : dim('○ not connected');
|
|
71
|
+
console.log(' ' + a.name.padEnd(20) + ' ' + st);
|
|
72
|
+
}
|
|
73
|
+
console.log('\n' + dim('Connect: mindos mcp install <agent-key>') + '\n');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function agentInfo(key, flags) {
|
|
77
|
+
if (!key) {
|
|
78
|
+
console.error(red('Usage: mindos agent info <agent-key>'));
|
|
79
|
+
process.exit(EXIT.ERROR);
|
|
80
|
+
}
|
|
81
|
+
const agent = MCP_AGENTS[key];
|
|
82
|
+
if (!agent) {
|
|
83
|
+
console.error(red('Unknown agent: ' + key));
|
|
84
|
+
process.exit(EXIT.ERROR);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const installed = detectAgentPresence(key);
|
|
88
|
+
const connected = installed ? hasMindosConfig(agent) : false;
|
|
89
|
+
const info = {
|
|
90
|
+
key,
|
|
91
|
+
name: agent.name,
|
|
92
|
+
installed,
|
|
93
|
+
mindosConnected: connected,
|
|
94
|
+
transport: agent.preferredTransport,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
if (isJsonMode(flags)) {
|
|
98
|
+
output(info, flags);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log('\n' + bold(agent.name));
|
|
103
|
+
console.log(' Key: ' + key);
|
|
104
|
+
console.log(' Installed: ' + (installed ? green('yes') : red('no')));
|
|
105
|
+
console.log(' MindOS: ' + (connected ? green('connected') : yellow('not connected')));
|
|
106
|
+
console.log(' Transport: ' + agent.preferredTransport);
|
|
107
|
+
if (agent.global) console.log(' Config: ' + expandHome(agent.global));
|
|
108
|
+
if (!connected && installed) console.log('\n Connect: mindos mcp install ' + key);
|
|
109
|
+
console.log('');
|
|
110
|
+
}
|
package/bin/commands/api.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { bold, dim, cyan, red } from '../lib/colors.js';
|
|
2
2
|
import { loadConfig } from '../lib/config.js';
|
|
3
|
+
import { EXIT } from '../lib/command.js';
|
|
3
4
|
|
|
4
5
|
export const meta = {
|
|
5
6
|
name: 'api',
|
|
@@ -23,7 +24,7 @@ export async function run(args, flags) {
|
|
|
23
24
|
const method = args[0].toUpperCase();
|
|
24
25
|
if (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
|
|
25
26
|
console.error(red('Invalid method: ' + args[0]));
|
|
26
|
-
process.exit(
|
|
27
|
+
process.exit(EXIT.ARGS);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
let apiPath = args[1];
|
|
@@ -46,13 +47,14 @@ export async function run(args, flags) {
|
|
|
46
47
|
} else {
|
|
47
48
|
console.log(await res.text());
|
|
48
49
|
}
|
|
49
|
-
if (!res.ok) process.exit(
|
|
50
|
+
if (!res.ok) process.exit(EXIT.ERROR);
|
|
50
51
|
} catch (err) {
|
|
51
52
|
if (err.cause && err.cause.code === 'ECONNREFUSED') {
|
|
52
53
|
console.error(red('Connection refused. Start with: mindos start'));
|
|
54
|
+
process.exit(EXIT.CONNECT);
|
|
53
55
|
} else {
|
|
54
56
|
console.error(red('Request failed: ' + err.message));
|
|
57
|
+
process.exit(EXIT.ERROR);
|
|
55
58
|
}
|
|
56
|
-
process.exit(1);
|
|
57
59
|
}
|
|
58
60
|
}
|
package/bin/commands/ask.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { bold, dim, cyan, green, red } from '../lib/colors.js';
|
|
6
6
|
import { loadConfig } from '../lib/config.js';
|
|
7
|
-
import { output, isJsonMode } from '../lib/command.js';
|
|
7
|
+
import { output, isJsonMode, EXIT } from '../lib/command.js';
|
|
8
8
|
|
|
9
9
|
export const meta = {
|
|
10
10
|
name: 'ask',
|
|
@@ -52,7 +52,7 @@ ${bold('Note:')} MindOS must be running (mindos start).
|
|
|
52
52
|
if (!healthRes.ok) throw new Error();
|
|
53
53
|
} catch {
|
|
54
54
|
console.error(red('MindOS is not running. Start it with: mindos start'));
|
|
55
|
-
process.exit(
|
|
55
|
+
process.exit(EXIT.ERROR);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (!isJsonMode(flags)) {
|
|
@@ -96,6 +96,6 @@ ${bold('Note:')} MindOS must be running (mindos start).
|
|
|
96
96
|
process.stdout.write('\r' + ' '.repeat(40) + '\r');
|
|
97
97
|
}
|
|
98
98
|
console.error(red(err.message));
|
|
99
|
-
process.exit(
|
|
99
|
+
process.exit(EXIT.ERROR);
|
|
100
100
|
}
|
|
101
101
|
}
|
package/bin/commands/file.js
CHANGED
|
@@ -9,14 +9,14 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync, renameSync, mkdirS
|
|
|
9
9
|
import { resolve, basename, dirname, relative } from 'node:path';
|
|
10
10
|
import { bold, dim, cyan, green, red, yellow } from '../lib/colors.js';
|
|
11
11
|
import { loadConfig } from '../lib/config.js';
|
|
12
|
-
import { output, isJsonMode } from '../lib/command.js';
|
|
12
|
+
import { output, isJsonMode, EXIT } from '../lib/command.js';
|
|
13
13
|
|
|
14
14
|
function getMindRoot() {
|
|
15
15
|
loadConfig();
|
|
16
16
|
const root = process.env.MIND_ROOT;
|
|
17
17
|
if (!root || !existsSync(root)) {
|
|
18
18
|
console.error(red('Mind root not configured. Run `mindos onboard` first.'));
|
|
19
|
-
process.exit(
|
|
19
|
+
process.exit(EXIT.ERROR);
|
|
20
20
|
}
|
|
21
21
|
return root;
|
|
22
22
|
}
|
|
@@ -71,7 +71,7 @@ export async function run(args, flags) {
|
|
|
71
71
|
default:
|
|
72
72
|
console.error(red(`Unknown subcommand: ${sub}`));
|
|
73
73
|
console.error(dim('Available: list, read, create, delete, rename, move, search'));
|
|
74
|
-
process.exit(
|
|
74
|
+
process.exit(EXIT.ERROR);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -150,12 +150,12 @@ function fileList(root, _args, flags) {
|
|
|
150
150
|
function fileRead(root, filePath, flags) {
|
|
151
151
|
if (!filePath) {
|
|
152
152
|
console.error(red('Usage: mindos file read <path>'));
|
|
153
|
-
process.exit(
|
|
153
|
+
process.exit(EXIT.ERROR);
|
|
154
154
|
}
|
|
155
155
|
const full = resolvePath(root, filePath);
|
|
156
156
|
if (!existsSync(full)) {
|
|
157
157
|
console.error(red(`File not found: ${filePath}`));
|
|
158
|
-
process.exit(
|
|
158
|
+
process.exit(EXIT.ERROR);
|
|
159
159
|
}
|
|
160
160
|
const content = readFileSync(full, 'utf-8');
|
|
161
161
|
|
|
@@ -169,13 +169,13 @@ function fileRead(root, filePath, flags) {
|
|
|
169
169
|
function fileCreate(root, filePath, flags) {
|
|
170
170
|
if (!filePath) {
|
|
171
171
|
console.error(red('Usage: mindos file create <path> --content "..."'));
|
|
172
|
-
process.exit(
|
|
172
|
+
process.exit(EXIT.ERROR);
|
|
173
173
|
}
|
|
174
174
|
const full = resolvePath(root, filePath);
|
|
175
175
|
if (existsSync(full) && !flags.force) {
|
|
176
176
|
console.error(red(`File already exists: ${filePath}`));
|
|
177
177
|
console.error(dim('Use --force to overwrite.'));
|
|
178
|
-
process.exit(
|
|
178
|
+
process.exit(EXIT.ERROR);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
const content = flags.content || `# ${basename(filePath, '.md')}\n`;
|
|
@@ -192,12 +192,12 @@ function fileCreate(root, filePath, flags) {
|
|
|
192
192
|
function fileDelete(root, filePath, flags) {
|
|
193
193
|
if (!filePath) {
|
|
194
194
|
console.error(red('Usage: mindos file delete <path>'));
|
|
195
|
-
process.exit(
|
|
195
|
+
process.exit(EXIT.ERROR);
|
|
196
196
|
}
|
|
197
197
|
const full = resolvePath(root, filePath);
|
|
198
198
|
if (!existsSync(full)) {
|
|
199
199
|
console.error(red(`File not found: ${filePath}`));
|
|
200
|
-
process.exit(
|
|
200
|
+
process.exit(EXIT.ERROR);
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
unlinkSync(full);
|
|
@@ -212,18 +212,18 @@ function fileDelete(root, filePath, flags) {
|
|
|
212
212
|
function fileRename(root, oldPath, newPath, flags) {
|
|
213
213
|
if (!oldPath || !newPath) {
|
|
214
214
|
console.error(red('Usage: mindos file rename <old-path> <new-path>'));
|
|
215
|
-
process.exit(
|
|
215
|
+
process.exit(EXIT.ERROR);
|
|
216
216
|
}
|
|
217
217
|
const fullOld = resolvePath(root, oldPath);
|
|
218
218
|
const fullNew = resolvePath(root, newPath);
|
|
219
219
|
|
|
220
220
|
if (!existsSync(fullOld)) {
|
|
221
221
|
console.error(red(`File not found: ${oldPath}`));
|
|
222
|
-
process.exit(
|
|
222
|
+
process.exit(EXIT.ERROR);
|
|
223
223
|
}
|
|
224
224
|
if (existsSync(fullNew) && !flags.force) {
|
|
225
225
|
console.error(red(`Target already exists: ${newPath}`));
|
|
226
|
-
process.exit(
|
|
226
|
+
process.exit(EXIT.ERROR);
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
mkdirSync(dirname(fullNew), { recursive: true });
|
|
@@ -239,7 +239,7 @@ function fileRename(root, oldPath, newPath, flags) {
|
|
|
239
239
|
function fileSearch(root, query, flags) {
|
|
240
240
|
if (!query) {
|
|
241
241
|
console.error(red('Usage: mindos file search <query>'));
|
|
242
|
-
process.exit(
|
|
242
|
+
process.exit(EXIT.ERROR);
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
const files = walkFiles(root, root);
|
package/bin/commands/search.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { bold, dim, cyan, red } from '../lib/colors.js';
|
|
2
2
|
import { loadConfig } from '../lib/config.js';
|
|
3
|
-
import { output, isJsonMode } from '../lib/command.js';
|
|
3
|
+
import { output, isJsonMode, EXIT } from '../lib/command.js';
|
|
4
4
|
|
|
5
5
|
export const meta = {
|
|
6
6
|
name: 'search', group: 'Knowledge',
|
|
@@ -46,6 +46,6 @@ export async function run(args, flags) {
|
|
|
46
46
|
} catch (err) {
|
|
47
47
|
if (err.cause && err.cause.code === 'ECONNREFUSED') { console.error(red('MindOS not running. Offline: mindos file search "' + query + '"')); }
|
|
48
48
|
else { console.error(red(err.message)); }
|
|
49
|
-
process.exit(
|
|
49
|
+
process.exit(EXIT.ERROR);
|
|
50
50
|
}
|
|
51
51
|
}
|
package/bin/commands/space.js
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
* mindos space — Mind Space management
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync, rmSync, renameSync } from 'node:fs';
|
|
6
6
|
import { resolve, relative } from 'node:path';
|
|
7
7
|
import { bold, dim, cyan, green, red } from '../lib/colors.js';
|
|
8
8
|
import { loadConfig } from '../lib/config.js';
|
|
9
|
-
import { output, isJsonMode } from '../lib/command.js';
|
|
9
|
+
import { output, isJsonMode, EXIT } from '../lib/command.js';
|
|
10
10
|
|
|
11
11
|
function getMindRoot() {
|
|
12
12
|
loadConfig();
|
|
13
13
|
const root = process.env.MIND_ROOT;
|
|
14
14
|
if (!root || !existsSync(root)) {
|
|
15
15
|
console.error(red('Mind root not configured. Run `mindos onboard` first.'));
|
|
16
|
-
process.exit(
|
|
16
|
+
process.exit(EXIT.ERROR);
|
|
17
17
|
}
|
|
18
18
|
return root;
|
|
19
19
|
}
|
|
@@ -21,12 +21,14 @@ function getMindRoot() {
|
|
|
21
21
|
export const meta = {
|
|
22
22
|
name: 'space',
|
|
23
23
|
group: 'Knowledge',
|
|
24
|
-
summary: 'Mind Space management (list, create, info)',
|
|
24
|
+
summary: 'Mind Space management (list, create, delete, rename, info)',
|
|
25
25
|
usage: 'mindos space <subcommand>',
|
|
26
26
|
examples: [
|
|
27
27
|
'mindos space list',
|
|
28
28
|
'mindos space list --json',
|
|
29
29
|
'mindos space create "Research"',
|
|
30
|
+
'mindos space delete "Old Project"',
|
|
31
|
+
'mindos space rename "Old" "New"',
|
|
30
32
|
'mindos space info "Work"',
|
|
31
33
|
],
|
|
32
34
|
};
|
|
@@ -42,11 +44,15 @@ ${bold('mindos space')} — Mind Space management
|
|
|
42
44
|
${bold('Subcommands:')}
|
|
43
45
|
${cyan('list'.padEnd(20))}${dim('List all spaces')}
|
|
44
46
|
${cyan('create <name>'.padEnd(20))}${dim('Create a new space')}
|
|
47
|
+
${cyan('delete <name>'.padEnd(20))}${dim('Delete a space and all its files')}
|
|
48
|
+
${cyan('rename <old> <new>'.padEnd(20))}${dim('Rename a space')}
|
|
45
49
|
${cyan('info <name>'.padEnd(20))}${dim('Show space details')}
|
|
46
50
|
|
|
47
51
|
${bold('Examples:')}
|
|
48
52
|
${dim('mindos space list')}
|
|
49
53
|
${dim('mindos space create "Research"')}
|
|
54
|
+
${dim('mindos space delete "Old Project"')}
|
|
55
|
+
${dim('mindos space rename "Old" "New"')}
|
|
50
56
|
`);
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
@@ -55,11 +61,13 @@ ${bold('Examples:')}
|
|
|
55
61
|
case 'list': return spaceList(root, flags);
|
|
56
62
|
case 'ls': return spaceList(root, flags);
|
|
57
63
|
case 'create': return spaceCreate(root, args[1], flags);
|
|
64
|
+
case 'delete': case 'rm': return spaceDelete(root, args[1], flags);
|
|
65
|
+
case 'rename': case 'mv': return spaceRename(root, args[1], args[2], flags);
|
|
58
66
|
case 'info': return spaceInfo(root, args[1], flags);
|
|
59
67
|
default:
|
|
60
68
|
console.error(red(`Unknown subcommand: ${sub}`));
|
|
61
|
-
console.error(dim('Available: list, create, info'));
|
|
62
|
-
process.exit(
|
|
69
|
+
console.error(dim('Available: list, create, delete, rename, info'));
|
|
70
|
+
process.exit(EXIT.ERROR);
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -114,12 +122,12 @@ function spaceList(root, flags) {
|
|
|
114
122
|
function spaceCreate(root, name, flags) {
|
|
115
123
|
if (!name) {
|
|
116
124
|
console.error(red('Usage: mindos space create <name>'));
|
|
117
|
-
process.exit(
|
|
125
|
+
process.exit(EXIT.ERROR);
|
|
118
126
|
}
|
|
119
127
|
const dir = resolve(root, name);
|
|
120
128
|
if (existsSync(dir)) {
|
|
121
129
|
console.error(red(`Space already exists: ${name}`));
|
|
122
|
-
process.exit(
|
|
130
|
+
process.exit(EXIT.ERROR);
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
mkdirSync(dir, { recursive: true });
|
|
@@ -132,15 +140,61 @@ function spaceCreate(root, name, flags) {
|
|
|
132
140
|
console.log(`${green('✔')} Created space: ${cyan(name)}`);
|
|
133
141
|
}
|
|
134
142
|
|
|
143
|
+
function spaceDelete(root, name, flags) {
|
|
144
|
+
if (!name) {
|
|
145
|
+
console.error(red('Usage: mindos space delete <name>'));
|
|
146
|
+
process.exit(EXIT.ERROR);
|
|
147
|
+
}
|
|
148
|
+
const dir = resolve(root, name);
|
|
149
|
+
if (!existsSync(dir)) {
|
|
150
|
+
console.error(red(`Space not found: ${name}`));
|
|
151
|
+
process.exit(EXIT.ERROR);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const fileCount = countFiles(dir);
|
|
155
|
+
rmSync(dir, { recursive: true, force: true });
|
|
156
|
+
|
|
157
|
+
if (isJsonMode(flags)) {
|
|
158
|
+
output({ ok: true, name, deletedFiles: fileCount }, flags);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
console.log(`${green('✔')} Deleted space: ${cyan(name)} (${fileCount} files removed)`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function spaceRename(root, oldName, newName, flags) {
|
|
165
|
+
if (!oldName || !newName) {
|
|
166
|
+
console.error(red('Usage: mindos space rename <old-name> <new-name>'));
|
|
167
|
+
process.exit(EXIT.ERROR);
|
|
168
|
+
}
|
|
169
|
+
const oldDir = resolve(root, oldName);
|
|
170
|
+
const newDir = resolve(root, newName);
|
|
171
|
+
if (!existsSync(oldDir)) {
|
|
172
|
+
console.error(red(`Space not found: ${oldName}`));
|
|
173
|
+
process.exit(EXIT.ERROR);
|
|
174
|
+
}
|
|
175
|
+
if (existsSync(newDir)) {
|
|
176
|
+
console.error(red(`Target already exists: ${newName}`));
|
|
177
|
+
process.exit(EXIT.ERROR);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
renameSync(oldDir, newDir);
|
|
181
|
+
|
|
182
|
+
if (isJsonMode(flags)) {
|
|
183
|
+
output({ ok: true, from: oldName, to: newName }, flags);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
console.log(`${green('✔')} Renamed space: ${cyan(oldName)} → ${cyan(newName)}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
135
189
|
function spaceInfo(root, name, flags) {
|
|
136
190
|
if (!name) {
|
|
137
191
|
console.error(red('Usage: mindos space info <name>'));
|
|
138
|
-
process.exit(
|
|
192
|
+
process.exit(EXIT.ERROR);
|
|
139
193
|
}
|
|
140
194
|
const dir = resolve(root, name);
|
|
141
195
|
if (!existsSync(dir)) {
|
|
142
196
|
console.error(red(`Space not found: ${name}`));
|
|
143
|
-
process.exit(
|
|
197
|
+
process.exit(EXIT.ERROR);
|
|
144
198
|
}
|
|
145
199
|
|
|
146
200
|
const fileCount = countFiles(dir);
|
package/bin/lib/command.js
CHANGED
|
@@ -16,6 +16,16 @@ import { ROOT } from './constants.js';
|
|
|
16
16
|
import { readFileSync } from 'node:fs';
|
|
17
17
|
import { resolve } from 'node:path';
|
|
18
18
|
|
|
19
|
+
// ── Exit codes ────────────────────────────────────────────────────────────────
|
|
20
|
+
// Standardized exit codes for CLI commands. Use these instead of raw numbers.
|
|
21
|
+
export const EXIT = {
|
|
22
|
+
OK: 0, // Success
|
|
23
|
+
ERROR: 1, // General error
|
|
24
|
+
ARGS: 2, // Invalid arguments or usage
|
|
25
|
+
CONNECT: 3, // Connection refused / service not running
|
|
26
|
+
NOT_FOUND: 4, // Resource not found (file, agent, etc.)
|
|
27
|
+
};
|
|
28
|
+
|
|
19
29
|
/** @type {Map<string, { meta: object, run: function }>} */
|
|
20
30
|
const registry = new Map();
|
|
21
31
|
|
package/package.json
CHANGED