@geminilight/mindos 0.6.22 → 0.6.25
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 +58 -46
- package/README_zh.md +58 -46
- package/app/app/.well-known/agent-card.json/route.ts +34 -0
- package/app/app/api/a2a/route.ts +100 -0
- package/app/app/api/file/import/route.ts +0 -2
- package/app/app/api/setup/route.ts +2 -0
- package/app/components/Backlinks.tsx +2 -2
- package/app/components/Breadcrumb.tsx +1 -1
- package/app/components/CsvView.tsx +41 -19
- package/app/components/DirView.tsx +2 -2
- package/app/components/FileTree.tsx +14 -1
- package/app/components/GuideCard.tsx +6 -2
- package/app/components/HomeContent.tsx +2 -2
- package/app/components/RightAskPanel.tsx +17 -10
- package/app/components/SearchModal.tsx +3 -3
- package/app/components/SidebarLayout.tsx +4 -2
- package/app/components/SyncStatusBar.tsx +2 -2
- package/app/components/ask/AskContent.tsx +6 -6
- package/app/components/ask/FileChip.tsx +1 -1
- package/app/components/ask/MentionPopover.tsx +2 -2
- package/app/components/ask/MessageList.tsx +1 -1
- package/app/components/ask/SlashCommandPopover.tsx +1 -1
- package/app/components/explore/UseCaseCard.tsx +2 -2
- package/app/components/help/HelpContent.tsx +6 -1
- package/app/components/panels/AgentsPanelAgentDetail.tsx +2 -2
- package/app/components/panels/DiscoverPanel.tsx +3 -3
- package/app/components/panels/PanelNavRow.tsx +2 -2
- package/app/components/panels/PluginsPanel.tsx +1 -1
- package/app/components/panels/SearchPanel.tsx +3 -3
- package/app/components/renderers/summary/SummaryRenderer.tsx +1 -1
- package/app/components/settings/AiTab.tsx +4 -4
- package/app/components/settings/KnowledgeTab.tsx +1 -1
- package/app/components/settings/McpTab.tsx +22 -4
- package/app/components/settings/UpdateTab.tsx +1 -1
- package/app/components/setup/index.tsx +9 -3
- package/app/components/walkthrough/WalkthroughProvider.tsx +2 -2
- package/app/hooks/useAskPanel.ts +7 -3
- package/app/hooks/useFileImport.ts +1 -1
- package/app/lib/a2a/agent-card.ts +107 -0
- package/app/lib/a2a/index.ts +23 -0
- package/app/lib/a2a/task-handler.ts +228 -0
- package/app/lib/a2a/types.ts +158 -0
- package/app/lib/agent/tools.ts +1 -1
- package/app/lib/core/fs-ops.ts +3 -2
- package/app/lib/fs.ts +28 -11
- package/app/lib/i18n-en.ts +2 -0
- package/app/lib/i18n-zh.ts +2 -0
- package/app/lib/settings.ts +1 -1
- package/bin/cli.js +48 -20
- package/bin/commands/agent.js +18 -0
- package/bin/commands/api.js +58 -0
- package/bin/commands/ask.js +101 -0
- package/bin/commands/file.js +286 -0
- package/bin/commands/search.js +51 -0
- package/bin/commands/space.js +167 -0
- package/bin/commands/status.js +69 -0
- package/bin/lib/command.js +156 -0
- package/mcp/dist/index.cjs +1 -1
- package/mcp/src/index.ts +1 -1
- package/package.json +1 -1
- package/skills/mindos/SKILL.md +2 -2
- package/skills/mindos-zh/SKILL.md +2 -2
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mindos space — Mind Space management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import { resolve, relative } from 'node:path';
|
|
7
|
+
import { bold, dim, cyan, green, red } from '../lib/colors.js';
|
|
8
|
+
import { loadConfig } from '../lib/config.js';
|
|
9
|
+
import { output, isJsonMode } from '../lib/command.js';
|
|
10
|
+
|
|
11
|
+
function getMindRoot() {
|
|
12
|
+
loadConfig();
|
|
13
|
+
const root = process.env.MIND_ROOT;
|
|
14
|
+
if (!root || !existsSync(root)) {
|
|
15
|
+
console.error(red('Mind root not configured. Run `mindos onboard` first.'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
return root;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const meta = {
|
|
22
|
+
name: 'space',
|
|
23
|
+
group: 'Knowledge',
|
|
24
|
+
summary: 'Mind Space management (list, create, info)',
|
|
25
|
+
usage: 'mindos space <subcommand>',
|
|
26
|
+
examples: [
|
|
27
|
+
'mindos space list',
|
|
28
|
+
'mindos space list --json',
|
|
29
|
+
'mindos space create "Research"',
|
|
30
|
+
'mindos space info "Work"',
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export async function run(args, flags) {
|
|
35
|
+
const sub = args[0];
|
|
36
|
+
const root = getMindRoot();
|
|
37
|
+
|
|
38
|
+
if (!sub || flags.help || flags.h) {
|
|
39
|
+
console.log(`
|
|
40
|
+
${bold('mindos space')} — Mind Space management
|
|
41
|
+
|
|
42
|
+
${bold('Subcommands:')}
|
|
43
|
+
${cyan('list'.padEnd(20))}${dim('List all spaces')}
|
|
44
|
+
${cyan('create <name>'.padEnd(20))}${dim('Create a new space')}
|
|
45
|
+
${cyan('info <name>'.padEnd(20))}${dim('Show space details')}
|
|
46
|
+
|
|
47
|
+
${bold('Examples:')}
|
|
48
|
+
${dim('mindos space list')}
|
|
49
|
+
${dim('mindos space create "Research"')}
|
|
50
|
+
`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
switch (sub) {
|
|
55
|
+
case 'list': return spaceList(root, flags);
|
|
56
|
+
case 'ls': return spaceList(root, flags);
|
|
57
|
+
case 'create': return spaceCreate(root, args[1], flags);
|
|
58
|
+
case 'info': return spaceInfo(root, args[1], flags);
|
|
59
|
+
default:
|
|
60
|
+
console.error(red(`Unknown subcommand: ${sub}`));
|
|
61
|
+
console.error(dim('Available: list, create, info'));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function isSpace(dir) {
|
|
67
|
+
// A space is a top-level directory that contains an INSTRUCTION.md
|
|
68
|
+
return existsSync(resolve(dir, 'INSTRUCTION.md'));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function countFiles(dir) {
|
|
72
|
+
let count = 0;
|
|
73
|
+
try {
|
|
74
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
75
|
+
for (const e of entries) {
|
|
76
|
+
if (e.name.startsWith('.')) continue;
|
|
77
|
+
if (e.isFile()) count++;
|
|
78
|
+
else if (e.isDirectory()) count += countFiles(resolve(dir, e.name));
|
|
79
|
+
}
|
|
80
|
+
} catch { /* skip */ }
|
|
81
|
+
return count;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function spaceList(root, flags) {
|
|
85
|
+
const entries = readdirSync(root, { withFileTypes: true });
|
|
86
|
+
const spaces = [];
|
|
87
|
+
|
|
88
|
+
for (const e of entries) {
|
|
89
|
+
if (!e.isDirectory() || e.name.startsWith('.')) continue;
|
|
90
|
+
const full = resolve(root, e.name);
|
|
91
|
+
if (isSpace(full)) {
|
|
92
|
+
const fileCount = countFiles(full);
|
|
93
|
+
spaces.push({ name: e.name, path: e.name, fileCount });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (isJsonMode(flags)) {
|
|
98
|
+
output({ count: spaces.length, spaces }, flags);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (spaces.length === 0) {
|
|
103
|
+
console.log(dim('No spaces found. Create one with: mindos space create "Name"'));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log(`\n${bold(`Spaces (${spaces.length}):`)}\n`);
|
|
108
|
+
for (const s of spaces) {
|
|
109
|
+
console.log(` ${cyan(s.name.padEnd(30))}${dim(`${s.fileCount} files`)}`);
|
|
110
|
+
}
|
|
111
|
+
console.log();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function spaceCreate(root, name, flags) {
|
|
115
|
+
if (!name) {
|
|
116
|
+
console.error(red('Usage: mindos space create <name>'));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const dir = resolve(root, name);
|
|
120
|
+
if (existsSync(dir)) {
|
|
121
|
+
console.error(red(`Space already exists: ${name}`));
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
mkdirSync(dir, { recursive: true });
|
|
126
|
+
writeFileSync(resolve(dir, 'INSTRUCTION.md'), `# ${name}\n\nSpace instructions go here.\n`, 'utf-8');
|
|
127
|
+
|
|
128
|
+
if (isJsonMode(flags)) {
|
|
129
|
+
output({ ok: true, name, path: name }, flags);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
console.log(`${green('✔')} Created space: ${cyan(name)}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function spaceInfo(root, name, flags) {
|
|
136
|
+
if (!name) {
|
|
137
|
+
console.error(red('Usage: mindos space info <name>'));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
const dir = resolve(root, name);
|
|
141
|
+
if (!existsSync(dir)) {
|
|
142
|
+
console.error(red(`Space not found: ${name}`));
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const fileCount = countFiles(dir);
|
|
147
|
+
const stat = statSync(dir);
|
|
148
|
+
|
|
149
|
+
const info = {
|
|
150
|
+
name,
|
|
151
|
+
path: name,
|
|
152
|
+
fileCount,
|
|
153
|
+
isSpace: isSpace(dir),
|
|
154
|
+
modified: stat.mtime.toISOString(),
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
if (isJsonMode(flags)) {
|
|
158
|
+
output(info, flags);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(`\n${bold(`Space: ${name}`)}\n`);
|
|
163
|
+
console.log(` ${dim('Files:'.padEnd(15))}${fileCount}`);
|
|
164
|
+
console.log(` ${dim('Is Space:'.padEnd(15))}${info.isSpace ? green('yes') : 'no (folder)'}`);
|
|
165
|
+
console.log(` ${dim('Modified:'.padEnd(15))}${info.modified}`);
|
|
166
|
+
console.log();
|
|
167
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mindos status — Show MindOS service status overview
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
6
|
+
import { bold, dim, cyan, green, red, yellow } from '../lib/colors.js';
|
|
7
|
+
import { loadConfig } from '../lib/config.js';
|
|
8
|
+
import { CONFIG_PATH, ROOT, MINDOS_DIR, LOG_PATH } from '../lib/constants.js';
|
|
9
|
+
import { isPortInUse } from '../lib/port.js';
|
|
10
|
+
import { output, isJsonMode } from '../lib/command.js';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
|
|
13
|
+
export const meta = {
|
|
14
|
+
name: 'status',
|
|
15
|
+
group: 'Core',
|
|
16
|
+
summary: 'Show MindOS service status overview',
|
|
17
|
+
usage: 'mindos status',
|
|
18
|
+
examples: [
|
|
19
|
+
'mindos status',
|
|
20
|
+
'mindos status --json',
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export async function run(_args, flags) {
|
|
25
|
+
loadConfig();
|
|
26
|
+
|
|
27
|
+
const webPort = process.env.MINDOS_WEB_PORT || '3456';
|
|
28
|
+
const mcpPort = process.env.MINDOS_MCP_PORT || '8781';
|
|
29
|
+
const mindRoot = process.env.MIND_ROOT || '';
|
|
30
|
+
|
|
31
|
+
const webRunning = await isPortInUse(Number(webPort));
|
|
32
|
+
const mcpRunning = await isPortInUse(Number(mcpPort));
|
|
33
|
+
|
|
34
|
+
const pkgVersion = (() => {
|
|
35
|
+
try { return JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8')).version; } catch { return '?'; }
|
|
36
|
+
})();
|
|
37
|
+
|
|
38
|
+
const configExists = existsSync(CONFIG_PATH);
|
|
39
|
+
|
|
40
|
+
const logSize = (() => {
|
|
41
|
+
try { return statSync(LOG_PATH).size; } catch { return 0; }
|
|
42
|
+
})();
|
|
43
|
+
|
|
44
|
+
const data = {
|
|
45
|
+
version: pkgVersion,
|
|
46
|
+
configured: configExists,
|
|
47
|
+
mindRoot,
|
|
48
|
+
web: { port: webPort, running: webRunning },
|
|
49
|
+
mcp: { port: mcpPort, running: mcpRunning },
|
|
50
|
+
logSize,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (isJsonMode(flags)) {
|
|
54
|
+
output(data, flags);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const indicator = (ok) => ok ? green('● running') : dim('○ stopped');
|
|
59
|
+
|
|
60
|
+
console.log(`
|
|
61
|
+
${bold('MindOS Status')} ${dim(`v${pkgVersion}`)}
|
|
62
|
+
|
|
63
|
+
${dim('Config:'.padEnd(15))}${configExists ? green('✔ configured') : red('✘ not configured')}
|
|
64
|
+
${dim('Mind Root:'.padEnd(15))}${mindRoot ? cyan(mindRoot) : dim('not set')}
|
|
65
|
+
${dim('Web Server:'.padEnd(15))}${indicator(webRunning)} ${dim(`(:${webPort})`)}
|
|
66
|
+
${dim('MCP Server:'.padEnd(15))}${indicator(mcpRunning)} ${dim(`(:${mcpPort})`)}
|
|
67
|
+
${dim('Log:'.padEnd(15))}${logSize > 0 ? dim(`${(logSize / 1024).toFixed(1)} KB`) : dim('empty')}
|
|
68
|
+
`);
|
|
69
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight command registry — zero dependencies.
|
|
3
|
+
*
|
|
4
|
+
* Each command exports: { meta, run }
|
|
5
|
+
* meta.name — primary name
|
|
6
|
+
* meta.aliases — optional alias names
|
|
7
|
+
* meta.group — help group (Core, Knowledge, MCP, Sync, Gateway, Config)
|
|
8
|
+
* meta.summary — one-line description
|
|
9
|
+
* meta.usage — usage string (optional)
|
|
10
|
+
* meta.flags — { flag: description } (optional)
|
|
11
|
+
* run(args, flags) — async handler
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { bold, dim, cyan, green, red } from './colors.js';
|
|
15
|
+
import { ROOT } from './constants.js';
|
|
16
|
+
import { readFileSync } from 'node:fs';
|
|
17
|
+
import { resolve } from 'node:path';
|
|
18
|
+
|
|
19
|
+
/** @type {Map<string, { meta: object, run: function }>} */
|
|
20
|
+
const registry = new Map();
|
|
21
|
+
|
|
22
|
+
/** @type {Map<string, string>} alias → primary name */
|
|
23
|
+
const aliases = new Map();
|
|
24
|
+
|
|
25
|
+
export function register(command) {
|
|
26
|
+
const { meta, run } = command;
|
|
27
|
+
registry.set(meta.name, { meta, run });
|
|
28
|
+
if (meta.aliases) {
|
|
29
|
+
for (const alias of meta.aliases) {
|
|
30
|
+
aliases.set(alias, meta.name);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function resolve_command(name) {
|
|
36
|
+
if (registry.has(name)) return registry.get(name);
|
|
37
|
+
const primary = aliases.get(name);
|
|
38
|
+
if (primary) return registry.get(primary);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getAllCommands() {
|
|
43
|
+
return [...registry.values()];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Parse process.argv into { command, args, flags } */
|
|
47
|
+
export function parseArgs(argv = process.argv.slice(2)) {
|
|
48
|
+
const flags = {};
|
|
49
|
+
const args = [];
|
|
50
|
+
let i = 0;
|
|
51
|
+
|
|
52
|
+
while (i < argv.length) {
|
|
53
|
+
const arg = argv[i];
|
|
54
|
+
if (arg.startsWith('--')) {
|
|
55
|
+
const key = arg.slice(2);
|
|
56
|
+
// Check if next arg is a value (not a flag)
|
|
57
|
+
if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {
|
|
58
|
+
flags[key] = argv[i + 1];
|
|
59
|
+
i += 2;
|
|
60
|
+
} else {
|
|
61
|
+
flags[key] = true;
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
} else if (arg.startsWith('-') && arg.length === 2) {
|
|
65
|
+
flags[arg.slice(1)] = true;
|
|
66
|
+
i++;
|
|
67
|
+
} else {
|
|
68
|
+
args.push(arg);
|
|
69
|
+
i++;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { command: args[0] || null, args: args.slice(1), flags };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Check if --json flag is set */
|
|
77
|
+
export function isJsonMode(flags) {
|
|
78
|
+
return flags.json === true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Output helper: human-readable or JSON */
|
|
82
|
+
export function output(data, flags) {
|
|
83
|
+
if (isJsonMode(flags)) {
|
|
84
|
+
console.log(JSON.stringify(data, null, 2));
|
|
85
|
+
} else if (typeof data === 'string') {
|
|
86
|
+
console.log(data);
|
|
87
|
+
} else {
|
|
88
|
+
console.log(JSON.stringify(data, null, 2));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Print global help */
|
|
93
|
+
export function printHelp() {
|
|
94
|
+
const pkgVersion = (() => {
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8')).version;
|
|
97
|
+
} catch { return '?'; }
|
|
98
|
+
})();
|
|
99
|
+
|
|
100
|
+
const row = (c, d) => ` ${cyan(c.padEnd(38))}${dim(d)}`;
|
|
101
|
+
|
|
102
|
+
const groups = {};
|
|
103
|
+
for (const { meta } of registry.values()) {
|
|
104
|
+
const group = meta.group || 'Other';
|
|
105
|
+
if (!groups[group]) groups[group] = [];
|
|
106
|
+
const usage = meta.usage || `mindos ${meta.name}`;
|
|
107
|
+
groups[group].push(row(usage, meta.summary));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const sections = [];
|
|
111
|
+
const groupOrder = ['Core', 'Knowledge', 'MCP', 'Sync', 'Gateway', 'Config'];
|
|
112
|
+
for (const g of groupOrder) {
|
|
113
|
+
if (groups[g]) {
|
|
114
|
+
sections.push(`${bold(`${g}:`)}\n${groups[g].join('\n')}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Any remaining groups
|
|
118
|
+
for (const [g, items] of Object.entries(groups)) {
|
|
119
|
+
if (!groupOrder.includes(g)) {
|
|
120
|
+
sections.push(`${bold(`${g}:`)}\n${items.join('\n')}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log(`
|
|
125
|
+
${bold('MindOS CLI')} ${dim(`v${pkgVersion}`)}
|
|
126
|
+
|
|
127
|
+
${sections.join('\n\n')}
|
|
128
|
+
|
|
129
|
+
${bold('Global Flags:')}
|
|
130
|
+
${cyan('--json'.padEnd(38))}${dim('Output in JSON format (for agents)')}
|
|
131
|
+
${cyan('--help, -h'.padEnd(38))}${dim('Show help')}
|
|
132
|
+
${cyan('--version, -v'.padEnd(38))}${dim('Show version')}
|
|
133
|
+
`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Print command-specific help */
|
|
137
|
+
export function printCommandHelp(cmd) {
|
|
138
|
+
const { meta } = cmd;
|
|
139
|
+
const usage = meta.usage || `mindos ${meta.name}`;
|
|
140
|
+
console.log(`\n${bold(usage)}\n`);
|
|
141
|
+
console.log(` ${meta.summary}\n`);
|
|
142
|
+
if (meta.flags) {
|
|
143
|
+
console.log(`${bold('Flags:')}`);
|
|
144
|
+
for (const [flag, desc] of Object.entries(meta.flags)) {
|
|
145
|
+
console.log(` ${cyan(flag.padEnd(30))}${dim(desc)}`);
|
|
146
|
+
}
|
|
147
|
+
console.log();
|
|
148
|
+
}
|
|
149
|
+
if (meta.examples) {
|
|
150
|
+
console.log(`${bold('Examples:')}`);
|
|
151
|
+
for (const ex of meta.examples) {
|
|
152
|
+
console.log(` ${dim(ex)}`);
|
|
153
|
+
}
|
|
154
|
+
console.log();
|
|
155
|
+
}
|
|
156
|
+
}
|
package/mcp/dist/index.cjs
CHANGED
|
@@ -107,7 +107,7 @@ data:
|
|
|
107
107
|
|
|
108
108
|
`:r>0?`[Showing characters ${r}\u2013${r+o.length} of ${i.length}]
|
|
109
109
|
|
|
110
|
-
`:"";return fe("mindos_read_file",{path:e},"ok",`${i.length} chars`),de(c+o)}catch(a){return fe("mindos_read_file",{path:e},"error",String(a)),be(String(a))}}),t.registerTool("mindos_write_file",{title:"Write File Content",description:"Overwrite the entire content of an existing file.",inputSchema:E.object({path:E.string().min(1),content:E.string()})},async({path:e,content:r})=>{try{return await dt("/api/file",{op:"save_file",path:e,content:r}),fe("mindos_write_file",{path:e},"ok",`Wrote ${r.length} chars`),de(`Successfully wrote ${r.length} characters to "${e}"`)}catch(n){return fe("mindos_write_file",{path:e},"error",String(n)),be(String(n))}}),t.registerTool("mindos_create_file",{title:"Create New File",description:"Create a new file in the knowledge base. Only .md and .csv files allowed.",inputSchema:E.object({path:E.string().min(1).regex(/\.(md|csv)$/),content:E.string().default("")})},async({path:e,content:r})=>{try{return await dt("/api/file",{op:"create_file",path:e,content:r}),fe("mindos_create_file",{path:e},"ok",`Created ${r.length} chars`),de(`Created "${e}" (${r.length} characters)`)}catch(n){return fe("mindos_create_file",{path:e},"error",String(n)),be(String(n))}}),t.registerTool("mindos_batch_create_files",{title:"Batch Create Files",description:"Create multiple new files in a single operation. Only .md and .csv files allowed. Returns a summary of created files and any errors.",inputSchema:E.object({files:E.array(E.object({path:E.string().min(1).regex(/\.(md|csv)$/).describe("Relative file path (must end in .md or .csv)"),content:E.string().default("").describe("Initial file content")})).min(1).max(50).describe("List of files to create (max 50 per call)")})},async({files:e})=>{let r=[],n=[];for(let i of e)try{await dt("/api/file",{op:"create_file",path:i.path,content:i.content}),r.push(i.path)}catch(o){n.push(`${i.path}: ${String(o)}`)}let a=`Batch creation complete.
|
|
110
|
+
`:"";return fe("mindos_read_file",{path:e},"ok",`${i.length} chars`),de(c+o)}catch(a){return fe("mindos_read_file",{path:e},"error",String(a)),be(String(a))}}),t.registerTool("mindos_write_file",{title:"Write File Content",description:"Overwrite the entire content of an existing file.",inputSchema:E.object({path:E.string().min(1),content:E.string()})},async({path:e,content:r})=>{try{return await dt("/api/file",{op:"save_file",path:e,content:r}),fe("mindos_write_file",{path:e},"ok",`Wrote ${r.length} chars`),de(`Successfully wrote ${r.length} characters to "${e}"`)}catch(n){return fe("mindos_write_file",{path:e},"error",String(n)),be(String(n))}}),t.registerTool("mindos_create_file",{title:"Create New File",description:"Create a new file in the knowledge base. Only .md and .csv files allowed. Creates parent directories but does NOT create Space scaffolding. Use mindos_create_space to create a Space.",inputSchema:E.object({path:E.string().min(1).regex(/\.(md|csv)$/),content:E.string().default("")})},async({path:e,content:r})=>{try{return await dt("/api/file",{op:"create_file",path:e,content:r}),fe("mindos_create_file",{path:e},"ok",`Created ${r.length} chars`),de(`Created "${e}" (${r.length} characters)`)}catch(n){return fe("mindos_create_file",{path:e},"error",String(n)),be(String(n))}}),t.registerTool("mindos_batch_create_files",{title:"Batch Create Files",description:"Create multiple new files in a single operation. Only .md and .csv files allowed. Returns a summary of created files and any errors.",inputSchema:E.object({files:E.array(E.object({path:E.string().min(1).regex(/\.(md|csv)$/).describe("Relative file path (must end in .md or .csv)"),content:E.string().default("").describe("Initial file content")})).min(1).max(50).describe("List of files to create (max 50 per call)")})},async({files:e})=>{let r=[],n=[];for(let i of e)try{await dt("/api/file",{op:"create_file",path:i.path,content:i.content}),r.push(i.path)}catch(o){n.push(`${i.path}: ${String(o)}`)}let a=`Batch creation complete.
|
|
111
111
|
Created ${r.length} file(s): ${r.join(", ")}`;return n.length>0&&(a+=`
|
|
112
112
|
|
|
113
113
|
Failed to create ${n.length} file(s):
|
package/mcp/src/index.ts
CHANGED
|
@@ -190,7 +190,7 @@ server.registerTool("mindos_write_file", {
|
|
|
190
190
|
|
|
191
191
|
server.registerTool("mindos_create_file", {
|
|
192
192
|
title: "Create New File",
|
|
193
|
-
description: "Create a new file in the knowledge base. Only .md and .csv files allowed.",
|
|
193
|
+
description: "Create a new file in the knowledge base. Only .md and .csv files allowed. Creates parent directories but does NOT create Space scaffolding. Use mindos_create_space to create a Space.",
|
|
194
194
|
inputSchema: z.object({
|
|
195
195
|
path: z.string().min(1).regex(/\.(md|csv)$/),
|
|
196
196
|
content: z.string().default(""),
|
package/package.json
CHANGED
package/skills/mindos/SKILL.md
CHANGED
|
@@ -105,8 +105,8 @@ Before any non-trivial write, confirm all checks:
|
|
|
105
105
|
|
|
106
106
|
- `mindos_read_file`: Read file content.
|
|
107
107
|
- `mindos_write_file`: Use only for true full replacement.
|
|
108
|
-
- `mindos_create_file`: Create `.md`/`.csv` files.
|
|
109
|
-
- `mindos_create_space`: Create a Mind Space (directory + README + INSTRUCTION scaffold).
|
|
108
|
+
- `mindos_create_file`: Create `.md`/`.csv` files. Creates parent directories automatically but does NOT create Space scaffolding (INSTRUCTION.md/README.md). Use `mindos_create_space` when you need a Space.
|
|
109
|
+
- `mindos_create_space`: Create a Mind Space (directory + README + INSTRUCTION scaffold). **This is the only way to create a Space.** Regular folders created by `create_file` remain plain directories. Use this when adding a new cognitive zone.
|
|
110
110
|
- `mindos_rename_space`: Rename a Space folder (directory). Do not use `rename_file` for folders.
|
|
111
111
|
- `mindos_delete_file`: Delete only with explicit user intent.
|
|
112
112
|
- `mindos_rename_file`, `mindos_move_file`: Structural edits with follow-up reference checks.
|
|
@@ -103,8 +103,8 @@ description: >
|
|
|
103
103
|
|
|
104
104
|
- `mindos_read_file`:读取文件内容。
|
|
105
105
|
- `mindos_write_file`:仅在确需整文件替换时使用。
|
|
106
|
-
- `mindos_create_file`:创建 `.md`/`.csv`
|
|
107
|
-
- `mindos_create_space`:新建心智空间(目录 + README + INSTRUCTION
|
|
106
|
+
- `mindos_create_file`:创建 `.md`/`.csv` 文件。自动创建父目录,但不会创建空间脚手架文件(INSTRUCTION.md/README.md)。需要创建空间请用 `mindos_create_space`。
|
|
107
|
+
- `mindos_create_space`:新建心智空间(目录 + README + INSTRUCTION 脚手架)。**这是创建空间的唯一方式。** 通过 `create_file` 创建的普通目录不会变成空间。新增整块知识分区时使用此工具。
|
|
108
108
|
- `mindos_rename_space`:重命名空间目录(文件夹)。不能用 `rename_file` 重命名目录。
|
|
109
109
|
- `mindos_delete_file`:仅在用户明确意图下删除。
|
|
110
110
|
- `mindos_rename_file`、`mindos_move_file`:结构变更后补做引用检查。
|