openspec-mcp 0.1.0 → 0.2.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.
Files changed (92) hide show
  1. package/README.md +83 -35
  2. package/README.zh.md +81 -33
  3. package/dist/api/routes/changes.d.ts.map +1 -1
  4. package/dist/api/routes/changes.js +54 -0
  5. package/dist/api/routes/changes.js.map +1 -1
  6. package/dist/api/routes/project.d.ts +7 -0
  7. package/dist/api/routes/project.d.ts.map +1 -0
  8. package/dist/api/routes/project.js +14 -0
  9. package/dist/api/routes/project.js.map +1 -0
  10. package/dist/api/routes/specs.d.ts.map +1 -1
  11. package/dist/api/routes/specs.js +100 -1
  12. package/dist/api/routes/specs.js.map +1 -1
  13. package/dist/api/routes/tasks.d.ts.map +1 -1
  14. package/dist/api/routes/tasks.js +33 -0
  15. package/dist/api/routes/tasks.js.map +1 -1
  16. package/dist/api/server.d.ts +5 -1
  17. package/dist/api/server.d.ts.map +1 -1
  18. package/dist/api/server.js +107 -14
  19. package/dist/api/server.js.map +1 -1
  20. package/dist/core/approval-manager.test.d.ts +5 -0
  21. package/dist/core/approval-manager.test.d.ts.map +1 -0
  22. package/dist/core/approval-manager.test.js +114 -0
  23. package/dist/core/approval-manager.test.js.map +1 -0
  24. package/dist/core/file-watcher.d.ts.map +1 -1
  25. package/dist/core/file-watcher.js +13 -0
  26. package/dist/core/file-watcher.js.map +1 -1
  27. package/dist/core/hooks-manager.d.ts +43 -0
  28. package/dist/core/hooks-manager.d.ts.map +1 -0
  29. package/dist/core/hooks-manager.js +194 -0
  30. package/dist/core/hooks-manager.js.map +1 -0
  31. package/dist/core/openspec-cli.d.ts +12 -0
  32. package/dist/core/openspec-cli.d.ts.map +1 -1
  33. package/dist/core/openspec-cli.js +85 -0
  34. package/dist/core/openspec-cli.js.map +1 -1
  35. package/dist/core/proposal-generator.d.ts +46 -0
  36. package/dist/core/proposal-generator.d.ts.map +1 -0
  37. package/dist/core/proposal-generator.js +155 -0
  38. package/dist/core/proposal-generator.js.map +1 -0
  39. package/dist/core/review-manager.d.ts +147 -0
  40. package/dist/core/review-manager.d.ts.map +1 -0
  41. package/dist/core/review-manager.js +235 -0
  42. package/dist/core/review-manager.js.map +1 -0
  43. package/dist/core/spec-parser.d.ts +51 -0
  44. package/dist/core/spec-parser.d.ts.map +1 -0
  45. package/dist/core/spec-parser.js +130 -0
  46. package/dist/core/spec-parser.js.map +1 -0
  47. package/dist/core/task-parser.test.d.ts +5 -0
  48. package/dist/core/task-parser.test.d.ts.map +1 -0
  49. package/dist/core/task-parser.test.js +124 -0
  50. package/dist/core/task-parser.test.js.map +1 -0
  51. package/dist/core/template-manager.d.ts +48 -0
  52. package/dist/core/template-manager.d.ts.map +1 -0
  53. package/dist/core/template-manager.js +268 -0
  54. package/dist/core/template-manager.js.map +1 -0
  55. package/dist/index.js +17 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/server/tools/generator.d.ts +8 -0
  58. package/dist/server/tools/generator.d.ts.map +1 -0
  59. package/dist/server/tools/generator.js +121 -0
  60. package/dist/server/tools/generator.js.map +1 -0
  61. package/dist/server/tools/hooks.d.ts +8 -0
  62. package/dist/server/tools/hooks.d.ts.map +1 -0
  63. package/dist/server/tools/hooks.js +86 -0
  64. package/dist/server/tools/hooks.js.map +1 -0
  65. package/dist/server/tools/management.d.ts.map +1 -1
  66. package/dist/server/tools/management.js +37 -2
  67. package/dist/server/tools/management.js.map +1 -1
  68. package/dist/server/tools/reviews.d.ts +8 -0
  69. package/dist/server/tools/reviews.d.ts.map +1 -0
  70. package/dist/server/tools/reviews.js +178 -0
  71. package/dist/server/tools/reviews.js.map +1 -0
  72. package/dist/server/tools/tasks.d.ts.map +1 -1
  73. package/dist/server/tools/tasks.js +38 -0
  74. package/dist/server/tools/tasks.js.map +1 -1
  75. package/dist/server/tools/templates.d.ts +8 -0
  76. package/dist/server/tools/templates.d.ts.map +1 -0
  77. package/dist/server/tools/templates.js +89 -0
  78. package/dist/server/tools/templates.js.map +1 -0
  79. package/dist/utils/constants.d.ts +54 -0
  80. package/dist/utils/constants.d.ts.map +1 -0
  81. package/dist/utils/constants.js +54 -0
  82. package/dist/utils/constants.js.map +1 -0
  83. package/dist/utils/version.d.ts +13 -0
  84. package/dist/utils/version.d.ts.map +1 -0
  85. package/dist/utils/version.js +26 -0
  86. package/dist/utils/version.js.map +1 -0
  87. package/package.json +2 -6
  88. package/web/dist/assets/index-BGNTCJhf.css +1 -0
  89. package/web/dist/assets/index-DKBVRb7-.js +99 -0
  90. package/web/dist/index.html +2 -2
  91. package/web/dist/assets/index--LppUKpS.js +0 -67
  92. package/web/dist/assets/index-DdJQfs9Z.css +0 -1
