@geminilight/mindos 0.6.28 → 0.6.30

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.
Files changed (113) hide show
  1. package/README.md +10 -4
  2. package/app/app/api/a2a/agents/route.ts +9 -0
  3. package/app/app/api/a2a/delegations/route.ts +9 -0
  4. package/app/app/api/a2a/discover/route.ts +2 -0
  5. package/app/app/api/a2a/route.ts +6 -6
  6. package/app/app/api/acp/config/route.ts +82 -0
  7. package/app/app/api/acp/detect/route.ts +114 -0
  8. package/app/app/api/acp/install/route.ts +51 -0
  9. package/app/app/api/acp/registry/route.ts +31 -0
  10. package/app/app/api/acp/session/route.ts +185 -0
  11. package/app/app/api/ask/route.ts +116 -13
  12. package/app/app/api/workflows/route.ts +156 -0
  13. package/app/app/layout.tsx +2 -0
  14. package/app/app/page.tsx +7 -2
  15. package/app/components/ActivityBar.tsx +12 -4
  16. package/app/components/AskModal.tsx +4 -1
  17. package/app/components/DirView.tsx +64 -2
  18. package/app/components/FileTree.tsx +40 -10
  19. package/app/components/GuideCard.tsx +7 -17
  20. package/app/components/HomeContent.tsx +1 -0
  21. package/app/components/MarkdownView.tsx +2 -0
  22. package/app/components/Panel.tsx +1 -0
  23. package/app/components/RightAskPanel.tsx +5 -1
  24. package/app/components/SearchModal.tsx +234 -80
  25. package/app/components/SidebarLayout.tsx +6 -0
  26. package/app/components/agents/AgentDetailContent.tsx +266 -52
  27. package/app/components/agents/AgentsContentPage.tsx +32 -6
  28. package/app/components/agents/AgentsPanelA2aTab.tsx +684 -0
  29. package/app/components/agents/AgentsPanelSessionsTab.tsx +166 -0
  30. package/app/components/agents/SkillDetailPopover.tsx +4 -9
  31. package/app/components/agents/agents-content-model.ts +2 -2
  32. package/app/components/ask/AgentSelectorCapsule.tsx +218 -0
  33. package/app/components/ask/AskContent.tsx +197 -239
  34. package/app/components/ask/FileChip.tsx +82 -17
  35. package/app/components/ask/MentionPopover.tsx +21 -3
  36. package/app/components/ask/MessageList.tsx +30 -9
  37. package/app/components/ask/SlashCommandPopover.tsx +21 -3
  38. package/app/components/help/HelpContent.tsx +9 -9
  39. package/app/components/panels/AgentsPanel.tsx +2 -0
  40. package/app/components/panels/AgentsPanelAgentDetail.tsx +5 -8
  41. package/app/components/panels/AgentsPanelHubNav.tsx +16 -2
  42. package/app/components/panels/EchoPanel.tsx +5 -1
  43. package/app/components/panels/EchoSidebarStats.tsx +136 -0
  44. package/app/components/panels/WorkflowsPanel.tsx +206 -0
  45. package/app/components/renderers/workflow-yaml/StepEditor.tsx +157 -0
  46. package/app/components/renderers/workflow-yaml/WorkflowEditor.tsx +201 -0
  47. package/app/components/renderers/workflow-yaml/WorkflowRunner.tsx +226 -0
  48. package/app/components/renderers/workflow-yaml/WorkflowYamlRenderer.tsx +126 -0
  49. package/app/components/renderers/workflow-yaml/execution.ts +177 -0
  50. package/app/components/renderers/workflow-yaml/index.ts +6 -0
  51. package/app/components/renderers/workflow-yaml/manifest.ts +21 -0
  52. package/app/components/renderers/workflow-yaml/parser.ts +172 -0
  53. package/app/components/renderers/workflow-yaml/selectors.tsx +522 -0
  54. package/app/components/renderers/workflow-yaml/serializer.ts +56 -0
  55. package/app/components/renderers/workflow-yaml/types.ts +46 -0
  56. package/app/components/settings/KnowledgeTab.tsx +3 -6
  57. package/app/components/settings/McpSkillsSection.tsx +4 -5
  58. package/app/components/settings/McpTab.tsx +6 -8
  59. package/app/components/setup/StepSecurity.tsx +4 -5
  60. package/app/components/setup/index.tsx +5 -11
  61. package/app/components/ui/Toaster.tsx +39 -0
  62. package/app/hooks/useA2aRegistry.ts +6 -1
  63. package/app/hooks/useAcpConfig.ts +96 -0
  64. package/app/hooks/useAcpDetection.ts +120 -0
  65. package/app/hooks/useAcpRegistry.ts +86 -0
  66. package/app/hooks/useAskModal.ts +12 -5
  67. package/app/hooks/useAskPanel.ts +8 -5
  68. package/app/hooks/useAskSession.ts +19 -2
  69. package/app/hooks/useDelegationHistory.ts +49 -0
  70. package/app/hooks/useImageUpload.ts +152 -0
  71. package/app/lib/a2a/client.ts +49 -5
  72. package/app/lib/a2a/orchestrator.ts +0 -1
  73. package/app/lib/a2a/task-handler.ts +4 -4
  74. package/app/lib/a2a/types.ts +15 -0
  75. package/app/lib/acp/acp-tools.ts +95 -0
  76. package/app/lib/acp/agent-descriptors.ts +274 -0
  77. package/app/lib/acp/bridge.ts +144 -0
  78. package/app/lib/acp/index.ts +40 -0
  79. package/app/lib/acp/registry.ts +202 -0
  80. package/app/lib/acp/session.ts +717 -0
  81. package/app/lib/acp/subprocess.ts +495 -0
  82. package/app/lib/acp/types.ts +274 -0
  83. package/app/lib/agent/model.ts +18 -3
  84. package/app/lib/agent/to-agent-messages.ts +25 -2
  85. package/app/lib/agent/tools.ts +2 -1
  86. package/app/lib/i18n/_core.ts +22 -0
  87. package/app/lib/i18n/index.ts +35 -0
  88. package/app/lib/i18n/modules/ai-chat.ts +215 -0
  89. package/app/lib/i18n/modules/common.ts +71 -0
  90. package/app/lib/i18n/modules/features.ts +153 -0
  91. package/app/lib/i18n/modules/knowledge.ts +429 -0
  92. package/app/lib/i18n/modules/navigation.ts +153 -0
  93. package/app/lib/i18n/modules/onboarding.ts +523 -0
  94. package/app/lib/i18n/modules/panels.ts +1196 -0
  95. package/app/lib/i18n/modules/settings.ts +585 -0
  96. package/app/lib/i18n-en.ts +2 -1518
  97. package/app/lib/i18n-zh.ts +2 -1542
  98. package/app/lib/i18n.ts +3 -6
  99. package/app/lib/pi-integration/skills.ts +21 -6
  100. package/app/lib/renderers/index.ts +2 -2
  101. package/app/lib/settings.ts +10 -0
  102. package/app/lib/toast.ts +79 -0
  103. package/app/lib/types.ts +12 -1
  104. package/app/next-env.d.ts +1 -1
  105. package/app/package.json +3 -1
  106. package/bin/cli.js +25 -25
  107. package/bin/commands/file.js +29 -2
  108. package/bin/commands/space.js +249 -91
  109. package/package.json +1 -1
  110. package/templates/en/.mindos/workflows/Sprint Release.flow.yaml +130 -0
  111. package/templates/zh/.mindos/workflows//345/221/250/350/277/255/344/273/243/346/243/200/346/237/245.flow.yaml +84 -0
  112. package/app/components/renderers/workflow/WorkflowRenderer.tsx +0 -409
  113. package/app/components/renderers/workflow/manifest.ts +0 -14
