openmatrix 0.1.56 → 0.1.57

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 CHANGED
@@ -386,6 +386,27 @@ Accept 阶段由 Reviewer Agent 执行:
386
386
  }
387
387
  ```
388
388
 
389
+ ## 状态存储
390
+
391
+ 任务状态持久化在 `.openmatrix/` 目录:
392
+
393
+ ```
394
+ .openmatrix/
395
+ ├── state.json # 全局状态 (runId, status, config, statistics)
396
+ ├── plan.md # AI 生成的执行计划
397
+ ├── tasks-input.json # 任务输入 (goals, constraints, deliverables)
398
+ ├── tasks/
399
+ │ └── TASK-001/
400
+ │ ├── task.json # 任务定义 + 状态 + 阶段信息
401
+ │ ├── context.md # Agent 上下文 (供后续 Agent 读取)
402
+ │ ├── develop.json # 开发阶段结果
403
+ │ ├── verify.json # 验证阶段结果 (质量门禁)
404
+ │ ├── accept.json # 验收阶段结果
405
+ │ └── artifacts/ # 产出文件 (result.md, quality-report.json 等)
406
+ ├── approvals/ # 审批记录
407
+ └── meetings/ # Meeting 记录
408
+ ```
409
+
389
410
  ---
390
411
 
391
412
  ## 多语言支持
@@ -465,6 +486,9 @@ cd openmatrix && npm install && npm run build && npm test
465
486
  - [x] `/om:brainstorm` 头脑风暴模式
466
487
  - [x] 多语言支持 (Python/Go/Java/TypeScript 等)
467
488
  - [x] E2E 测试支持 (Web/Mobile/GUI)
489
+ - [x] Agent 上下文共享 (Agent Memory)
490
+ - [x] Task 子目录结构 + Phase 结果持久化
491
+ - [x] 执行循环持久化 (`openmatrix step`/`complete` 防上下文压缩丢失)
468
492
  - [ ] VSCode 扩展
469
493
  - [ ] CI/CD 集成
470
494
 
@@ -7,11 +7,20 @@ import type { Task, AgentType, AgentResult } from '../../types/index.js';
7
7
  * - 分析技术方案
8
8
  * - 总结最佳实践
9
9
  * - 提供决策建议
10
+ *
11
+ * 支持动态领域感知,根据任务描述自动适配研究方向
10
12
  */
11
13
  export declare class ResearcherAgent {
12
14
  readonly type: AgentType;
13
15
  readonly capabilities: string[];
14
16
  execute(task: Task): Promise<AgentResult>;
15
- private buildResearchPrompt;
17
+ /**
18
+ * 构建动态领域感知的研究 Prompt
19
+ */
20
+ private buildDynamicResearchPrompt;
21
+ /**
22
+ * 从任务描述中提取研究上下文
23
+ */
24
+ private extractResearchContext;
16
25
  private generateRunId;
17
26
  }
@@ -9,6 +9,8 @@ exports.ResearcherAgent = void 0;
9
9
  * - 分析技术方案
10
10
  * - 总结最佳实践
11
11
  * - 提供决策建议
12
+ *
13
+ * 支持动态领域感知,根据任务描述自动适配研究方向
12
14
  */
13
15
  class ResearcherAgent {
14
16
  type = 'researcher';
@@ -16,7 +18,7 @@ class ResearcherAgent {
16
18
  async execute(task) {
17
19
  const startTime = Date.now();
18
20
  try {
19
- const prompt = this.buildResearchPrompt(task);
21
+ const prompt = this.buildDynamicResearchPrompt(task);
20
22
  return {
21
23
  runId: this.generateRunId(),
22
24
  taskId: task.id,
@@ -44,88 +46,208 @@ class ResearcherAgent {
44
46
  };
45
47
  }
46
48
  }
47
- buildResearchPrompt(task) {
49
+ /**
50
+ * 构建动态领域感知的研究 Prompt
51
+ */
52
+ buildDynamicResearchPrompt(task) {
53
+ // 从任务描述中提取领域和角色信息
54
+ const { domain, role, focus } = this.extractResearchContext(task.description);
48
55
  return `