@@ -57,5 +57,38 @@ export function registerTasksRoutes(fastify, ctx) {
57
57
  },
58
58
  };
59
59
  });
60
+ /**
61
+ * POST /api/changes/:id/tasks/batch - 批量更新任务状态
62
+ */
63
+ fastify.post('/changes/:id/tasks/batch', async (request, reply) => {
64
+ const { id } = request.params;
65
+ const { updates } = request.body;
66
+ if (!Array.isArray(updates) || updates.length === 0) {
67
+ return reply.status(400).send({ error: 'updates array is required' });
68
+ }
69
+ const results = [];
70
+ for (const update of updates) {
71
+ if (!['pending', 'in_progress', 'done'].includes(update.status)) {
72
+ results.push({ taskId: update.taskId, success: false, error: 'Invalid status' });
73
+ continue;
74
+ }
75
+ const result = await cli.updateTaskStatus(id, update.taskId, update.status);
76
+ results.push({
77
+ taskId: update.taskId,
78
+ success: result.success,
79
+ error: result.error,
80
+ });
81
+ }
82
+ const successCount = results.filter((r) => r.success).length;
83
+ // 广播批量更新事件
84
+ ctx.broadcast('tasks:batch_updated', { changeId: id, results });
85
+ return {
86
+ changeId: id,
87
+ total: updates.length,
88
+ success: successCount,
89
+ failed: updates.length - successCount,
90
+ results,
91
+ };
92
+ });
60
93
  }
61
94
  //# sourceMappingURL=tasks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/api/routes/tasks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,mBAAmB,CAAC,OAAwB,EAAE,GAAe;IAC3E,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACzD,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAwB,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH;;OAEG;IACH,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACnE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAwC,CAAC;QACxE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAsD,CAAC;QAElF,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAE9D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,WAAW;YACX,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH;;OAEG;IACH,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QAClC,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,EAAE,CAAC;QAErB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC;gBACb,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;QAED,SAAS;QACT,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC3E,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACnF,MAAM,iBAAiB,GACrB,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvE,OAAO;YACL,SAAS;YACT,OAAO,EAAE;gBACP,KAAK,EAAE,UAAU;gBACjB,SAAS,EAAE,cAAc;gBACzB,UAAU,EAAE,iBAAiB;aAC9B;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/api/routes/tasks.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,9 @@
5
5
  import { FastifyInstance } from 'fastify';
6
6
  import { OpenSpecCli } from '../core/openspec-cli.js';
7
7
  import { ApprovalManager } from '../core/approval-manager.js';
