openmatrix 0.1.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 (85) hide show
  1. package/README.md +512 -0
  2. package/dist/agents/agent-runner.d.ts +152 -0
  3. package/dist/agents/agent-runner.js +656 -0
  4. package/dist/agents/base-agent.d.ts +46 -0
  5. package/dist/agents/base-agent.js +17 -0
  6. package/dist/agents/impl/coder-agent.d.ts +17 -0
  7. package/dist/agents/impl/coder-agent.js +96 -0
  8. package/dist/agents/impl/executor-agent.d.ts +32 -0
  9. package/dist/agents/impl/executor-agent.js +168 -0
  10. package/dist/agents/impl/index.d.ts +6 -0
  11. package/dist/agents/impl/index.js +17 -0
  12. package/dist/agents/impl/planner-agent.d.ts +24 -0
  13. package/dist/agents/impl/planner-agent.js +126 -0
  14. package/dist/agents/impl/researcher-agent.d.ts +17 -0
  15. package/dist/agents/impl/researcher-agent.js +133 -0
  16. package/dist/agents/impl/reviewer-agent.d.ts +17 -0
  17. package/dist/agents/impl/reviewer-agent.js +120 -0
  18. package/dist/agents/impl/tester-agent.d.ts +17 -0
  19. package/dist/agents/impl/tester-agent.js +110 -0
  20. package/dist/cli/commands/approve.d.ts +2 -0
  21. package/dist/cli/commands/approve.js +87 -0
  22. package/dist/cli/commands/meeting.d.ts +2 -0
  23. package/dist/cli/commands/meeting.js +245 -0
  24. package/dist/cli/commands/report.d.ts +2 -0
  25. package/dist/cli/commands/report.js +202 -0
  26. package/dist/cli/commands/resume.d.ts +2 -0
  27. package/dist/cli/commands/resume.js +104 -0
  28. package/dist/cli/commands/retry.d.ts +2 -0
  29. package/dist/cli/commands/retry.js +79 -0
  30. package/dist/cli/commands/start.d.ts +2 -0
  31. package/dist/cli/commands/start.js +252 -0
  32. package/dist/cli/commands/status.d.ts +2 -0
  33. package/dist/cli/commands/status.js +226 -0
  34. package/dist/cli/index.d.ts +2 -0
  35. package/dist/cli/index.js +26 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +9 -0
  38. package/dist/orchestrator/ai-reviewer.d.ts +50 -0
  39. package/dist/orchestrator/ai-reviewer.js +326 -0
  40. package/dist/orchestrator/approval-manager.d.ts +62 -0
  41. package/dist/orchestrator/approval-manager.js +160 -0
  42. package/dist/orchestrator/executor.d.ts +114 -0
  43. package/dist/orchestrator/executor.js +325 -0
  44. package/dist/orchestrator/full-test-runner.d.ts +122 -0
  45. package/dist/orchestrator/full-test-runner.js +335 -0
  46. package/dist/orchestrator/git-commit-manager.d.ts +75 -0
  47. package/dist/orchestrator/git-commit-manager.js +248 -0
  48. package/dist/orchestrator/interactive-question-generator.d.ts +90 -0
  49. package/dist/orchestrator/interactive-question-generator.js +312 -0
  50. package/dist/orchestrator/meeting-manager.d.ts +85 -0
  51. package/dist/orchestrator/meeting-manager.js +222 -0
  52. package/dist/orchestrator/phase-executor.d.ts +198 -0
  53. package/dist/orchestrator/phase-executor.js +796 -0
  54. package/dist/orchestrator/question-generator.d.ts +22 -0
  55. package/dist/orchestrator/question-generator.js +102 -0
  56. package/dist/orchestrator/retry-manager.d.ts +41 -0
  57. package/dist/orchestrator/retry-manager.js +83 -0
  58. package/dist/orchestrator/scheduler.d.ts +62 -0
  59. package/dist/orchestrator/scheduler.js +148 -0
  60. package/dist/orchestrator/state-machine.d.ts +53 -0
  61. package/dist/orchestrator/state-machine.js +124 -0
  62. package/dist/orchestrator/task-parser.d.ts +7 -0
  63. package/dist/orchestrator/task-parser.js +63 -0
  64. package/dist/orchestrator/task-planner.d.ts +71 -0
  65. package/dist/orchestrator/task-planner.js +316 -0
  66. package/dist/storage/file-store.d.ts +12 -0
  67. package/dist/storage/file-store.js +80 -0
  68. package/dist/storage/state-manager.d.ts +31 -0
  69. package/dist/storage/state-manager.js +202 -0
  70. package/dist/types/index.d.ts +193 -0
  71. package/dist/types/index.js +30 -0
  72. package/dist/utils/logger.d.ts +41 -0
  73. package/dist/utils/logger.js +166 -0
  74. package/dist/utils/progress-reporter.d.ts +116 -0
  75. package/dist/utils/progress-reporter.js +287 -0
  76. package/package.json +50 -0
  77. package/scripts/build-check.js +19 -0
  78. package/scripts/install-skills.js +51 -0
  79. package/skills/approve.md +253 -0
  80. package/skills/meeting.md +346 -0
  81. package/skills/report.md +100 -0
  82. package/skills/resume.md +68 -0
  83. package/skills/retry.md +61 -0
  84. package/skills/start.md +449 -0
  85. package/skills/status.md +46 -0
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StateManager = void 0;
4
+ const file_store_js_1 = require("./file-store.js");
5
+ const DEFAULT_CONFIG = {
6
+ timeout: 120,
7
+ maxRetries: 3,
8
+ approvalPoints: ['plan', 'merge'],
9
+ maxConcurrentAgents: 3,
10
+ model: 'claude-sonnet-4-6'
11
+ };
12
+ class StateManager {
13
+ store;
14
+ stateCache = null;
15
+ constructor(basePath) {
16
+ this.store = new file_store_js_1.FileStore(basePath);
17
+ }
18
+ async initialize() {
19
+ const existing = await this.store.readJson('state.json');
20
+ if (!existing) {
21
+ const initialState = {
22
+ version: '1.0',
23
+ runId: this.generateRunId(),
24
+ status: 'initialized',
25
+ currentPhase: 'planning',
26
+ startedAt: new Date().toISOString(),
27
+ config: DEFAULT_CONFIG,
28
+ statistics: {
29
+ totalTasks: 0,
30
+ completed: 0,
31
+ inProgress: 0,
32
+ failed: 0,
33
+ pending: 0
34
+ }
35
+ };
36
+ await this.store.writeJson('state.json', initialState);
37
+ this.stateCache = initialState;
38
+ }
39
+ else {
40
+ this.stateCache = existing;
41
+ }
42
+ }
43
+ async getState() {
44
+ if (!this.stateCache) {
45
+ this.stateCache = await this.store.readJson('state.json');
46
+ }
47
+ return this.stateCache;
48
+ }
49
+ async updateState(updates) {
50
+ const state = await this.getState();
51
+ const newState = { ...state, ...updates };
52
+ await this.store.writeJson('state.json', newState);
53
+ this.stateCache = newState;
54
+ }
55
+ async createTask(input) {
56
+ const taskId = this.generateTaskId();
57
+ const now = new Date().toISOString();
58
+ const task = {
59
+ id: taskId,
60
+ title: input.title,
61
+ description: input.description,
62
+ status: 'pending',
63
+ priority: input.priority,
64
+ timeout: input.timeout,
65
+ dependencies: input.dependencies,
66
+ assignedAgent: input.assignedAgent,
67
+ phases: {
68
+ develop: { status: 'pending', duration: null },
69
+ verify: { status: 'pending', duration: null },
70
+ accept: { status: 'pending', duration: null }
71
+ },
72
+ retryCount: 0,
73
+ error: null,
74
+ createdAt: now,
75
+ updatedAt: now
76
+ };
77
+ await this.store.writeJson(`tasks/${taskId}/task.json`, task);
78
+ // Update statistics
79
+ const state = await this.getState();
80
+ await this.updateState({
81
+ statistics: {
82
+ ...state.statistics,
83
+ totalTasks: state.statistics.totalTasks + 1,
84
+ pending: state.statistics.pending + 1
85
+ }
86
+ });
87
+ return task;
88
+ }
89
+ async getTask(taskId) {
90
+ return await this.store.readJson(`tasks/${taskId}/task.json`);
91
+ }
92
+ async updateTask(taskId, updates) {
93
+ const task = await this.getTask(taskId);
94
+ if (!task)
95
+ throw new Error(`Task ${taskId} not found`);
96
+ const oldStatus = task.status;
97
+ const updatedTask = {
98
+ ...task,
99
+ ...updates,
100
+ updatedAt: new Date().toISOString()
101
+ };
102
+ await this.store.writeJson(`tasks/${taskId}/task.json`, updatedTask);
103
+ // Update statistics if status changed
104
+ if (updates.status && updates.status !== oldStatus) {
105
+ await this.updateTaskStatistics(oldStatus, updates.status);
106
+ }
107
+ }
108
+ async listTasks() {
109
+ const dirs = await this.store.listDirs('tasks');
110
+ const tasks = [];
111
+ for (const dir of dirs) {
112
+ const task = await this.getTask(dir);
113
+ if (task)
114
+ tasks.push(task);
115
+ }
116
+ return tasks.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
117
+ }
118
+ async updateTaskStatistics(oldStatus, newStatus) {
119
+ const state = await this.getState();
120
+ const stats = { ...state.statistics };
121
+ // Decrement old status count
122
+ if (oldStatus === 'pending')
123
+ stats.pending--;
124
+ else if (oldStatus === 'in_progress')
125
+ stats.inProgress--;
126
+ else if (oldStatus === 'completed')
127
+ stats.completed--;
128
+ else if (oldStatus === 'failed')
129
+ stats.failed--;
130
+ // Increment new status count
131
+ if (newStatus === 'pending')
132
+ stats.pending++;
133
+ else if (newStatus === 'in_progress')
134
+ stats.inProgress++;
135
+ else if (newStatus === 'completed')
136
+ stats.completed++;
137
+ else if (newStatus === 'failed')
138
+ stats.failed++;
139
+ await this.updateState({ statistics: stats });
140
+ }
141
+ generateRunId() {
142
+ const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
143
+ const rand = Math.random().toString(36).slice(2, 6);
144
+ return `run-${date}-${rand}`;
145
+ }
146
+ generateTaskId() {
147
+ const timestamp = Date.now().toString(36).toUpperCase();
148
+ const rand = Math.random().toString(36).slice(2, 4).toUpperCase();
149
+ return `TASK-${timestamp}${rand}`;
150
+ }
151
+ // ============ Approval Methods ============
152
+ async saveApproval(approval) {
153
+ await this.store.writeJson(`approvals/${approval.id}.json`, approval);
154
+ }
155
+ async getApproval(approvalId) {
156
+ return await this.store.readJson(`approvals/${approvalId}.json`);
157
+ }
158
+ async updateApproval(approval) {
159
+ await this.store.writeJson(`approvals/${approval.id}.json`, approval);
160
+ }
161
+ async getApprovalsByStatus(status) {
162
+ const files = await this.store.listFiles('approvals');
163
+ const approvals = [];
164
+ for (const file of files) {
165
+ const approval = await this.store.readJson(`approvals/${file}`);
166
+ if (approval && approval.status === status) {
167
+ approvals.push(approval);
168
+ }
169
+ }
170
+ return approvals.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
171
+ }
172
+ async getAllApprovals() {
173
+ const files = await this.store.listFiles('approvals');
174
+ const approvals = [];
175
+ for (const file of files) {
176
+ const approval = await this.store.readJson(`approvals/${file}`);
177
+ if (approval) {
178
+ approvals.push(approval);
179
+ }
180
+ }
181
+ return approvals.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
182
+ }
183
+ // ============ Meeting Methods ============
184
+ async saveMeeting(meeting) {
185
+ await this.store.writeJson(`meetings/${meeting.id}.json`, meeting);
186
+ }
187
+ async getMeeting(meetingId) {
188
+ return await this.store.readJson(`meetings/${meetingId}.json`);
189
+ }
190
+ async getMeetingsByStatus(status) {
191
+ const files = await this.store.listFiles('meetings');
192
+ const meetings = [];
193
+ for (const file of files) {
194
+ const meeting = await this.store.readJson(`meetings/${file}`);
195
+ if (meeting && meeting.status === status) {
196
+ meetings.push(meeting);
197
+ }
198
+ }
199
+ return meetings.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
200
+ }
201
+ }
202
+ exports.StateManager = StateManager;
@@ -0,0 +1,193 @@
1
+ export type TaskStatus = 'pending' | 'scheduled' | 'in_progress' | 'blocked' | 'waiting' | 'verify' | 'accept' | 'completed' | 'failed' | 'retry_queue';
2
+ export type TaskPriority = 'P0' | 'P1' | 'P2' | 'P3';
3
+ export interface TaskPhase {
4
+ status: TaskStatus;
5
+ duration: number | null;
6
+ startedAt?: string;
7
+ completedAt?: string;
8
+ }
9
+ export interface Task {
10
+ id: string;
11
+ title: string;
12
+ description: string;
13
+ status: TaskStatus;
14
+ priority: TaskPriority;
15
+ timeout: number;
16
+ dependencies: string[];
17
+ assignedAgent: AgentType;
18
+ phases: {
19
+ develop: TaskPhase;
20
+ verify: TaskPhase;
21
+ accept: TaskPhase;
22
+ };
23
+ retryCount: number;
24
+ error: string | null;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ /** 验收标准 */
28
+ acceptanceCriteria?: string[];
29
+ /** 关联的测试任务 ID */
30
+ testTaskId?: string;
31
+ /** 任务所属阶段 */
32
+ phase?: 'design' | 'develop' | 'verify' | 'accept';
33
+ }
34
+ export type AgentType = 'planner' | 'coder' | 'tester' | 'reviewer' | 'researcher' | 'executor';
35
+ export type AgentStatus = 'idle' | 'running' | 'completed' | 'failed';
36
+ export interface AgentResult {
37
+ runId: string;
38
+ taskId: string;
39
+ agentType: AgentType;
40
+ status: AgentStatus;
41
+ output: string;
42
+ artifacts: string[];
43
+ needsApproval: boolean;
44
+ error?: string;
45
+ duration: number;
46
+ completedAt: string;
47
+ }
48
+ /**
49
+ * Claude Code Subagent 类型
50
+ */
51
+ export type ClaudeCodeSubagentType = 'general-purpose' | 'Explore' | 'Plan';
52
+ /**
53
+ * Subagent 任务配置 - 用于 Agent 工具调用
54
+ */
55
+ export interface SubagentTask {
56
+ /** Subagent 类型 */
57
+ subagent_type: ClaudeCodeSubagentType;
58
+ /** 简短描述 (3-5 词) */
59
+ description: string;
60
+ /** 完整任务提示词 */
61
+ prompt: string;
62
+ /** 是否使用隔离 worktree */
63
+ isolation?: 'worktree';
64
+ /** 任务 ID (用于追踪) */
65
+ taskId: string;
66
+ /** 原始 Agent 类型 */
67
+ agentType: AgentType;
68
+ /** 超时时间 (ms) */
69
+ timeout: number;
70
+ /** 是否需要审批 */
71
+ needsApproval: boolean;
72
+ }
73
+ export type RunStatus = 'initialized' | 'running' | 'paused' | 'completed' | 'failed';
74
+ export interface GlobalState {
75
+ version: string;
76
+ runId: string;
77
+ status: RunStatus;
78
+ currentPhase: 'planning' | 'execution' | 'verification' | 'acceptance';
79
+ startedAt: string;
80
+ config: AppConfig;
81
+ statistics: {
82
+ totalTasks: number;
83
+ completed: number;
84
+ inProgress: number;
85
+ failed: number;
86
+ pending: number;
87
+ };
88
+ }
89
+ export interface AppConfig {
90
+ timeout: number;
91
+ maxRetries: number;
92
+ approvalPoints: ('plan' | 'merge' | 'deploy')[];
93
+ maxConcurrentAgents: number;
94
+ model: string;
95
+ /** 质量配置 */
96
+ quality?: QualityConfig;
97
+ }
98
+ /**
99
+ * 质量配置 - 控制自动化质量门禁
100
+ */
101
+ export interface QualityConfig {
102
+ /** 启用 TDD 模式 (先写测试再写代码) */
103
+ tdd: boolean;
104
+ /** 最低测试覆盖率 (%) */
105
+ minCoverage: number;
106
+ /** 严格 Lint (error 即失败) */
107
+ strictLint: boolean;
108
+ /** 安全扫描 */
109
+ securityScan: boolean;
110
+ /** 质量级别 */
111
+ level: 'fast' | 'balanced' | 'strict';
112
+ }
113
+ /**
114
+ * 质量报告 - Verify 阶段产出
115
+ */
116
+ export interface QualityReport {
117
+ taskId: string;
118
+ timestamp: string;
119
+ /** 测试结果 */
120
+ tests: {
121
+ passed: number;
122
+ failed: number;
123
+ skipped: number;
124
+ coverage: number;
125
+ status: 'pass' | 'fail';
126
+ };
127
+ /** 构建结果 */
128
+ build: {
129
+ success: boolean;
130
+ errors: string[];
131
+ status: 'pass' | 'fail';
132
+ };
133
+ /** Lint 结果 */
134
+ lint: {
135
+ errors: number;
136
+ warnings: number;
137
+ status: 'pass' | 'fail' | 'warning';
138
+ };
139
+ /** 安全扫描结果 */
140
+ security: {
141
+ vulnerabilities: SecurityVulnerability[];
142
+ status: 'pass' | 'fail';
143
+ };
144
+ /** 验收标准检查 */
145
+ acceptance: {
146
+ total: number;
147
+ met: number;
148
+ details: AcceptanceCheck[];
149
+ status: 'pass' | 'fail';
150
+ };
151
+ /** 总体状态 */
152
+ overall: 'pass' | 'fail' | 'warning';
153
+ }
154
+ export interface SecurityVulnerability {
155
+ severity: 'low' | 'medium' | 'high' | 'critical';
156
+ package: string;
157
+ description: string;
158
+ }
159
+ export interface AcceptanceCheck {
160
+ criterion: string;
161
+ met: boolean;
162
+ evidence?: string;
163
+ }
164
+ /**
165
+ * 预设质量配置
166
+ */
167
+ export declare const QUALITY_PRESETS: Record<string, QualityConfig>;
168
+ export type ApprovalStatus = 'pending' | 'approved' | 'rejected';
169
+ export interface Approval {
170
+ id: string;
171
+ type: 'plan' | 'merge' | 'deploy' | 'meeting' | 'custom';
172
+ taskId: string;
173
+ title: string;
174
+ description: string;
175
+ content: string;
176
+ options: ApprovalOption[];
177
+ status: ApprovalStatus;
178
+ decision?: 'approve' | 'modify' | 'reject';
179
+ createdAt: string;
180
+ decidedAt?: string;
181
+ }
182
+ export interface ApprovalOption {
183
+ key: string;
184
+ label: string;
185
+ }
186
+ export interface ParsedTask {
187
+ title: string;
188
+ description: string;
189
+ goals: string[];
190
+ constraints: string[];
191
+ deliverables: string[];
192
+ rawContent: string;
193
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ // src/types/index.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.QUALITY_PRESETS = void 0;
5
+ /**
6
+ * 预设质量配置
7
+ */
8
+ exports.QUALITY_PRESETS = {
9
+ fast: {
10
+ tdd: false,
11
+ minCoverage: 0,
12
+ strictLint: false,
13
+ securityScan: false,
14
+ level: 'fast'
15
+ },
16
+ balanced: {
17
+ tdd: false,
18
+ minCoverage: 60,
19
+ strictLint: true,
20
+ securityScan: true,
21
+ level: 'balanced'
22
+ },
23
+ strict: {
24
+ tdd: true,
25
+ minCoverage: 80,
26
+ strictLint: true,
27
+ securityScan: true,
28
+ level: 'strict'
29
+ }
30
+ };
@@ -0,0 +1,41 @@
1
+ import winston from 'winston';
2
+ export interface LoggerOptions {
3
+ level?: string;
4
+ logDir?: string;
5
+ console?: boolean;
6
+ }
7
+ /**
8
+ * 创建或获取默认 Logger
9
+ */
10
+ export declare function createLogger(options?: LoggerOptions): winston.Logger;
11
+ /**
12
+ * 获取默认 logger 实例
13
+ */
14
+ export declare function getLogger(): winston.Logger;
15
+ /**
16
+ * 设置默认 logger
17
+ */
18
+ export declare function setLogger(logger: winston.Logger): void;
19
+ /**
20
+ * 便捷方法: 直接记录日志
21
+ */
22
+ export declare const logger: {
23
+ info: (message: string, meta?: any) => winston.Logger;
24
+ error: (message: string, meta?: any) => winston.Logger;
25
+ warn: (message: string, meta?: any) => winston.Logger;
26
+ debug: (message: string, meta?: any) => winston.Logger;
27
+ task: {
28
+ start: (taskId: string, title: string) => void;
29
+ complete: (taskId: string, duration?: number) => void;
30
+ fail: (taskId: string, error: string) => void;
31
+ retry: (taskId: string, attempt: number) => void;
32
+ };
33
+ agent: {
34
+ call: (agentType: string, taskId: string) => void;
35
+ result: (agentType: string, taskId: string, success: boolean) => void;
36
+ };
37
+ approval: {
38
+ request: (approvalId: string, type: string) => void;
39
+ decision: (approvalId: string, decision: string) => void;
40
+ };
41
+ };
@@ -0,0 +1,166 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.logger = void 0;
40
+ exports.createLogger = createLogger;
41
+ exports.getLogger = getLogger;
42
+ exports.setLogger = setLogger;
43
+ // src/utils/logger.ts
44
+ const winston_1 = __importDefault(require("winston"));
45
+ const path = __importStar(require("path"));
46
+ const fs = __importStar(require("fs"));
47
+ /**
48
+ * OpenMatrix Logger - 基于 Winston 的日志系统
49
+ *
50
+ * 特性:
51
+ * 1. 多级别日志 (error, warn, info, debug)
52
+ * 2. 文件滚动日志
53
+ * 3. 控制台彩色输出
54
+ * 4. 结构化 JSON 日志
55
+ */
56
+ let defaultLogger = null;
57
+ /**
58
+ * 创建或获取默认 Logger
59
+ */
60
+ function createLogger(options = {}) {
61
+ const { level = process.env.OPENMATRIX_LOG_LEVEL || 'info', logDir = '.openmatrix/logs', console: enableConsole = true } = options;
62
+ // 确保日志目录存在
63
+ const absoluteLogDir = path.resolve(process.cwd(), logDir);
64
+ if (!fs.existsSync(absoluteLogDir)) {
65
+ fs.mkdirSync(absoluteLogDir, { recursive: true });
66
+ }
67
+ // 定义日志格式
68
+ const customFormat = winston_1.default.format.combine(winston_1.default.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston_1.default.format.errors({ stack: true }), winston_1.default.format.printf(({ level, message, timestamp, ...metadata }) => {
69
+ const metaStr = Object.keys(metadata).length ? JSON.stringify(metadata) : '';
70
+ return `${timestamp} [${level.toUpperCase()}] ${message} ${metaStr}`;
71
+ }));
72
+ // JSON 格式 (用于文件)
73
+ const jsonFormat = winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.json());
74
+ // 控制台格式 (带颜色)
75
+ const consoleFormat = winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.timestamp({ format: 'HH:mm:ss' }), winston_1.default.format.printf(({ level, message, timestamp, ...metadata }) => {
76
+ const metaStr = Object.keys(metadata).length ? JSON.stringify(metadata) : '';
77
+ return `${timestamp} ${level} ${message} ${metaStr}`;
78
+ }));
79
+ // 创建 transports
80
+ const transports = [];
81
+ // 文件日志
82
+ transports.push(new winston_1.default.transports.File({
83
+ filename: path.join(absoluteLogDir, 'error.log'),
84
+ level: 'error',
85
+ format: jsonFormat,
86
+ maxsize: 5 * 1024 * 1024, // 5MB
87
+ maxFiles: 5
88
+ }));
89
+ transports.push(new winston_1.default.transports.File({
90
+ filename: path.join(absoluteLogDir, 'combined.log'),
91
+ format: jsonFormat,
92
+ maxsize: 10 * 1024 * 1024, // 10MB
93
+ maxFiles: 10
94
+ }));
95
+ // 控制台日志
96
+ if (enableConsole) {
97
+ transports.push(new winston_1.default.transports.Console({
98
+ format: consoleFormat,
99
+ level
100
+ }));
101
+ }
102
+ // 创建 logger
103
+ const logger = winston_1.default.createLogger({
104
+ level,
105
+ defaultMeta: { service: 'openmatrix' },
106
+ transports
107
+ });
108
+ return logger;
109
+ }
110
+ /**
111
+ * 获取默认 logger 实例
112
+ */
113
+ function getLogger() {
114
+ if (!defaultLogger) {
115
+ defaultLogger = createLogger();
116
+ }
117
+ return defaultLogger;
118
+ }
119
+ /**
120
+ * 设置默认 logger
121
+ */
122
+ function setLogger(logger) {
123
+ defaultLogger = logger;
124
+ }
125
+ /**
126
+ * 便捷方法: 直接记录日志
127
+ */
128
+ exports.logger = {
129
+ info: (message, meta) => getLogger().info(message, meta),
130
+ error: (message, meta) => getLogger().error(message, meta),
131
+ warn: (message, meta) => getLogger().warn(message, meta),
132
+ debug: (message, meta) => getLogger().debug(message, meta),
133
+ // 任务相关日志
134
+ task: {
135
+ start: (taskId, title) => {
136
+ getLogger().info(`Task started: ${taskId}`, { taskId, title });
137
+ },
138
+ complete: (taskId, duration) => {
139
+ getLogger().info(`Task completed: ${taskId}`, { taskId, duration });
140
+ },
141
+ fail: (taskId, error) => {
142
+ getLogger().error(`Task failed: ${taskId}`, { taskId, error });
143
+ },
144
+ retry: (taskId, attempt) => {
145
+ getLogger().warn(`Task retry: ${taskId}`, { taskId, attempt });
146
+ }
147
+ },
148
+ // Agent 相关日志
149
+ agent: {
150
+ call: (agentType, taskId) => {
151
+ getLogger().info(`Agent called: ${agentType}`, { agentType, taskId });
152
+ },
153
+ result: (agentType, taskId, success) => {
154
+ getLogger().debug(`Agent result: ${agentType}`, { agentType, taskId, success });
155
+ }
156
+ },
157
+ // 审批相关日志
158
+ approval: {
159
+ request: (approvalId, type) => {
160
+ getLogger().info(`Approval requested: ${approvalId}`, { approvalId, type });
161
+ },
162
+ decision: (approvalId, decision) => {
163
+ getLogger().info(`Approval decision: ${approvalId}`, { approvalId, decision });
164
+ }
165
+ }
166
+ };