49
56
  # 调研任务
50
57
 
51
- ## 调研问题
58
+ ## 研究领域
59
+ ${domain}
60
+
61
+ ## 角色定位
62
+ ${role}
63
+
64
+ ## 研究方向
65
+ ${focus}
52
66
 
67
+ ## 原始任务描述
53
68
  ${task.description}
54
69
 
55
70
  ## 调研步骤
56
71
 
57
72
  1. **搜索资料**
58
- - 官方文档
59
- - 技术博客
60
- - GitHub 仓库
61
- - Stack Overflow
73
+ - 使用 WebSearch 搜索领域核心概念
74
+ - 搜索行业标准、最佳实践
75
+ - 搜索主流技术方案和开源项目
76
+ - 搜索常见挑战和解决方案
62
77
 
63
- 2. **分析方案**
78
+ 2. **分析整理**
64
79
  - 功能对比
65
- - 性能对比
66
- - 社区支持
80
+ - 性能特点
81
+ - 社区生态
67
82
  - 学习曲线
83
+ - 适用场景
68
84
 
69
85
  3. **总结发现**
70
- - 关键信息
71
- - 优缺点
72
- - 适用场景
86
+ - 关键信息提炼
87
+ - 优缺点分析
88
+ - 决策建议
73
89
 
74
90
  ## 输出格式
75
91
 
76
92
  \`\`\`markdown
77
- # 调研报告
93
+ # ${domain} 调研报告
78
94
 
79
- ## 问题
80
- [调研的核心问题]
95
+ ## 核心发现
81
96
 
82
- ## 调研方法
83
- - 搜索关键词: ...
84
- - 参考来源: ...
97
+ [3-5 个关键发现,每个用一句话概括]
85
98
 
86
- ## 发现
99
+ 1. ...
100
+ 2. ...
101
+ 3. ...
87
102
 
88
- ### 方案 A: [名称]
89
- - 描述: ...
90
- - 优点:
91
- - ...
92
- - 缺点:
93
- - ...
94
- - 适用场景: ...
103
+ ## 详细分析
95
104
 
96
- ### 方案 B: [名称]
97
- - 描述: ...
98
- - 优点:
105
+ ### 发现 1: [标题]
106
+ - **描述**: ...
107
+ - **关键点**:
99
108
  - ...
100
- - 缺点:
101
- - ...
102
- - 适用场景: ...
109
+ - **注意事项**: ...
110
+
111
+ ### 发现 2: [标题]
112
+ ...
103
113
 
104
- ## 方案对比
114
+ ## 行业最佳实践
105
115
 
106
- | 维度 | 方案 A | 方案 B |
107
- |-----|--------|--------|
108
- | 性能 | ⭐⭐⭐ | ⭐⭐ |
109
- | 易用性 | ⭐⭐ | ⭐⭐⭐ |
110
- | 社区 | ⭐⭐⭐ | ⭐ |
116
+ 1. ...
117
+ 2. ...
118
+ 3. ...
119
+
120
+ ## 关键决策点
121
+
122
+ [用户需要做出的关键决策]
123
+
124
+ 1. **决策 1**: [决策描述]
125
+ - 选项 A: ... (适用场景)
126
+ - 选项 B: ... (适用场景)
127
+ - 建议: ...
128
+
129
+ 2. **决策 2**: ...
111
130
 
112
- ## 建议
131
+ ## 推荐方案
113
132
 
114
- **推荐方案**: [方案 X]
133
+ **首选方案**: ...
115
134
 
116
135
  **理由**:
117
136
  1. ...
118
137
  2. ...
119
138
 
139
+ **备选方案**: ...
140
+
120
141
  ## 参考资料
142
+
121
143
  1. [标题](链接)
144
+ 2. [标题](链接)
122
145
  \`\`\`
123
146
 
124
147
  ## 开始调研
125
148
 
126
149
  请使用 WebSearch 和 WebFetch 工具搜索相关信息。
150
+ 至少搜索 5 个相关关键词,覆盖官方文档、社区讨论、技术博客等维度。
127
151
  `;