@@ -1,10 +1,14 @@
1
1
  /**
2
- * mindos space — Mind Space management
2
+ * mindos space — Knowledge base structure management
3
+ *
4
+ * Manages the directory tree of the knowledge base.
5
+ * "Space" = directory + INSTRUCTION.md (AI context).
6
+ * All directory operations go here; file content ops go to `mindos file`.
3
7
  */
4
8
 
5
9
  import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync, rmSync, renameSync } from 'node:fs';
6
- import { resolve, relative } from 'node:path';
7
- import { bold, dim, cyan, green, red } from '../lib/colors.js';
10
+ import { resolve, basename } from 'node:path';
11
+ import { bold, dim, cyan, green, red, yellow } from '../lib/colors.js';
8
12
  import { loadConfig } from '../lib/config.js';
9
13
  import { output, isJsonMode, EXIT } from '../lib/command.js';
10
14
 
@@ -21,15 +25,18 @@ function getMindRoot() {
21
25
  export const meta = {
22
26
  name: 'space',
23
27
  group: 'Knowledge',
24
- summary: 'Mind Space management (list, create, delete, rename, info)',
28
+ summary: 'Knowledge base structure (ls, mkdir, rmdir, init, info, tree)',
25
29
  usage: 'mindos space <subcommand>',
26
30
  examples: [
27
- 'mindos space list',
28
- 'mindos space list --json',
31
+ 'mindos space ls',
32
+ 'mindos space ls "📝 笔记"',
33
+ 'mindos space tree',
34
+ 'mindos space mkdir "📝 笔记/新分类"',
35
+ 'mindos space rmdir "📝 笔记/旧分类"',
36
+ 'mindos space init "exploration"',
37
+ 'mindos space info "📝 笔记"',
29
38
  'mindos space create "Research"',
30
- 'mindos space delete "Old Project"',
31
39
  'mindos space rename "Old" "New"',
32
- 'mindos space info "Work"',
33
40
  ],
34
41
  };
35
42
 
@@ -39,48 +46,56 @@ export async function run(args, flags) {
39
46
 
40
47
  if (!sub || flags.help || flags.h) {
41
48
  console.log(`
42
- ${bold('mindos space')} — Mind Space management
49
+ ${bold('mindos space')} — Knowledge base structure management
43
50
 
44
- ${bold('Subcommands:')}
45
- ${cyan('list'.padEnd(20))}${dim('List all spaces')}
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')}
49
- ${cyan('info <name>'.padEnd(20))}${dim('Show space details')}
51
+ ${bold('Browse:')}
52
+ ${cyan('ls [path]'.padEnd(24))}${dim('List contents of a directory (default: root)')}
53
+ ${cyan('tree [path]'.padEnd(24))}${dim('Show directory tree recursively')}
54
+ ${cyan('info <path>'.padEnd(24))}${dim('Show directory details (type, files, modified)')}
55
+
56
+ ${bold('Structure:')}
57
+ ${cyan('create <name>'.padEnd(24))}${dim('Create a new Space (directory + INSTRUCTION.md)')}
58
+ ${cyan('mkdir <path>'.padEnd(24))}${dim('Create a directory (no INSTRUCTION.md)')}
59
+ ${cyan('rmdir <path>'.padEnd(24))}${dim('Delete a directory and all its contents')}
60
+ ${cyan('rename <old> <new>'.padEnd(24))}${dim('Rename or move a directory')}
61
+ ${cyan('init <path>'.padEnd(24))}${dim('Upgrade a directory to a Space (add INSTRUCTION.md)')}
50
62
 
51
63
  ${bold('Examples:')}
52
- ${dim('mindos space list')}
53
- ${dim('mindos space create "Research"')}
54
- ${dim('mindos space delete "Old Project"')}
55
- ${dim('mindos space rename "Old" "New"')}
64
+ ${dim('mindos space ls')}
65
+ ${dim('mindos space ls "📝 笔记" --json')}
66
+ ${dim('mindos space tree "⚙️ 配置"')}
67
+ ${dim('mindos space mkdir "📝 笔记/新分类/子分类"')}
68
+ ${dim('mindos space init "exploration"')}
56
69
  `);
57
70
  return;
58
71
  }
59
72
 
60
73
  switch (sub) {
61
- case 'list': return spaceList(root, flags);
62
- case 'ls': return spaceList(root, flags);
74
+ case 'ls': case 'list': return spaceLs(root, args[1], flags);
75
+ case 'tree': return spaceTree(root, args[1], flags);
76
+ case 'info': return spaceInfo(root, args[1], flags);
63
77
  case 'create': return spaceCreate(root, args[1], flags);
64
- case 'delete': case 'rm': return spaceDelete(root, args[1], flags);
78
+ case 'mkdir': return spaceMkdir(root, args[1], flags);
79
+ case 'rmdir': case 'rm': case 'delete': return spaceRmdir(root, args[1], flags);
65
80
  case 'rename': case 'mv': return spaceRename(root, args[1], args[2], flags);
66
- case 'info': return spaceInfo(root, args[1], flags);
81
+ case 'init': case 'convert': return spaceInit(root, args[1], flags);
67
82
  default:
68
83
  console.error(red(`Unknown subcommand: ${sub}`));
69
- console.error(dim('Available: list, create, delete, rename, info'));
70
- process.exit(EXIT.ERROR);
84
+ console.error(dim('Available: ls, tree, info, create, mkdir, rmdir, rename, init'));
85
+ process.exit(EXIT.ARGS);
71
86
  }
72
87
  }
73
88
 
89
+ // ── Helpers ────────────────────────────────────────────────────────────────────
90
+
74
91
  function isSpace(dir) {
75
- // A space is a top-level directory that contains an INSTRUCTION.md
76
92
  return existsSync(resolve(dir, 'INSTRUCTION.md'));
77
93
  }
78
94
 
79
95
  function countFiles(dir) {
80
96
  let count = 0;
81
97
  try {
82
- const entries = readdirSync(dir, { withFileTypes: true });
83
- for (const e of entries) {
98
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
84
99
  if (e.name.startsWith('.')) continue;
85
100
  if (e.isFile()) count++;
86
101
  else if (e.isDirectory()) count += countFiles(resolve(dir, e.name));
@@ -89,133 +104,276 @@ function countFiles(dir) {
89
104
  return count;
90
105
  }
91
106
 
92
- function spaceList(root, flags) {
93
- const entries = readdirSync(root, { withFileTypes: true });
107
+ function resolvePath(root, relPath) {
108
+ const full = relPath ? resolve(root, relPath) : root;
109
+ if (!existsSync(full)) {
110
+ console.error(red(`Not found: ${relPath || '(root)'}`));
111
+ process.exit(EXIT.NOT_FOUND);
112
+ }
113
+ return full;
114
+ }
115
+
116
+ // ── ls: list contents of a directory ──────────────────────────────────────────
117
+
118
+ function spaceLs(root, relPath, flags) {
119
+ const dir = resolvePath(root, relPath);
120
+ const entries = readdirSync(dir, { withFileTypes: true });
94
121
  const spaces = [];
122
+ const dirs = [];
123
+ const files = [];
95
124
 
96
125
  for (const e of entries) {
97
- if (!e.isDirectory() || e.name.startsWith('.')) continue;
98
- const full = resolve(root, e.name);
99
- if (isSpace(full)) {
100
- const fileCount = countFiles(full);
101
- spaces.push({ name: e.name, path: e.name, fileCount });
126
+ if (e.name.startsWith('.')) continue;
127
+ const full = resolve(dir, e.name);
128
+ if (e.isDirectory()) {
129
+ const entry = { name: e.name, type: isSpace(full) ? 'space' : 'dir', fileCount: countFiles(full) };
130
+ (entry.type === 'space' ? spaces : dirs).push(entry);
131
+ } else if (e.isFile()) {
132
+ files.push({ name: e.name, type: 'file' });
102
133
  }
103
134
  }
104
135
 
105
136
  if (isJsonMode(flags)) {
106
- output({ count: spaces.length, spaces }, flags);
137
+ output({ path: relPath || '.', entries: [...spaces, ...dirs, ...files] }, flags);
107
138
  return;
108
139
  }
109
140
 
110
- if (spaces.length === 0) {
111
- console.log(dim('No spaces found. Create one with: mindos space create "Name"'));
141
+ const label = relPath ? `${relPath}/` : 'Knowledge Base';
142
+ const total = spaces.length + dirs.length + files.length;
143
+ if (total === 0) {
144
+ console.log(dim(`\n${label} is empty.\n`));
112
145
  return;
113
146
  }
114
147
 
115
- console.log(`\n${bold(`Spaces (${spaces.length}):`)}\n`);
148
+ console.log(`\n${bold(label)}\n`);
116
149
  for (const s of spaces) {
117
- console.log(` ${cyan(s.name.padEnd(30))}${dim(`${s.fileCount} files`)}`);
150
+ console.log(` ${cyan(s.name + '/')} ${dim(`[Space] ${s.fileCount} files`)}`);
151
+ }
152
+ for (const d of dirs) {
153
+ console.log(` ${d.name}/ ${dim(`${d.fileCount} files`)}`);
154
+ }
155
+ for (const f of files) {
156
+ console.log(` ${dim(f.name)}`);
157
+ }
158
+ if (dirs.length > 0 && !relPath) {
159
+ console.log(dim(`\n Tip: \`mindos space init <name>\` to upgrade a directory to a Space`));
118
160
  }
119
161
  console.log();
120
162
  }
121
163
 
164
+ // ── tree: recursive directory tree ────────────────────────────────────────────
165
+
166
+ function spaceTree(root, relPath, flags) {
167
+ const dir = resolvePath(root, relPath);
168
+
169
+ if (isJsonMode(flags)) {
170
+ output({ path: relPath || '.', tree: buildTree(dir) }, flags);
171
+ return;
172
+ }
173
+
174
+ const label = relPath || 'Knowledge Base';
175
+ console.log(`\n${bold(label)}`);
176
+ printTree(dir, '');
177
+ console.log();
178
+ }
179
+
180
+ function buildTree(dir) {
181
+ const result = [];
182
+ try {
183
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
184
+ if (e.name.startsWith('.')) continue;
185
+ const full = resolve(dir, e.name);
186
+ if (e.isDirectory()) {
187
+ result.push({ name: e.name, type: isSpace(full) ? 'space' : 'dir', children: buildTree(full) });
188
+ } else {
189
+ result.push({ name: e.name, type: 'file' });
190
+ }
191
+ }
192
+ } catch { /* skip */ }
193
+ return result;
194
+ }
195
+
196
+ function printTree(dir, prefix) {
197
+ let entries;
198
+ try { entries = readdirSync(dir, { withFileTypes: true }).filter(e => !e.name.startsWith('.')); }
199
+ catch { return; }
200
+
201
+ entries.forEach((e, i) => {
202
+ const isLast = i === entries.length - 1;
203
+ const connector = isLast ? '└── ' : '├── ';
204
+ const full = resolve(dir, e.name);
205
+ if (e.isDirectory()) {
206
+ const tag = isSpace(full) ? cyan(' [Space]') : '';
207
+ console.log(`${prefix}${connector}${e.name}/${tag}`);
208
+ printTree(full, prefix + (isLast ? ' ' : '│ '));
209
+ } else {
210
+ console.log(`${prefix}${connector}${dim(e.name)}`);
211
+ }
212
+ });
213
+ }
214
+
215
+ // ── info ──────────────────────────────────────────────────────────────────────
216
+
217
+ function spaceInfo(root, relPath, flags) {
218
+ if (!relPath) {
219
+ console.error(red('Usage: mindos space info <path>'));
220
+ process.exit(EXIT.ARGS);
221
+ }
222
+ const dir = resolvePath(root, relPath);
223
+ const stat = statSync(dir);
224
+ if (!stat.isDirectory()) {
225
+ console.error(red(`Not a directory: ${relPath}. Use \`mindos file read\` for files.`));
226
+ process.exit(EXIT.ARGS);
227
+ }
228
+
229
+ const fileCount = countFiles(dir);
230
+ const subdirs = readdirSync(dir, { withFileTypes: true }).filter(e => e.isDirectory() && !e.name.startsWith('.')).length;
231
+ const space = isSpace(dir);
232
+
233
+ const info = { name: basename(relPath), path: relPath, type: space ? 'space' : 'dir', fileCount, subdirs, modified: stat.mtime.toISOString() };
234
+
235
+ if (isJsonMode(flags)) {
236
+ output(info, flags);
237
+ return;
238
+ }
239
+
240
+ console.log(`\n${bold(relPath)}\n`);
241
+ console.log(` ${dim('Type:'.padEnd(15))}${space ? cyan('Space') : 'Directory'}`);
242
+ console.log(` ${dim('Files:'.padEnd(15))}${fileCount}`);
243
+ console.log(` ${dim('Subdirs:'.padEnd(15))}${subdirs}`);
244
+ console.log(` ${dim('Modified:'.padEnd(15))}${info.modified}`);
245
+ if (!space) {
246
+ console.log(`\n ${dim('Tip: `mindos space init "' + relPath + '"` to upgrade to a Space')}`);
247
+ }
248
+ console.log();
249
+ }
250
+
251
+ // ── create: new Space (dir + INSTRUCTION.md) ──────────────────────────────────
252
+
122
253
  function spaceCreate(root, name, flags) {
123
254
  if (!name) {
124
255
  console.error(red('Usage: mindos space create <name>'));
125
- process.exit(EXIT.ERROR);
256
+ process.exit(EXIT.ARGS);
126
257
  }
127
258
  const dir = resolve(root, name);
128
259
  if (existsSync(dir)) {
129
- console.error(red(`Space already exists: ${name}`));
260
+ console.error(red(`Already exists: ${name}`));
130
261
  process.exit(EXIT.ERROR);
131
262
  }
132
263
 
133
264
  mkdirSync(dir, { recursive: true });
134
- writeFileSync(resolve(dir, 'INSTRUCTION.md'), `# ${name}\n\nSpace instructions go here.\n`, 'utf-8');
265
+ writeFileSync(resolve(dir, 'INSTRUCTION.md'), `# ${basename(name)}\n\nSpace instructions go here.\n`, 'utf-8');
266
+ writeFileSync(resolve(dir, 'README.md'), `# ${basename(name)}\n`, 'utf-8');
135
267
 
136
268
  if (isJsonMode(flags)) {
137
- output({ ok: true, name, path: name }, flags);
269
+ output({ ok: true, name, type: 'space' }, flags);
138
270
  return;
139
271
  }
140
- console.log(`${green('✔')} Created space: ${cyan(name)}`);
272
+ console.log(`${green('✔')} Created Space: ${cyan(name)}`);
141
273
  }
142
274
 
143
- function spaceDelete(root, name, flags) {
144
- if (!name) {
145
- console.error(red('Usage: mindos space delete <name>'));
146
- process.exit(EXIT.ERROR);
275
+ // ── mkdir: plain directory ────────────────────────────────────────────────────
276
+
277
+ function spaceMkdir(root, relPath, flags) {
278
+ if (!relPath) {
279
+ console.error(red('Usage: mindos space mkdir <path>'));
280
+ process.exit(EXIT.ARGS);
147
281
  }
148
- const dir = resolve(root, name);
149
- if (!existsSync(dir)) {
150
- console.error(red(`Space not found: ${name}`));
151
- process.exit(EXIT.ERROR);
282
+ const full = resolve(root, relPath);
283
+ if (existsSync(full)) {
284
+ if (isJsonMode(flags)) {
285
+ output({ ok: true, path: relPath, created: false }, flags);
286
+ return;
287
+ }
288
+ console.log(dim(`Already exists: ${relPath}`));
289
+ return;
152
290
  }
153
291
 
292
+ mkdirSync(full, { recursive: true });
293
+
294
+ if (isJsonMode(flags)) {
295
+ output({ ok: true, path: relPath, created: true }, flags);
296
+ return;
297
+ }
298
+ console.log(`${green('✔')} Created directory: ${cyan(relPath)}`);
299
+ }
300
+
301
+ // ── rmdir: delete directory ───────────────────────────────────────────────────
302
+
303
+ function spaceRmdir(root, relPath, flags) {
304
+ if (!relPath) {
305
+ console.error(red('Usage: mindos space rmdir <path>'));
306
+ process.exit(EXIT.ARGS);
307
+ }
308
+ const dir = resolvePath(root, relPath);
154
309
  const fileCount = countFiles(dir);
155
310
  rmSync(dir, { recursive: true, force: true });
156
311
 
157
312
  if (isJsonMode(flags)) {
158
- output({ ok: true, name, deletedFiles: fileCount }, flags);
313
+ output({ ok: true, path: relPath, deletedFiles: fileCount }, flags);
159
314
  return;
160
315
  }
161
- console.log(`${green('✔')} Deleted space: ${cyan(name)} (${fileCount} files removed)`);
316
+ console.log(`${green('✔')} Deleted: ${cyan(relPath)} (${fileCount} files removed)`);
162
317
  }
163
318
 
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);
319
+ // ── rename ────────────────────────────────────────────────────────────────────
320
+
321
+ function spaceRename(root, oldPath, newPath, flags) {
322
+ if (!oldPath || !newPath) {
323
+ console.error(red('Usage: mindos space rename <old-path> <new-path>'));
324
+ process.exit(EXIT.ARGS);
174
325
  }
326
+ const oldDir = resolvePath(root, oldPath);
327
+ const newDir = resolve(root, newPath);
175
328
  if (existsSync(newDir)) {
176
- console.error(red(`Target already exists: ${newName}`));
329
+ console.error(red(`Target already exists: ${newPath}`));
177
330
  process.exit(EXIT.ERROR);
178
331
  }
179
332
 
333
+ // Ensure parent of target exists
334
+ const parentDir = resolve(newDir, '..');
335
+ if (!existsSync(parentDir)) mkdirSync(parentDir, { recursive: true });
336
+
180
337
  renameSync(oldDir, newDir);
181
338
 
182
339
  if (isJsonMode(flags)) {
183
- output({ ok: true, from: oldName, to: newName }, flags);
340
+ output({ ok: true, from: oldPath, to: newPath }, flags);
184
341
  return;
185
342
  }
186
- console.log(`${green('✔')} Renamed space: ${cyan(oldName)} → ${cyan(newName)}`);
343
+ console.log(`${green('✔')} Renamed: ${cyan(oldPath)} → ${cyan(newPath)}`);
187
344
  }
188
345
 
189
- function spaceInfo(root, name, flags) {
190
- if (!name) {
191
- console.error(red('Usage: mindos space info <name>'));
192
- process.exit(EXIT.ERROR);
346
+ // ── init: upgrade directory to Space ──────────────────────────────────────────
347
+
348
+ function spaceInit(root, relPath, flags) {
349
+ if (!relPath) {
350
+ console.error(red('Usage: mindos space init <path>'));
351
+ process.exit(EXIT.ARGS);
193
352
  }
194
- const dir = resolve(root, name);
353
+ const dir = resolve(root, relPath);
354
+
355
+ // If doesn't exist, create it + init as Space
195
356
  if (!existsSync(dir)) {
196
- console.error(red(`Space not found: ${name}`));
197
- process.exit(EXIT.ERROR);
357
+ mkdirSync(dir, { recursive: true });
198
358
  }
199
359
 
200
- const fileCount = countFiles(dir);
201
- const stat = statSync(dir);
360
+ if (isSpace(dir)) {
361
+ if (isJsonMode(flags)) {
362
+ output({ ok: true, path: relPath, initialized: false, message: 'already a Space' }, flags);
363
+ return;
364
+ }
365
+ console.log(dim(`Already a Space: ${relPath}`));
366
+ return;
367
+ }
202
368
 
203
- const info = {
204
- name,
205
- path: name,
206
- fileCount,
207
- isSpace: isSpace(dir),
208
- modified: stat.mtime.toISOString(),
209
- };
369
+ writeFileSync(resolve(dir, 'INSTRUCTION.md'), `# ${basename(relPath)}\n\nSpace instructions go here.\n`, 'utf-8');
370
+ if (!existsSync(resolve(dir, 'README.md'))) {
371
+ writeFileSync(resolve(dir, 'README.md'), `# ${basename(relPath)}\n`, 'utf-8');
372
+ }
210
373
 
211
374
  if (isJsonMode(flags)) {
212
- output(info, flags);
375
+ output({ ok: true, path: relPath, initialized: true }, flags);
213
376
  return;
214
377
  }
215
-
216
- console.log(`\n${bold(`Space: ${name}`)}\n`);
217
- console.log(` ${dim('Files:'.padEnd(15))}${fileCount}`);
218
- console.log(` ${dim('Is Space:'.padEnd(15))}${info.isSpace ? green('yes') : 'no (folder)'}`);
219
- console.log(` ${dim('Modified:'.padEnd(15))}${info.modified}`);
220
- console.log();
378
+ console.log(`${green('✔')} Initialized Space: ${cyan(relPath)}`);
221
379
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geminilight/mindos",
3
- "version": "0.6.28",
3
+ "version": "0.6.30",
4
4
  "description": "MindOS — Human-Agent Collaborative Mind System. Local-first knowledge base that syncs your mind to all AI Agents via MCP.",
5
5
  "keywords": [
6
6
  "mindos",
@@ -0,0 +1,130 @@
1
+ title: Sprint Release Workflow
2
+ description: Weekly sprint release process with multi-agent collaboration and comprehensive QA
3
+
4
+ # Global configuration - skills available across all steps
5
+ skills:
6
+ - software-architecture
7
+ - code-review-quality
8
+ - document-release
9
+
10
+ # Global tools guidance (advisory - LLM auto-selects based on context)
11
+ tools:
12
+ - git
13
+ - npm
14
+ - github
15
+
16
+ # Workflow steps - executed sequentially
17
+ steps:
18
+ # Step 1: Run comprehensive test suite
19
+ - id: run_tests
20
+ name: Run tests
21
+ description: Execute full test suite and report results with coverage metrics
22
+ agent: cursor
23
+ prompt: |
24
+ Execute the full test suite for this project.
25
+
26
+ Provide:
27
+ 1. Total tests run, passed, failed
28
+ 2. Coverage report (lines/branches/functions)
29
+ 3. Any critical failures with recommendations
30
+ 4. Time taken
31
+
32
+ If failures exist, list the top 3 most critical with suggested fixes.
33
+ timeout: 120
34
+
35
+ # Step 2: Code review with dedicated AI agent
36
+ - id: code_review
37
+ name: Code review
38
+ description: Comprehensive code review using software architecture principles
39
+ agent: claude-code
40
+ skill: code-review-quality
41
+ prompt: |
42
+ Review the recent code changes using the code-review-quality standard.
43
+
44
+ Evaluate:
45
+ 1. Correctness - error handling, edge cases
46
+ 2. Security - authentication, input validation, secrets
47
+ 3. Performance - N+1 queries, caching, complexity
48
+ 4. Maintainability - naming, tests, documentation
49
+ 5. Architecture - follows project patterns, no anti-patterns
50
+
51
+ Provide a rating (e.g., 8.5/10) and key recommendations.
52
+ timeout: 120
53
+
54
+ # Step 3: Automated security scan (no agent - use LLM with tools)
55
+ - id: security_check
56
+ name: Security scan
57
+ description: Run security analysis and dependency checks
58
+ tools:
59
+ - npm
60
+ - github
61
+ prompt: |
62
+ Perform security checks on this project:
63
+
64
+ 1. Check for known vulnerabilities in npm dependencies
65
+ 2. Review recent dependency changes
66
+ 3. Check for hardcoded secrets or credentials
67
+ 4. Evaluate access control and authentication mechanisms
68
+ 5. Assess error handling for information leaks
69
+
70
+ Report severity and recommended fixes.
71
+ timeout: 60
72
+
73
+ # Step 4: Update documentation using document-release skill
74
+ - id: update_docs
75
+ name: Update documentation
76
+ description: Sync CHANGELOG, README, and API docs with shipped changes
77
+ skill: document-release
78
+ prompt: |
79
+ Update project documentation based on the shipped changes:
80
+
81
+ 1. Update CHANGELOG.md following semantic versioning
82
+ 2. Update README.md if features or APIs changed
83
+ 3. Update API documentation if endpoints changed
84
+ 4. Verify all documentation links are valid
85
+ 5. Check code examples match current implementation
86
+
87
+ Provide a summary of all documentation updates made.
88
+ timeout: 60
89
+
90
+ # Step 5: Final checklist before release
91
+ - id: pre_release_check
92
+ name: Pre-release verification
93
+ description: Final comprehensive verification before shipping
94
+ agent: mindos
95
+ prompt: |
96
+ Perform final pre-release verification:
97
+
98
+ Checklist:
99
+ ☐ All tests passing
100
+ ☐ Code review completed and issues resolved
101
+ ☐ Security scan passed or risks accepted
102
+ ☐ Documentation updated and links valid
103
+ ☐ Version bumped correctly (semver)
104
+ ☐ Git tags and commits clean
105
+ ☐ No uncommitted changes
106
+ ☐ Changelog entry present
107
+ ☐ Dependencies updated and locked
108
+ ☐ Performance benchmarks acceptable
109
+
110
+ Confirm release readiness or list any blockers.
111
+ timeout: 60
112
+
113
+ # Step 6: Create release tag and prepare release notes
114
+ - id: create_release
115
+ name: Create release
116
+ description: Tag release and prepare release notes for publishing
117
+ tools:
118
+ - git
119
+ - npm
120
+ prompt: |
121
+ Prepare the project for release:
122
+
123
+ 1. Confirm version in package.json matches intended release
124
+ 2. Create git tag for this version (vX.Y.Z)
125
+ 3. Generate release notes from CHANGELOG.md
126
+ 4. Prepare npm release command (do not execute yet)
127
+ 5. List all deliverables included in this release
128
+
129
+ Provide step-by-step commands for final publishing.
130
+ timeout: 60
@@ -0,0 +1,84 @@
1
+ title: 周迭代检查工作流
2
+ description: 每周进行代码审查、测试运行和文档更新的标准工作流
3
+
4
+ # 全局配置 - 此工作流可用的技能
5
+ skills:
6
+ - software-architecture
7
+ - code-review-quality
8
+
9
+ # 工作流步骤 - 按顺序执行
10
+ steps:
11
+ # 第 1 步:运行测试套件
12
+ - id: run_tests
13
+ name: 运行测试
14
+ description: 执行完整测试套件并报告覆盖率
15
+ agent: cursor
16
+ prompt: |
17
+ 执行此项目的完整测试套件。
18
+
19
+ 提供以下信息:
20
+ 1. 运行的总测试数、通过数、失败数
21
+ 2. 覆盖率报告(行/分支/函数)
22
+ 3. 任何严重失败及修复建议
23
+ 4. 耗时
24
+
25
+ 如果有失败,列出前 3 个最严重的失败及建议的修复方案。
26
+ timeout: 120
27
+
28
+ # 第 2 步:代码审查
29
+ - id: code_review
30
+ name: 代码审查
31
+ description: 使用标准进行代码审查
32
+ agent: claude-code
33
+ skill: code-review-quality
34
+ prompt: |
35
+ 使用代码审查标准对最近的代码变更进行审查。
36
+
37
+ 评估以下方面:
38
+ 1. 正确性 - 错误处理、边界情况
39
+ 2. 安全性 - 认证、输入验证、密钥管理
40
+ 3. 性能 - 查询优化、缓存策略、复杂度
41
+ 4. 可维护性 - 命名规范、测试覆盖、文档完整性
42
+ 5. 架构 - 是否遵循项目模式,有无反模式
43
+
44
+ 给出评分(如 8.5/10)和主要建议。
45
+ timeout: 120
46
+
47
+ # 第 3 步:更新文档
48
+ - id: update_docs
49
+ name: 更新文档
50
+ description: 同步 CHANGELOG 和 README
51
+ skill: document-release
52
+ prompt: |
53
+ 根据本次发布的变更更新项目文档:
54
+
55
+ 1. 更新 CHANGELOG.md,遵循语义化版本规范
56
+ 2. 如果功能或 API 变更,更新 README.md
57
+ 3. 如果端点变更,更新 API 文档
58
+ 4. 验证所有文档链接有效
59
+ 5. 检查代码示例是否匹配当前实现
60
+
61
+ 提供所有文档变更的摘要。
62
+ timeout: 60
63
+
64
+ # 第 4 步:发布前最终检查
65
+ - id: final_check
66
+ name: 发布前验证
67
+ description: 最终确认一切就绪
68
+ agent: mindos
69
+ prompt: |
70
+ 进行最终的发布前验证检查:
71
+
72
+ 清单:
73
+ ☐ 所有测试通过
74
+ ☐ 代码审查完成并问题已解决
75
+ ☐ 文档已更新并链接有效
76
+ ☐ 版本号正确升级(语义化版本)
77
+ ☐ Git 标签和提交干净
78
+ ☐ 无未提交的更改
79
+ ☐ CHANGELOG 条目存在
80
+ ☐ 依赖项已更新并锁定
81
+ ☐ 性能基准可接受
82
+
83
+ 确认发布就绪或列出任何阻碍因素。
84
+ timeout: 60