8
+ import { ReviewManager } from '../core/review-manager.js';
8
9
  import { FileWatcher } from '../core/file-watcher.js';
10
+ import { SpecParser } from '../core/spec-parser.js';
9
11
  export interface ApiServerOptions {
10
12
  cwd: string;
11
13
  port: number;
@@ -13,8 +15,10 @@ export interface ApiServerOptions {
13
15
  export interface ApiContext {
14
16
  cli: OpenSpecCli;
15
17
  approvalManager: ApprovalManager;
18
+ reviewManager: ReviewManager;
19
+ specParser: SpecParser;
16
20
  fileWatcher: FileWatcher;
17
- broadcast: (event: string, data: any) => void;
21
+ broadcast: (event: string, data: any, topic?: string) => void;
18
22
  }
19
23
  /**
20
24
  * 创建并启动 API 服务器
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAMnD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAStD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,WAAW,CAAC;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA+IxF"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAOnD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAWpD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,WAAW,CAAC;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/D;AA2CD;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA+MxF"}
@@ -10,13 +10,51 @@ import * as path from 'path';
10
10
  import { fileURLToPath } from 'url';
11
11
  import { OpenSpecCli } from '../core/openspec-cli.js';
12
12
  import { ApprovalManager } from '../core/approval-manager.js';
13
+ import { ReviewManager } from '../core/review-manager.js';
13
14
  import { FileWatcher } from '../core/file-watcher.js';
15
+ import { SpecParser } from '../core/spec-parser.js';
14
16
  import { registerChangesRoutes } from './routes/changes.js';
15
17
  import { registerSpecsRoutes } from './routes/specs.js';
16
18
  import { registerTasksRoutes } from './routes/tasks.js';
17
19
  import { registerApprovalsRoutes } from './routes/approvals.js';
20
+ import { registerProjectRoutes } from './routes/project.js';
21
+ import { VERSION } from '../utils/version.js';
18
22
  const __filename = fileURLToPath(import.meta.url);
19
23
  const __dirname = path.dirname(__filename);
24
+ const MAX_PORT_ATTEMPTS = 20;
25
+ function isAddressInUse(error) {
26
+ return (typeof error === 'object' &&
27
+ error !== null &&
28
+ 'code' in error &&
29
+ error.code === 'EADDRINUSE');
30
+ }
31
+ function resolveActualPort(instance, fallback) {
32
+ const address = instance.server.address();
33
+ if (address && typeof address === 'object') {
34
+ return address.port ?? fallback;
35
+ }
36
+ return fallback;
37
+ }
38
+ async function listenWithFallback(instance, preferredPort) {
39
+ if (preferredPort === 0) {
40
+ await instance.listen({ port: 0, host: '0.0.0.0' });
41
+ return resolveActualPort(instance, preferredPort);
42
+ }
43
+ let port = preferredPort;
44
+ for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt += 1) {
45
+ try {
46
+ await instance.listen({ port, host: '0.0.0.0' });
47
+ return resolveActualPort(instance, port);
48
+ }
49
+ catch (error) {
50
+ if (!isAddressInUse(error)) {
51
+ throw error;
52
+ }
53
+ port += 1;
54
+ }
55
+ }
56
+ throw new Error(`No available port found starting from ${preferredPort}`);
57
+ }
20
58
  /**
21
59
  * 创建并启动 API 服务器
22
60
  */
@@ -46,16 +84,29 @@ export async function startApiServer(options) {
46
84
  // 创建核心模块
47
85
  const cli = new OpenSpecCli({ cwd });
48
86
  const approvalManager = new ApprovalManager({ cwd });
87
+ const reviewManager = new ReviewManager({ cwd });
88
+ const specParser = new SpecParser({ cwd });
49
89
  const fileWatcher = new FileWatcher({ cwd });
50
90
  // WebSocket 客户端列表
51
91
  const wsClients = new Set();
52
- // 广播函数
53
- const broadcast = (event, data) => {
92
+ // 客户端订阅管理 (socket -> Set<topic>)
93
+ const subscriptions = new Map();
94
+ // 广播函数 (支持按主题过滤)
95
+ const broadcast = (event, data, topic) => {
54
96
  const message = JSON.stringify({ event, data, timestamp: new Date().toISOString() });
55
97
  for (const client of wsClients) {
56
98
  if (client.readyState === 1) {
57
99
  // OPEN
58
- client.send(message);
100
+ // 如果指定了主题,只发送给订阅了该主题的客户端
101
+ if (topic) {
102
+ const clientTopics = subscriptions.get(client);
103
+ if (clientTopics?.has(topic) || clientTopics?.has('*')) {
104
+ client.send(message);
105
+ }
106
+ }
107
+ else {
108
+ client.send(message);
109
+ }
59
110
  }
60
111
  }
61
112
  };
@@ -63,6 +114,8 @@ export async function startApiServer(options) {
63
114
  const ctx = {
64
115
  cli,
65
116
  approvalManager,
117
+ reviewManager,
118
+ specParser,
66
119
  fileWatcher,
67
120
  broadcast,
68
121
  };
@@ -70,7 +123,8 @@ export async function startApiServer(options) {
70
123
  fastify.get('/ws', { websocket: true }, (connection) => {
71
124
  const { socket } = connection;
72
125
  wsClients.add(socket);
73
- console.log(`WebSocket client connected. Total: ${wsClients.size}`);
126
+ subscriptions.set(socket, new Set(['*'])); // 默认订阅所有
127
+ fastify.log.info(`WebSocket client connected. Total: ${wsClients.size}`);
74
128
  // 发送欢迎消息
75
129
  socket.send(JSON.stringify({
76
130
  event: 'connected',
@@ -80,19 +134,41 @@ export async function startApiServer(options) {
80
134
  socket.on('message', (message) => {
81
135
  try {
82
136
  const data = JSON.parse(message.toString());
83
- console.log('WebSocket message:', data);
84
- // 处理订阅请求等
137
+ fastify.log.info({ msg: 'WebSocket message', data });
138
+ // 处理订阅请求
85
139
  if (data.type === 'subscribe') {
86
- // TODO: 实现订阅逻辑
140
+ const topics = data.topics || [];
141
+ const clientSubs = subscriptions.get(socket) || new Set();
142
+ topics.forEach((t) => clientSubs.add(t));
143
+ subscriptions.set(socket, clientSubs);
144
+ socket.send(JSON.stringify({
145
+ event: 'subscribed',
146
+ data: { topics: Array.from(clientSubs) },
147
+ timestamp: new Date().toISOString(),
148
+ }));
149
+ }
150
+ // 处理取消订阅
151
+ if (data.type === 'unsubscribe') {
152
+ const topics = data.topics || [];
153
+ const clientSubs = subscriptions.get(socket);
154
+ if (clientSubs) {
155
+ topics.forEach((t) => clientSubs.delete(t));
156
+ }
157
+ socket.send(JSON.stringify({
158
+ event: 'unsubscribed',
159
+ data: { topics, remaining: clientSubs ? Array.from(clientSubs) : [] },
160
+ timestamp: new Date().toISOString(),
161
+ }));
87
162
  }
88
163
  }
89
164
  catch (e) {
90
- console.error('Invalid WebSocket message:', e);
165
+ fastify.log.error({ msg: 'Invalid WebSocket message', error: e });
91
166
  }
92
167
  });
93
168
  socket.on('close', () => {
94
169
  wsClients.delete(socket);
95
- console.log(`WebSocket client disconnected. Total: ${wsClients.size}`);
170
+ subscriptions.delete(socket);
171
+ fastify.log.info(`WebSocket client disconnected. Total: ${wsClients.size}`);
96
172
  });
97
173
  });
98
174
  // 注册 REST 路由
@@ -101,10 +177,11 @@ export async function startApiServer(options) {
101
177
  registerSpecsRoutes(instance, ctx);
102
178
  registerTasksRoutes(instance, ctx);
103
179
  registerApprovalsRoutes(instance, ctx);
180
+ registerProjectRoutes(instance, ctx);
104
181
  }, { prefix: '/api' });
105
182
  // 健康检查
106
183
  fastify.get('/health', async () => {
107
- return { status: 'ok', version: '0.1.0' };
184
+ return { status: 'ok', version: VERSION };
108
185
  });
109
186
  // SPA fallback - 所有非 API 路由返回 index.html
110
187
  fastify.setNotFoundHandler(async (request, reply) => {
@@ -114,14 +191,30 @@ export async function startApiServer(options) {
114
191
  return reply.code(404).send({ error: 'Not Found', statusCode: 404 });
115
192
  });
116
193
  // 启动文件监控
117
- fileWatcher.on('change', (event, filePath) => {
118
- broadcast('file:changed', { event, filePath });
194
+ fileWatcher.on('change', (event, fileInfo) => {
195
+ broadcast('file:changed', { event, filePath: fileInfo });
196
+ // 处理 review 文件变化 - 广播 reviews:updated 事件
197
+ if (typeof fileInfo === 'object' && fileInfo.type?.startsWith('review:')) {
198
+ const targetType = fileInfo.type.replace('review:', '');
199
+ const match = fileInfo.path?.match(/reviews\/changes\/([^/]+)\//);
200
+ const changeId = match ? match[1] : null;
201
+ if (changeId && ['proposal', 'design', 'tasks'].includes(targetType)) {
202
+ broadcast('reviews:updated', {
203
+ changeId,
204
+ targetType,
205
+ timestamp: new Date().toISOString()
206
+ }, 'reviews');
207
+ }
208
+ }
119
209
  });
120
210
  await fileWatcher.start();
121
211
  // 启动服务器
122
212
  try {
123
- await fastify.listen({ port, host: '0.0.0.0' });
124
- console.log(`\n🚀 OpenSpec MCP Dashboard running at http://localhost:${port}`);
213
+ const actualPort = await listenWithFallback(fastify, port);
214
+ if (actualPort !== port || port === 0) {
215
+ fastify.log.warn(`Dashboard port ${port} unavailable, using ${actualPort} instead`);
216
+ }
217
+ console.log(`\n🚀 OpenSpec MCP Dashboard running at http://localhost:${actualPort}`);
125
218
  console.log(`📁 Watching: ${cwd}/openspec`);
126
219
  }
127
220
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,OAA4B,MAAM,SAAS,CAAC;AACnD,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAClD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAc3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAyB;IAC5D,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAE9B,gBAAgB;IAChB,MAAM,OAAO,GAAG,OAAO,CAAC;QACtB,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,OAAO;IACP,MAAM,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE;QAClC,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAEzC,wBAAwB;IACxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE;YACpC,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,GAAG;SACZ,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;QACtB,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;IAChE,CAAC;IAED,SAAS;IACT,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACrC,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAE7C,kBAAkB;IAClB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAO,CAAC;IAEjC,OAAO;IACP,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,IAAS,EAAE,EAAE;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACrF,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;YAC/B,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO;gBACP,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,UAAU;IACV,MAAM,GAAG,GAAe;QACtB,GAAG;QACH,eAAe;QACf,WAAW;QACX,SAAS;KACV,CAAC;IAEF,kBAAkB;IAClB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE;QACrD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;QAE9B,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,sCAAsC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAEpE,SAAS;QACT,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,EAAE,OAAO,EAAE,qCAAqC,EAAE;YACxD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CACH,CAAC;QAEF,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAY,EAAE,EAAE;YACpC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;gBAExC,UAAU;gBACV,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAC9B,eAAe;gBACjB,CAAC;YACH,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;YACjD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,yCAAyC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,aAAa;IACb,MAAM,OAAO,CAAC,QAAQ,CACpB,KAAK,EAAE,QAAQ,EAAE,EAAE;QACjB,qBAAqB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACrC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACnC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACnC,uBAAuB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC,EACD,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;IAEF,OAAO;IACP,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAChC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,yCAAyC;IACzC,OAAO,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACvE,OAAO,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,SAAS;IACT,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC3C,SAAS,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;IAE1B,QAAQ;IACR,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,2DAA2D,IAAI,EAAE,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,WAAW,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO;IACP,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * ApprovalManager 单元测试
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=approval-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-manager.test.d.ts","sourceRoot":"","sources":["../../src/core/approval-manager.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * ApprovalManager 单元测试
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
+ import { ApprovalManager } from './approval-manager.js';
6
+ import * as fs from 'fs/promises';
7
+ import * as path from 'path';
8
+ import * as os from 'os';
9
+ describe('ApprovalManager', () => {
10
+ let tempDir;
11
+ let manager;
12
+ beforeEach(async () => {
13
+ // 创建临时目录
14
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'approval-test-'));
15
+ await fs.mkdir(path.join(tempDir, 'openspec', 'approvals'), { recursive: true });
16
+ manager = new ApprovalManager({ cwd: tempDir });
17
+ });
18
+ afterEach(async () => {
19
+ // 清理临时目录
20
+ await fs.rm(tempDir, { recursive: true, force: true });
21
+ });
22
+ describe('requestApproval', () => {
23
+ it('should create a new approval record', async () => {
24
+ const record = await manager.requestApproval('test-change', 'user1');
25
+ expect(record.changeId).toBe('test-change');
26
+ expect(record.status).toBe('pending_approval');
27
+ expect(record.requestedBy).toBe('user1');
28
+ expect(record.history).toHaveLength(1);
29
+ expect(record.history[0].action).toBe('request_approval');
30
+ });
31
+ it('should include reviewers when specified', async () => {
32
+ const record = await manager.requestApproval('test-change', 'user1', ['reviewer1', 'reviewer2']);
33
+ expect(record.reviewers).toEqual(['reviewer1', 'reviewer2']);
34
+ });
35
+ });
36
+ describe('approve', () => {
37
+ it('should approve a pending approval', async () => {
38
+ await manager.requestApproval('test-change', 'user1');
39
+ const record = await manager.approve('test-change', 'approver1', 'Looks good!');
40
+ expect(record.status).toBe('approved');
41
+ expect(record.approvals).toHaveLength(1);
42
+ expect(record.approvals[0].approver).toBe('approver1');
43
+ expect(record.approvals[0].comment).toBe('Looks good!');
44
+ });
45
+ it('should throw error for non-existent change', async () => {
46
+ await expect(manager.approve('non-existent', 'approver1')).rejects.toThrow('No approval record found');
47
+ });
48
+ it('should throw error for non-pending approval', async () => {
49
+ const record = await manager.requestApproval('test-change', 'user1');
50
+ await manager.approve('test-change', 'approver1');
51
+ await expect(manager.approve('test-change', 'approver2')).rejects.toThrow('Must be pending_approval');
52
+ });
53
+ });
54
+ describe('reject', () => {
55
+ it('should reject a pending approval', async () => {
56
+ await manager.requestApproval('test-change', 'user1');
57
+ const record = await manager.reject('test-change', 'reviewer1', 'Needs more work');
58
+ expect(record.status).toBe('rejected');
59
+ expect(record.rejections).toHaveLength(1);
60
+ expect(record.rejections[0].rejector).toBe('reviewer1');
61
+ expect(record.rejections[0].reason).toBe('Needs more work');
62
+ });
63
+ });
64
+ describe('status flow', () => {
65
+ it('should support full approval workflow', async () => {
66
+ // Request approval
67
+ let record = await manager.requestApproval('test-change', 'author');
68
+ expect(record.status).toBe('pending_approval');
69
+ // Approve
70
+ record = await manager.approve('test-change', 'reviewer');
71
+ expect(record.status).toBe('approved');
72
+ // Start implementation
73
+ record = await manager.startImplementation('test-change', 'author');
74
+ expect(record.status).toBe('implementing');
75
+ // Mark completed
76
+ record = await manager.markCompleted('test-change', 'author');
77
+ expect(record.status).toBe('completed');
78
+ // Verify history
79
+ expect(record.history).toHaveLength(4);
80
+ });
81
+ it('should support rejection and resubmission', async () => {
82
+ // Request approval
83
+ await manager.requestApproval('test-change', 'author');
84
+ // Reject
85
+ let record = await manager.reject('test-change', 'reviewer', 'Fix issues');
86
+ expect(record.status).toBe('rejected');
87
+ // Reset to draft
88
+ record = await manager.resetToDraft('test-change', 'author');
89
+ expect(record.status).toBe('draft');
90
+ // Request again
91
+ record = await manager.requestApproval('test-change', 'author');
92
+ expect(record.status).toBe('pending_approval');
93
+ });
94
+ });
95
+ describe('listApprovals', () => {
96
+ it('should list all approval records', async () => {
97
+ await manager.requestApproval('change-1', 'user1');
98
+ await manager.requestApproval('change-2', 'user2');
99
+ const records = await manager.listApprovals();
100
+ expect(records).toHaveLength(2);
101
+ });
102
+ });
103
+ describe('listPendingApprovals', () => {
104
+ it('should return only pending approvals', async () => {
105
+ await manager.requestApproval('change-1', 'user1');
106
+ await manager.requestApproval('change-2', 'user2');
107
+ await manager.approve('change-1', 'approver');
108
+ const pending = await manager.listPendingApprovals();
109
+ expect(pending).toHaveLength(1);
110
+ expect(pending[0].changeId).toBe('change-2');
111
+ });
112
+ });
113
+ });
114
+ //# sourceMappingURL=approval-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-manager.test.js","sourceRoot":"","sources":["../../src/core/approval-manager.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../src/core/file-watcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA0B;gBAE7B,OAAO,EAAE,kBAAkB;IAKvC;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,OAAO,CAAC,WAAW;IA0BnB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;IACH,UAAU,IAAI,OAAO;CAGtB"}
1
+ {"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../src/core/file-watcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA0B;gBAE7B,OAAO,EAAE,kBAAkB;IAKvC;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAuCnB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;IACH,UAAU,IAAI,OAAO;CAGtB"}
@@ -86,6 +86,19 @@ export class FileWatcher extends EventEmitter {
86
86
  if (relativePath.includes('openspec/changes/archive/')) {
87
87
  return 'archive';
88
88
  }
89
+ if (relativePath.includes('openspec/reviews/')) {
90
+ // Extract target type from path: reviews/changes/{changeId}/{targetType}.json
91
+ if (relativePath.includes('/changes/')) {
92
+ const match = relativePath.match(/\/changes\/([^/]+)\/(\w+)\.json$/);
93
+ if (match) {
94
+ return `review:${match[2]}`; // review:proposal, review:design, review:tasks
95
+ }
96
+ }
97
+ if (relativePath.includes('/specs/')) {
98
+ return 'review:spec';
99
+ }
100
+ return 'review';
101
+ }
89
102
  if (relativePath.includes('openspec/changes/')) {
90
103
  if (relativePath.endsWith('proposal.md'))
91
104
  return 'proposal';
@@ -1 +1 @@
1
- {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../src/core/file-watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../src/core/file-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Git Hooks 管理器
3
+ * 管理 OpenSpec Git hooks 的安装和卸载
4
+ */
5
+ export declare class HooksManager {
6
+ private cwd;
7
+ constructor(options?: {
8
+ cwd?: string;
9
+ });
10
+ /**
11
+ * 获取 Git hooks 目录
12
+ */
13
+ private getHooksDir;
14
+ /**
15
+ * 检查是否在 Git 仓库中
16
+ */
17
+ isGitRepo(): Promise<boolean>;
18
+ /**
19
+ * 获取已安装的 hooks
20
+ */
21
+ getInstalledHooks(): Promise<string[]>;
22
+ /**
23
+ * 安装 Git hooks
24
+ */
25
+ install(): Promise<{
26
+ success: boolean;
27
+ installed: string[];
28
+ error?: string;
29
+ }>;
30
+ /**
31
+ * 安装单个 hook
32
+ */
33
+ private installHook;
34
+ /**
35
+ * 卸载 Git hooks
36
+ */
37
+ uninstall(): Promise<{
38
+ success: boolean;
39
+ removed: string[];
40
+ error?: string;
41
+ }>;
42
+ }
43
+ //# sourceMappingURL=hooks-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-manager.d.ts","sourceRoot":"","sources":["../../src/core/hooks-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmEH,qBAAa,YAAY;IACvB,OAAO,CAAC,GAAG,CAAS;gBAER,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE;IAItC;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IASnC;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAmB5C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC;QACvB,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IA4BF;;OAEG;YACW,WAAW;IAmBzB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CAgCH"}