128
152
  }
153
+ /**
154
+ * 从任务描述中提取研究上下文
155
+ */
156
+ extractResearchContext(description) {
157
+ const lower = description.toLowerCase();
158
+ // 领域关键词映射
159
+ const domainMap = [
160
+ {
161
+ keywords: ['游戏', 'game', 'gamedev', 'unity', 'unreal'],
162
+ domain: '游戏开发',
163
+ aspects: ['游戏类型', '目标平台', '技术架构', '美术风格', '盈利模式']
164
+ },
165
+ {
166
+ keywords: ['网站', 'website', 'web app', '门户'],
167
+ domain: 'Web 网站开发',
168
+ aspects: ['功能需求', '用户体验', '技术栈', 'SEO', '性能优化']
169
+ },
170
+ {
171
+ keywords: ['app', '移动应用', 'ios', 'android', 'flutter'],
172
+ domain: '移动应用开发',
173
+ aspects: ['平台选择', '用户界面', '性能优化', '发布流程', '用户增长']
174
+ },
175
+ {
176
+ keywords: ['支付', 'payment', 'stripe', '支付宝'],
177
+ domain: '支付系统',
178
+ aspects: ['支付方式', '安全合规', '风控策略', '对账结算', '国际化']
179
+ },
180
+ {
181
+ keywords: ['电商', 'ecommerce', 'shop', '商城'],
182
+ domain: '电商系统',
183
+ aspects: ['商品管理', '购物流程', '库存物流', '营销工具', '数据分析']
184
+ },
185
+ {
186
+ keywords: ['社交', 'social', 'community', '论坛'],
187
+ domain: '社交平台',
188
+ aspects: ['用户关系', '内容互动', '实时通讯', '内容审核', '推荐算法']
189
+ },
190
+ {
191
+ keywords: ['安全', 'security', 'auth', '认证', '加密'],
192
+ domain: '安全领域',
193
+ aspects: ['威胁模型', '认证授权', '数据保护', '审计监控', '合规要求']
194
+ },
195
+ {
196
+ keywords: ['后台', 'admin', 'dashboard', 'cms', '管理'],
197
+ domain: '后台管理系统',
198
+ aspects: ['权限模型', '数据看板', '工作流程', 'API 设计', '多租户']
199
+ },
200
+ {
201
+ keywords: ['ai', '人工智能', 'ml', '机器学习', '大模型', 'llm'],
202
+ domain: 'AI/机器学习',
203
+ aspects: ['模型选择', '数据处理', '训练部署', '性能优化', '伦理合规']
204
+ },
205
+ {
206
+ keywords: ['区块链', 'blockchain', 'web3', 'defi', 'nft'],
207
+ domain: '区块链',
208
+ aspects: ['链选择', '智能合约', '安全审计', '性能扩展', '合规监管']
209
+ },
210
+ {
211
+ keywords: ['音视频', 'streaming', '直播', 'rtc', 'webrtc'],
212
+ domain: '音视频',
213
+ aspects: ['编解码', '传输协议', '延迟优化', '存储分发', '实时互动']
214
+ }
215
+ ];
216
+ // 查找匹配的领域
217
+ for (const { keywords, domain, aspects } of domainMap) {
218
+ if (keywords.some(kw => lower.includes(kw))) {
219
+ return {
220
+ domain,
221
+ role: `${domain}专家`,
222
+ focus: `请重点调研以下方面: ${aspects.join('、')}`
223
+ };
224
+ }
225
+ }
226
+ // 通用领域:尝试从"做X"模式提取
227
+ const actionPatterns = [
228
+ /做(一个|个)(.+?)(的|app|网站|系统|平台|工具|应用|$)/,
229
+ /开发(一个|个)?(.+?)(系统|应用|平台|工具|$)/,
230
+ /构建(一个|个)?(.+?)(系统|应用|平台|工具|$)/,
231
+ /build (a |an )?(.+?)(app|website|system|tool|platform|$)/i,
232
+ ];
233
+ for (const pattern of actionPatterns) {
234
+ const match = description.match(pattern);
235
+ if (match && match[2]) {
236
+ const extracted = match[2].trim();
237
+ return {
238
+ domain: extracted,
239
+ role: `${extracted}领域专家`,
240
+ focus: `请调研 ${extracted} 的核心概念、技术方案、最佳实践、常见挑战`
241
+ };
242
+ }
243
+ }
244
+ // 默认:使用原始描述
245
+ return {
246
+ domain: '项目开发',
247
+ role: '技术顾问',
248
+ focus: '请调研相关技术方案、最佳实践、实现路径'
249
+ };
250
+ }
129
251
  generateRunId() {
130
252
  return `researcher-${Date.now().toString(36)}`;
131
253
  }
@@ -177,6 +177,8 @@ exports.brainstormCommand = new commander_1.Command('brainstorm')
177
177
  }
178
178
  // 生成头脑风暴问题
179
179
  const questions = generateBrainstormQuestions(taskContent, taskTitle);
180
+ // 检测是否涉及垂直领域
181
+ const domainDetection = detectVerticalDomain(taskContent);
180
182
  // 创建会话
181
183
  const session = {
182
184
  status: 'brainstorming',
@@ -185,12 +187,13 @@ exports.brainstormCommand = new commander_1.Command('brainstorm')
185
187
  questions,
186
188
  answers: {},
187
189
  insights: [],
188
- designNotes: []
190
+ designNotes: [],
191
+ suggestResearch: domainDetection.isVertical ? domainDetection.domain : undefined
189
192
  };
190
193
  await fs.writeFile(brainstormPath, JSON.stringify(session, null, 2));
191
194
  if (options.json) {
192
195
  // JSON 输出供 Skill 解析
193
- console.log(JSON.stringify({
196
+ const output = {
194
197
  status: 'brainstorming',
195
198
  message: '开始头脑风暴',
196
199
  taskTitle,
@@ -202,11 +205,21 @@ exports.brainstormCommand = new commander_1.Command('brainstorm')
202
205
  multiSelect: q.multiSelect
203
206
  })),
204
207
  hint: '请逐一回答问题,完成后再调用 --complete'
205
- }));
208
+ };
209
+ // 如果检测到垂直领域,添加建议
210
+ if (domainDetection.isVertical) {
211
+ output.suggestResearch = domainDetection.domain;
212
+ output.researchHint = `检测到垂直领域「${domainDetection.domain}」,建议先进行领域调研`;
213
+ }
214
+ console.log(JSON.stringify(output));
206
215
  }
207
216
  else {
208
217
  console.log('\n🧠 开始头脑风暴...\n');
209
218
  console.log(`📋 任务: ${taskTitle}\n`);
219
+ if (domainDetection.isVertical) {
220
+ console.log(`🔍 检测到垂直领域: ${domainDetection.domain}`);
221
+ console.log(' 建议使用 /om:research 进行领域调研\n');
222
+ }
210
223
  console.log('需要探索以下问题:');
211
224
  questions.forEach((q, i) => {
212
225
  console.log(` ${i + 1}. ${q.question}`);
@@ -214,6 +227,37 @@ exports.brainstormCommand = new commander_1.Command('brainstorm')
214
227
  console.log('\n💡 使用 /om:brainstorm 技能进行交互式问答');
215
228
  }
216
229
  });
230
+ /**
231
+ * 检测是否可能需要领域调研
232
+ * 不硬编码领域,只判断是否像垂直领域任务
233
+ */
234
+ function detectVerticalDomain(taskContent) {
235
+ const lower = taskContent.toLowerCase();
236
+ // 检测"做X"模式 - 这是垂直领域任务的典型特征
237
+ const actionPatterns = [
238
+ /做(一个|个)(.+?)(的|app|网站|系统|平台|工具|应用|游戏|$)/,
239
+ /开发(一个|个)?(.+?)(系统|应用|平台|工具|游戏|$)/,
240
+ /构建(一个|个)?(.+?)(系统|应用|平台|工具|$)/,
241
+ /build (a |an )?(.+?)(app|website|system|tool|platform|game|$)/i,
242
+ /create (a |an )?(.+?)(app|website|system|tool|platform|game|$)/i,
243
+ ];
244
+ for (const pattern of actionPatterns) {
245
+ const match = taskContent.match(pattern);
246
+ if (match && match[2]) {
247
+ const extracted = match[2].trim();
248
+ // 如果提取的内容有意义,认为是垂直领域任务
249
+ if (extracted.length > 1) {
250
+ return { isVertical: true, domain: extracted };
251
+ }
252
+ }
253
+ }
254
+ // 检测是否包含"系统"、"平台"、"应用"等大词
255
+ const systemKeywords = ['系统', '平台', '应用', 'system', 'platform', 'app'];
256
+ if (systemKeywords.some(kw => lower.includes(kw))) {
257
+ return { isVertical: true, domain: '待分析' };
258
+ }
259
+ return { isVertical: false, domain: '' };
260
+ }
217
261
  /**
218
262
  * 根据任务内容生成头脑风暴问题
219
263
  */
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const researchCommand: Command;
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.researchCommand = void 0;
37
+ // src/cli/commands/research.ts
38
+ const commander_1 = require("commander");
39
+ const gitignore_js_1 = require("../../utils/gitignore.js");
40
+ const fs = __importStar(require("fs/promises"));
41
+ const path = __importStar(require("path"));
42
+ /**
43
+ * 生成并行研究 Agent 配置
44
+ */
45
+ function generateAgents(topic, domain, aspects) {
46
+ return [
47
+ {
48
+ role: 'domain_researcher',
49
+ focus: `搜索 ${domain} 领域的核心概念、行业标准、最佳实践。关键词: ${aspects.slice(0, 4).join(', ')}`,
50
+ status: 'pending'
51
+ },
52
+ {
53
+ role: 'tech_explorer',
54
+ focus: `搜索 ${domain} 的主流技术方案、开源项目、技术栈选择、架构模式`,
55
+ status: 'pending'
56
+ },
57
+ {
58
+ role: 'scenario_analyst',
59
+ focus: `结合用户具体需求 "${topic}",分析实际应用场景、常见挑战、经验教训`,
60
+ status: 'pending'
61
+ }
62
+ ];
63
+ }
64
+ exports.researchCommand = new commander_1.Command('research')
65
+ .description('领域调研和问题探索 - 为后续任务提供知识基础')
66
+ .argument('[topic]', '研究主题')
67
+ .option('--json', '输出 JSON 格式 (供 Skill 解析)')
68
+ .option('--confirm', '确认进入深度研究 (从 Skill 传入)')
69
+ .option('--complete', '标记研究完成,生成报告和任务上下文')
70
+ .option('--results <json>', '研究结果 JSON (从 Skill 传入)')
71
+ .action(async (topic, options) => {
72
+ const basePath = process.cwd();
73
+ const omPath = path.join(basePath, '.openmatrix');
74
+ const researchPath = path.join(omPath, 'research');
75
+ const knowledgePath = path.join(researchPath, 'knowledge');
76
+ // 确保目录存在
77
+ await fs.mkdir(omPath, { recursive: true });
78
+ await fs.mkdir(researchPath, { recursive: true });
79
+ await fs.mkdir(knowledgePath, { recursive: true });
80
+ // 确保 .openmatrix 被 git 忽略
81
+ await (0, gitignore_js_1.ensureOpenmatrixGitignore)(basePath);
82
+ const sessionPath = path.join(researchPath, 'session.json');
83
+ // ========== --complete 模式: 研究完成,汇总结果 ==========
84
+ if (options.complete) {
85
+ try {
86
+ const sessionData = await fs.readFile(sessionPath, 'utf-8');
87
+ const session = JSON.parse(sessionData);
88
+ // 如果传入了结果,合并
89
+ if (options.results) {
90
+ try {
91
+ const results = JSON.parse(options.results);
92
+ if (results.agents)
93
+ session.agents = results.agents;
94
+ if (results.report)
95
+ session.report = results.report;
96
+ if (results.knowledge)
97
+ session.knowledge = [...session.knowledge, ...results.knowledge];
98
+ if (results.context)
99
+ session.context = results.context;
100
+ if (results.domainQuestions)
101
+ session.domainQuestions = results.domainQuestions;
102
+ if (results.answers)
103
+ session.answers = { ...session.answers, ...results.answers };
104
+ }
105
+ catch {
106
+ // 忽略解析错误
107
+ }
108
+ }
109
+ session.status = 'completed';
110
+ session.completedAt = new Date().toISOString();
111
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
112
+ // 写入研究报告
113
+ if (session.report) {
114
+ await fs.writeFile(path.join(researchPath, 'RESEARCH.md'), session.report, 'utf-8');
115
+ }
116
+ // 写入知识条目
117
+ for (let i = 0; i < session.knowledge.length; i++) {
118
+ await fs.writeFile(path.join(knowledgePath, `finding-${i + 1}.md`), session.knowledge[i], 'utf-8');
119
+ }
120
+ // 写入任务上下文 (供 start 使用)
121
+ const taskContext = session.context || { goals: [], constraints: [], deliverables: [] };
122
+ await fs.writeFile(path.join(researchPath, 'context.json'), JSON.stringify({
123
+ topic: session.topic,
124
+ domain: session.domain,
125
+ ...taskContext,
126
+ reportPath: '.openmatrix/research/RESEARCH.md',
127
+ knowledgePath: '.openmatrix/research/knowledge/'
128
+ }, null, 2), 'utf-8');
129
+ if (options.json) {
130
+ console.log(JSON.stringify({
131
+ status: 'completed',
132
+ message: '研究完成',
133
+ topic: session.topic,
134
+ domain: session.domain,
135
+ report: session.report,
136
+ knowledge: session.knowledge,
137
+ context: taskContext,
138
+ reportPath: '.openmatrix/research/RESEARCH.md',
139
+ hint: '研究结果已保存,可以使用 /om:start 开始执行任务'
140
+ }));
141
+ }
142
+ else {
143
+ console.log('研究完成!');
144
+ console.log(` 主题: ${session.topic}`);
145
+ console.log(` 领域: ${session.domain}`);
146
+ console.log(` 知识条目: ${session.knowledge.length} 个`);
147
+ console.log('\n使用 /om:start 基于研究结果开始任务');
148
+ }
149
+ return;
150
+ }
151
+ catch {
152
+ if (options.json) {
153
+ console.log(JSON.stringify({ status: 'error', message: '没有进行中的研究会话' }));
154
+ }
155
+ else {
156
+ console.log('没有进行中的研究会话');
157
+ console.log(' 使用 openmatrix research <topic> 开始新的研究');
158
+ }
159
+ return;
160
+ }
161
+ }
162
+ // ========== --confirm 模式: 用户确认后进入深度研究 ==========
163
+ if (options.confirm) {
164
+ try {
165
+ const sessionData = await fs.readFile(sessionPath, 'utf-8');
166
+ const session = JSON.parse(sessionData);
167
+ if (session.status !== 'preview') {
168
+ if (options.json) {
169
+ console.log(JSON.stringify({ status: 'error', message: `当前状态为 ${session.status},无法确认` }));
170
+ }
171
+ else {
172
+ console.log(`当前状态为 ${session.status},无法确认`);
173
+ }
174
+ return;
175
+ }
176
+ // 生成研究 Agent
177
+ const agents = generateAgents(session.topic, session.domain, session.aspects);
178
+ session.status = 'researching';
179
+ session.agents = agents;
180
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
181
+ if (options.json) {
182
+ console.log(JSON.stringify({
183
+ status: 'researching',
184
+ message: '开始深度研究',
185
+ topic: session.topic,
186
+ domain: session.domain,
187
+ aspects: session.aspects,
188
+ agents: agents.map(a => ({ role: a.role, focus: a.focus, status: a.status })),
189
+ hint: '使用 Agent 工具并行执行研究'
190
+ }));
191
+ }
192
+ else {
193
+ console.log('\n开始深度研究...\n');
194
+ console.log(` 主题: ${session.topic}`);
195
+ console.log(` 领域: ${session.domain}`);
196
+ console.log('\n研究 Agent:');
197
+ agents.forEach((a, i) => {
198
+ console.log(` ${i + 1}. [${a.role}] ${a.focus}`);
199
+ });
200
+ }
201
+ return;
202
+ }
203
+ catch {
204
+ if (options.json) {
205
+ console.log(JSON.stringify({ status: 'error', message: '没有待确认的研究会话' }));
206
+ }
207
+ else {
208
+ console.log('没有待确认的研究会话');
209
+ }
210
+ return;
211
+ }
212
+ }
213
+ // ========== 初始模式: 创建会话,等待 AI 分析 ==========
214
+ let researchTopic = topic;
215
+ if (!researchTopic) {
216
+ const defaultPath = path.join(basePath, 'RESEARCH.md');
217
+ try {
218
+ const content = await fs.readFile(defaultPath, 'utf-8');
219
+ const lines = content.split('\n');
220
+ for (const line of lines) {
221
+ const match = line.match(/^#\s+(.+)$/);
222
+ if (match) {
223
+ researchTopic = match[1].trim();
224
+ break;
225
+ }
226
+ }
227
+ if (!researchTopic)
228
+ researchTopic = content.slice(0, 100).trim();
229
+ if (!options.json)
230
+ console.log(`读取研究文件: ${defaultPath}`);
231
+ }
232
+ catch {
233
+ if (options.json) {
234
+ console.log(JSON.stringify({ status: 'error', message: '请提供研究主题' }));
235
+ }
236
+ else {
237
+ console.log('请提供研究主题');
238
+ console.log(' 用法: openmatrix research <topic>');
239
+ console.log(' 或创建 RESEARCH.md 文件');
240
+ }
241
+ return;
242
+ }
243
+ }
244
+ // 创建初始会话 - 领域信息由 Agent 分析后更新
245
+ const session = {
246
+ status: 'initialized',
247
+ topic: researchTopic,
248
+ domain: '',
249
+ aspects: [],
250
+ estimatedQuestions: 0,
251
+ agents: [],
252
+ domainQuestions: [],
253
+ answers: {},
254
+ knowledge: [],
255
+ createdAt: new Date().toISOString()
256
+ };
257
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
258
+ if (options.json) {
259
+ console.log(JSON.stringify({
260
+ status: 'initialized',
261
+ message: '研究会话已创建,需要 AI 分析领域',
262
+ topic: researchTopic,
263
+ hint: '请使用 Agent 分析主题,识别领域和调研方向,然后更新会话并展示给用户确认'
264
+ }));
265
+ }
266
+ else {
267
+ console.log(`\n研究主题: ${researchTopic}`);
268
+ console.log('使用 /om:research 技能启动 AI 分析');
269
+ }
270
+ });