evo-skills 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 (188) hide show
  1. package/.eslintrc.json +36 -0
  2. package/.prettierrc +11 -0
  3. package/README.md +227 -0
  4. package/USER-GUIDE.md +382 -0
  5. package/dist/cli/commands/diff.d.ts +7 -0
  6. package/dist/cli/commands/diff.d.ts.map +1 -0
  7. package/dist/cli/commands/diff.js +126 -0
  8. package/dist/cli/commands/diff.js.map +1 -0
  9. package/dist/cli/commands/freeze.d.ts +12 -0
  10. package/dist/cli/commands/freeze.d.ts.map +1 -0
  11. package/dist/cli/commands/freeze.js +93 -0
  12. package/dist/cli/commands/freeze.js.map +1 -0
  13. package/dist/cli/commands/log.d.ts +7 -0
  14. package/dist/cli/commands/log.d.ts.map +1 -0
  15. package/dist/cli/commands/log.js +76 -0
  16. package/dist/cli/commands/log.js.map +1 -0
  17. package/dist/cli/commands/rollback.d.ts +7 -0
  18. package/dist/cli/commands/rollback.d.ts.map +1 -0
  19. package/dist/cli/commands/rollback.js +92 -0
  20. package/dist/cli/commands/rollback.js.map +1 -0
  21. package/dist/cli/commands/status.d.ts +7 -0
  22. package/dist/cli/commands/status.d.ts.map +1 -0
  23. package/dist/cli/commands/status.js +88 -0
  24. package/dist/cli/commands/status.js.map +1 -0
  25. package/dist/cli/index.d.ts +3 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +25 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/config/defaults.d.ts +6 -0
  30. package/dist/config/defaults.d.ts.map +1 -0
  31. package/dist/config/defaults.js +31 -0
  32. package/dist/config/defaults.js.map +1 -0
  33. package/dist/config/index.d.ts +68 -0
  34. package/dist/config/index.d.ts.map +1 -0
  35. package/dist/config/index.js +195 -0
  36. package/dist/config/index.js.map +1 -0
  37. package/dist/core/evaluator/base-rule.d.ts +50 -0
  38. package/dist/core/evaluator/base-rule.d.ts.map +1 -0
  39. package/dist/core/evaluator/base-rule.js +69 -0
  40. package/dist/core/evaluator/base-rule.js.map +1 -0
  41. package/dist/core/evaluator/index.d.ts +33 -0
  42. package/dist/core/evaluator/index.d.ts.map +1 -0
  43. package/dist/core/evaluator/index.js +74 -0
  44. package/dist/core/evaluator/index.js.map +1 -0
  45. package/dist/core/evaluator/rules/repeated-drift.d.ts +19 -0
  46. package/dist/core/evaluator/rules/repeated-drift.d.ts.map +1 -0
  47. package/dist/core/evaluator/rules/repeated-drift.js +82 -0
  48. package/dist/core/evaluator/rules/repeated-drift.js.map +1 -0
  49. package/dist/core/evaluator/rules/repeated-manual-fix.d.ts +23 -0
  50. package/dist/core/evaluator/rules/repeated-manual-fix.d.ts.map +1 -0
  51. package/dist/core/evaluator/rules/repeated-manual-fix.js +97 -0
  52. package/dist/core/evaluator/rules/repeated-manual-fix.js.map +1 -0
  53. package/dist/core/journal/index.d.ts +76 -0
  54. package/dist/core/journal/index.d.ts.map +1 -0
  55. package/dist/core/journal/index.js +207 -0
  56. package/dist/core/journal/index.js.map +1 -0
  57. package/dist/core/observer/base-observer.d.ts +64 -0
  58. package/dist/core/observer/base-observer.d.ts.map +1 -0
  59. package/dist/core/observer/base-observer.js +142 -0
  60. package/dist/core/observer/base-observer.js.map +1 -0
  61. package/dist/core/observer/codex-observer.d.ts +71 -0
  62. package/dist/core/observer/codex-observer.d.ts.map +1 -0
  63. package/dist/core/observer/codex-observer.js +248 -0
  64. package/dist/core/observer/codex-observer.js.map +1 -0
  65. package/dist/core/observer/index.d.ts +7 -0
  66. package/dist/core/observer/index.d.ts.map +1 -0
  67. package/dist/core/observer/index.js +7 -0
  68. package/dist/core/observer/index.js.map +1 -0
  69. package/dist/core/observer/trace-manager.d.ts +82 -0
  70. package/dist/core/observer/trace-manager.d.ts.map +1 -0
  71. package/dist/core/observer/trace-manager.js +196 -0
  72. package/dist/core/observer/trace-manager.js.map +1 -0
  73. package/dist/core/origin-registry/index.d.ts +59 -0
  74. package/dist/core/origin-registry/index.d.ts.map +1 -0
  75. package/dist/core/origin-registry/index.js +235 -0
  76. package/dist/core/origin-registry/index.js.map +1 -0
  77. package/dist/core/patch-generator/base-strategy.d.ts +35 -0
  78. package/dist/core/patch-generator/base-strategy.d.ts.map +1 -0
  79. package/dist/core/patch-generator/base-strategy.js +55 -0
  80. package/dist/core/patch-generator/base-strategy.js.map +1 -0
  81. package/dist/core/patch-generator/index.d.ts +32 -0
  82. package/dist/core/patch-generator/index.d.ts.map +1 -0
  83. package/dist/core/patch-generator/index.js +101 -0
  84. package/dist/core/patch-generator/index.js.map +1 -0
  85. package/dist/core/patch-generator/strategies/add-fallback.d.ts +11 -0
  86. package/dist/core/patch-generator/strategies/add-fallback.d.ts.map +1 -0
  87. package/dist/core/patch-generator/strategies/add-fallback.js +57 -0
  88. package/dist/core/patch-generator/strategies/add-fallback.js.map +1 -0
  89. package/dist/core/patch-generator/strategies/prune-noise.d.ts +11 -0
  90. package/dist/core/patch-generator/strategies/prune-noise.d.ts.map +1 -0
  91. package/dist/core/patch-generator/strategies/prune-noise.js +48 -0
  92. package/dist/core/patch-generator/strategies/prune-noise.js.map +1 -0
  93. package/dist/core/shadow-manager/index.d.ts +65 -0
  94. package/dist/core/shadow-manager/index.d.ts.map +1 -0
  95. package/dist/core/shadow-manager/index.js +229 -0
  96. package/dist/core/shadow-manager/index.js.map +1 -0
  97. package/dist/core/shadow-registry/index.d.ts +68 -0
  98. package/dist/core/shadow-registry/index.d.ts.map +1 -0
  99. package/dist/core/shadow-registry/index.js +173 -0
  100. package/dist/core/shadow-registry/index.js.map +1 -0
  101. package/dist/daemon/index.d.ts +43 -0
  102. package/dist/daemon/index.d.ts.map +1 -0
  103. package/dist/daemon/index.js +144 -0
  104. package/dist/daemon/index.js.map +1 -0
  105. package/dist/storage/index.d.ts +7 -0
  106. package/dist/storage/index.d.ts.map +1 -0
  107. package/dist/storage/index.js +7 -0
  108. package/dist/storage/index.js.map +1 -0
  109. package/dist/storage/markdown.d.ts +66 -0
  110. package/dist/storage/markdown.d.ts.map +1 -0
  111. package/dist/storage/markdown.js +227 -0
  112. package/dist/storage/markdown.js.map +1 -0
  113. package/dist/storage/ndjson.d.ts +118 -0
  114. package/dist/storage/ndjson.d.ts.map +1 -0
  115. package/dist/storage/ndjson.js +238 -0
  116. package/dist/storage/ndjson.js.map +1 -0
  117. package/dist/storage/sqlite.d.ts +131 -0
  118. package/dist/storage/sqlite.d.ts.map +1 -0
  119. package/dist/storage/sqlite.js +415 -0
  120. package/dist/storage/sqlite.js.map +1 -0
  121. package/dist/types/index.d.ts +158 -0
  122. package/dist/types/index.d.ts.map +1 -0
  123. package/dist/types/index.js +5 -0
  124. package/dist/types/index.js.map +1 -0
  125. package/dist/utils/diff.d.ts +20 -0
  126. package/dist/utils/diff.d.ts.map +1 -0
  127. package/dist/utils/diff.js +47 -0
  128. package/dist/utils/diff.js.map +1 -0
  129. package/dist/utils/hash.d.ts +17 -0
  130. package/dist/utils/hash.d.ts.map +1 -0
  131. package/dist/utils/hash.js +28 -0
  132. package/dist/utils/hash.js.map +1 -0
  133. package/dist/utils/index.d.ts +8 -0
  134. package/dist/utils/index.d.ts.map +1 -0
  135. package/dist/utils/index.js +8 -0
  136. package/dist/utils/index.js.map +1 -0
  137. package/dist/utils/logger.d.ts +11 -0
  138. package/dist/utils/logger.d.ts.map +1 -0
  139. package/dist/utils/logger.js +64 -0
  140. package/dist/utils/logger.js.map +1 -0
  141. package/dist/utils/path.d.ts +67 -0
  142. package/dist/utils/path.d.ts.map +1 -0
  143. package/dist/utils/path.js +115 -0
  144. package/dist/utils/path.js.map +1 -0
  145. package/docs/ENGINEERING_PLAN.md +1065 -0
  146. package/docs/PRD.md +1004 -0
  147. package/docs/PROGRESS.md +523 -0
  148. package/package.json +60 -0
  149. package/src/cli/commands/diff.ts +158 -0
  150. package/src/cli/commands/freeze.ts +108 -0
  151. package/src/cli/commands/log.ts +87 -0
  152. package/src/cli/commands/rollback.ts +99 -0
  153. package/src/cli/commands/status.ts +101 -0
  154. package/src/cli/index.ts +31 -0
  155. package/src/config/defaults.ts +32 -0
  156. package/src/config/index.ts +220 -0
  157. package/src/core/evaluator/base-rule.ts +90 -0
  158. package/src/core/evaluator/index.ts +86 -0
  159. package/src/core/evaluator/rules/repeated-drift.ts +109 -0
  160. package/src/core/evaluator/rules/repeated-manual-fix.ts +129 -0
  161. package/src/core/journal/index.ts +286 -0
  162. package/src/core/observer/base-observer.ts +200 -0
  163. package/src/core/observer/codex-observer.ts +309 -0
  164. package/src/core/observer/index.ts +7 -0
  165. package/src/core/observer/trace-manager.ts +250 -0
  166. package/src/core/origin-registry/index.ts +264 -0
  167. package/src/core/patch-generator/base-strategy.ts +67 -0
  168. package/src/core/patch-generator/index.ts +118 -0
  169. package/src/core/patch-generator/strategies/add-fallback.ts +69 -0
  170. package/src/core/patch-generator/strategies/prune-noise.ts +65 -0
  171. package/src/core/shadow-manager/index.ts +278 -0
  172. package/src/core/shadow-registry/index.ts +200 -0
  173. package/src/daemon/index.ts +174 -0
  174. package/src/storage/index.ts +7 -0
  175. package/src/storage/markdown.ts +267 -0
  176. package/src/storage/ndjson.ts +273 -0
  177. package/src/storage/sqlite.ts +555 -0
  178. package/src/types/index.ts +212 -0
  179. package/src/utils/diff.ts +60 -0
  180. package/src/utils/hash.ts +31 -0
  181. package/src/utils/index.ts +8 -0
  182. package/src/utils/logger.ts +78 -0
  183. package/src/utils/path.ts +129 -0
  184. package/tests/unit/config.test.ts +65 -0
  185. package/tests/unit/path.test.ts +89 -0
  186. package/tests/unit/utils.test.ts +45 -0
  187. package/tsconfig.json +31 -0
  188. package/vitest.config.ts +19 -0
@@ -0,0 +1,286 @@
1
+ import { existsSync, mkdirSync, copyFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { createChildLogger } from '../../utils/logger.js';
4
+ import { hashString } from '../../utils/hash.js';
5
+ import { createJournalStore } from '../../storage/ndjson.js';
6
+ import { createSQLiteStorage } from '../../storage/sqlite.js';
7
+ import type { EvolutionRecord, JournalQueryOptions } from '../../types/index.js';
8
+
9
+ const logger = createChildLogger('journal');
10
+
11
+ /**
12
+ * Journal Manager
13
+ * 负责管理演化日志和版本控制
14
+ */
15
+ export class JournalManager {
16
+ private db;
17
+ private projectRoot: string;
18
+
19
+ constructor(projectRoot: string) {
20
+ this.projectRoot = projectRoot;
21
+ const dbPath = join(projectRoot, '.evo', 'state', 'sessions.db');
22
+ this.db = createSQLiteStorage(dbPath);
23
+ }
24
+
25
+ /**
26
+ * 初始化数据库
27
+ */
28
+ async init(): Promise<void> {
29
+ await this.db.init();
30
+ }
31
+
32
+ /**
33
+ * 记录一次演化
34
+ */
35
+ async record(
36
+ shadowId: string,
37
+ record: Omit<EvolutionRecord, 'revision'>
38
+ ): Promise<number> {
39
+ // 获取当前 revision
40
+ const currentRevision = await this.getLatestRevision(shadowId);
41
+ const newRevision = currentRevision + 1;
42
+
43
+ // 创建完整的演化记录
44
+ const fullRecord: EvolutionRecord = {
45
+ ...record,
46
+ revision: newRevision,
47
+ };
48
+
49
+ // 写入 journal
50
+ const journal = this.getJournal(shadowId);
51
+ journal.append(fullRecord);
52
+
53
+ // 更新数据库索引
54
+ this.db.addEvolutionRecordIndex({
55
+ shadow_id: shadowId,
56
+ revision: newRevision,
57
+ timestamp: fullRecord.timestamp,
58
+ change_type: fullRecord.change_type,
59
+ source_sessions: fullRecord.source_sessions,
60
+ confidence: 0, // 默认置信度
61
+ });
62
+
63
+ // 更新 shadow revision
64
+ const skillId = this.extractSkillId(shadowId);
65
+ if (skillId) {
66
+ this.db.updateShadowRevision(shadowId, newRevision);
67
+ }
68
+
69
+ logger.info(`Evolution recorded: revision ${newRevision}`, {
70
+ shadow_id: shadowId,
71
+ change_type: fullRecord.change_type,
72
+ });
73
+
74
+ return newRevision;
75
+ }
76
+
77
+ /**
78
+ * 获取 journal
79
+ */
80
+ getJournal(shadowId: string) {
81
+ const skillId = this.extractSkillId(shadowId);
82
+ const journalPath = join(
83
+ this.projectRoot,
84
+ '.evo',
85
+ 'skills',
86
+ skillId,
87
+ 'journal.ndjson'
88
+ );
89
+ return createJournalStore(journalPath);
90
+ }
91
+
92
+ /**
93
+ * 获取 journal 记录
94
+ */
95
+ async getJournalRecords(
96
+ shadowId: string,
97
+ options?: JournalQueryOptions
98
+ ): Promise<EvolutionRecord[]> {
99
+ const journal = this.getJournal(shadowId);
100
+ const allRecords = await journal.readAll();
101
+
102
+ let filtered = allRecords;
103
+
104
+ if (options?.fromRevision !== undefined) {
105
+ filtered = filtered.filter((r) => r.revision >= options.fromRevision!);
106
+ }
107
+
108
+ if (options?.toRevision !== undefined) {
109
+ filtered = filtered.filter((r) => r.revision <= options.toRevision!);
110
+ }
111
+
112
+ if (options?.changeType) {
113
+ filtered = filtered.filter((r) => r.change_type === options.changeType);
114
+ }
115
+
116
+ // 按 revision 降序排列
117
+ filtered.sort((a, b) => b.revision - a.revision);
118
+
119
+ if (options?.limit) {
120
+ filtered = filtered.slice(0, options.limit);
121
+ }
122
+
123
+ return filtered;
124
+ }
125
+
126
+ /**
127
+ * 获取最新 revision
128
+ */
129
+ async getLatestRevision(shadowId: string): Promise<number> {
130
+ const journal = this.getJournal(shadowId);
131
+ return journal.getLatestRevision();
132
+ }
133
+
134
+ /**
135
+ * 获取指定 revision 的记录
136
+ */
137
+ async getRecordByRevision(
138
+ shadowId: string,
139
+ revision: number
140
+ ): Promise<EvolutionRecord | null> {
141
+ const journal = this.getJournal(shadowId);
142
+ return journal.getByRevision(revision);
143
+ }
144
+
145
+ /**
146
+ * 创建 snapshot
147
+ */
148
+ async createSnapshot(shadowId: string, revision?: number): Promise<void> {
149
+ const skillId = this.extractSkillId(shadowId);
150
+ const targetRevision = revision ?? (await this.getLatestRevision(shadowId));
151
+
152
+ // 读取当前 shadow 内容
153
+ const shadowPath = join(
154
+ this.projectRoot,
155
+ '.evo',
156
+ 'skills',
157
+ skillId,
158
+ 'current.md'
159
+ );
160
+
161
+ if (!existsSync(shadowPath)) {
162
+ throw new Error(`Shadow skill not found: ${skillId}`);
163
+ }
164
+
165
+ // 创建 snapshot 文件
166
+ const snapshotsDir = join(
167
+ this.projectRoot,
168
+ '.evo',
169
+ 'skills',
170
+ skillId,
171
+ 'snapshots'
172
+ );
173
+
174
+ if (!existsSync(snapshotsDir)) {
175
+ mkdirSync(snapshotsDir, { recursive: true });
176
+ }
177
+
178
+ const snapshotFileName = `rev_${String(targetRevision).padStart(4, '0')}.md`;
179
+ const snapshotPath = join(snapshotsDir, snapshotFileName);
180
+
181
+ // 复制当前内容到 snapshot
182
+ copyFileSync(shadowPath, snapshotPath);
183
+
184
+ // 计算内容哈希
185
+ const { readFileSync } = require('node:fs');
186
+ const content = readFileSync(shadowPath, 'utf-8');
187
+ const contentHash = hashString(content);
188
+
189
+ // 记录到数据库
190
+ this.db.addSnapshot({
191
+ shadow_id: shadowId,
192
+ revision: targetRevision,
193
+ timestamp: new Date().toISOString(),
194
+ file_path: snapshotPath,
195
+ content_hash: contentHash,
196
+ });
197
+
198
+ logger.info(`Snapshot created: revision ${targetRevision}`, {
199
+ shadow_id: shadowId,
200
+ path: snapshotPath,
201
+ });
202
+ }
203
+
204
+ /**
205
+ * 回滚到指定 revision
206
+ */
207
+ async rollback(shadowId: string, targetRevision: number): Promise<void> {
208
+ const skillId = this.extractSkillId(shadowId);
209
+
210
+ // 查找 snapshot
211
+ const snapshots = this.db.getSnapshots(shadowId);
212
+ const snapshot = snapshots.find((s) => s.revision === targetRevision);
213
+
214
+ if (!snapshot) {
215
+ throw new Error(`Snapshot not found for revision ${targetRevision}`);
216
+ }
217
+
218
+ // 复制 snapshot 到当前
219
+ const shadowPath = join(
220
+ this.projectRoot,
221
+ '.evo',
222
+ 'skills',
223
+ skillId,
224
+ 'current.md'
225
+ );
226
+
227
+ copyFileSync(snapshot.file_path, shadowPath);
228
+
229
+ // 更新 revision
230
+ this.db.updateShadowRevision(shadowId, targetRevision);
231
+
232
+ logger.info(`Rolled back to revision ${targetRevision}`, {
233
+ shadow_id: shadowId,
234
+ snapshot_path: snapshot.file_path,
235
+ });
236
+ }
237
+
238
+ /**
239
+ * 回滚到上一个 snapshot
240
+ */
241
+ async rollbackToSnapshot(shadowId: string): Promise<void> {
242
+ const snapshots = this.db.getSnapshots(shadowId);
243
+ if (snapshots.length === 0) {
244
+ throw new Error('No snapshots available');
245
+ }
246
+
247
+ // 获取最新的 snapshot
248
+ const latestSnapshot = snapshots[0];
249
+ await this.rollback(shadowId, latestSnapshot.revision);
250
+ }
251
+
252
+ /**
253
+ * 获取所有 snapshots
254
+ */
255
+ getSnapshots(shadowId: string) {
256
+ return this.db.getSnapshots(shadowId);
257
+ }
258
+
259
+ /**
260
+ * 获取最新 snapshot
261
+ */
262
+ getLatestSnapshot(shadowId: string) {
263
+ return this.db.getLatestSnapshot(shadowId);
264
+ }
265
+
266
+ /**
267
+ * 从 shadowId 提取 skillId
268
+ */
269
+ private extractSkillId(shadowId: string): string {
270
+ // shadowId 格式: skillId@projectId
271
+ const parts = shadowId.split('@');
272
+ return parts[0] || shadowId;
273
+ }
274
+
275
+ /**
276
+ * 关闭数据库连接
277
+ */
278
+ close(): void {
279
+ this.db.close();
280
+ }
281
+ }
282
+
283
+ // 导出工厂函数
284
+ export function createJournalManager(projectRoot: string): JournalManager {
285
+ return new JournalManager(projectRoot);
286
+ }
@@ -0,0 +1,200 @@
1
+ import { createChildLogger } from '../../utils/logger.js';
2
+ import type { Trace, TraceStatus, RuntimeType } from '../../types/index.js';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+
5
+ const logger = createChildLogger('observer');
6
+
7
+ /**
8
+ * Observer 基类
9
+ * 负责从主 Agent 采集执行 trace
10
+ */
11
+ export abstract class BaseObserver {
12
+ protected runtime: RuntimeType;
13
+ protected isRunning: boolean = false;
14
+ protected onTraceCallback?: (trace: Trace) => void;
15
+
16
+ constructor(runtime: RuntimeType) {
17
+ this.runtime = runtime;
18
+ }
19
+
20
+ /**
21
+ * 启动 observer
22
+ */
23
+ abstract start(): Promise<void>;
24
+
25
+ /**
26
+ * 停止 observer
27
+ */
28
+ abstract stop(): Promise<void>;
29
+
30
+ /**
31
+ * 注册 trace 回调
32
+ */
33
+ onTrace(callback: (trace: Trace) => void): void {
34
+ this.onTraceCallback = callback;
35
+ }
36
+
37
+ /**
38
+ * 发送 trace
39
+ */
40
+ protected emitTrace(trace: Omit<Trace, 'trace_id' | 'runtime'>): void {
41
+ const fullTrace: Trace = {
42
+ ...trace,
43
+ trace_id: uuidv4(),
44
+ runtime: this.runtime,
45
+ };
46
+
47
+ logger.debug('Trace emitted', {
48
+ trace_id: fullTrace.trace_id,
49
+ event_type: fullTrace.event_type,
50
+ });
51
+
52
+ this.onTraceCallback?.(fullTrace);
53
+ }
54
+
55
+ /**
56
+ * 创建用户输入 trace
57
+ */
58
+ protected createUserInputTrace(
59
+ sessionId: string,
60
+ turnId: string,
61
+ input: string
62
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
63
+ return {
64
+ session_id: sessionId,
65
+ turn_id: turnId,
66
+ event_type: 'user_input',
67
+ timestamp: new Date().toISOString(),
68
+ user_input: input,
69
+ status: 'success',
70
+ };
71
+ }
72
+
73
+ /**
74
+ * 创建助手输出 trace
75
+ */
76
+ protected createAssistantOutputTrace(
77
+ sessionId: string,
78
+ turnId: string,
79
+ output: string
80
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
81
+ return {
82
+ session_id: sessionId,
83
+ turn_id: turnId,
84
+ event_type: 'assistant_output',
85
+ timestamp: new Date().toISOString(),
86
+ assistant_output: output,
87
+ status: 'success',
88
+ };
89
+ }
90
+
91
+ /**
92
+ * 创建工具调用 trace
93
+ */
94
+ protected createToolCallTrace(
95
+ sessionId: string,
96
+ turnId: string,
97
+ toolName: string,
98
+ toolArgs: Record<string, unknown>
99
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
100
+ return {
101
+ session_id: sessionId,
102
+ turn_id: turnId,
103
+ event_type: 'tool_call',
104
+ timestamp: new Date().toISOString(),
105
+ tool_name: toolName,
106
+ tool_args: toolArgs,
107
+ status: 'success',
108
+ };
109
+ }
110
+
111
+ /**
112
+ * 创建工具结果 trace
113
+ */
114
+ protected createToolResultTrace(
115
+ sessionId: string,
116
+ turnId: string,
117
+ toolName: string,
118
+ toolResult: Record<string, unknown>,
119
+ status: TraceStatus = 'success'
120
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
121
+ return {
122
+ session_id: sessionId,
123
+ turn_id: turnId,
124
+ event_type: 'tool_result',
125
+ timestamp: new Date().toISOString(),
126
+ tool_name: toolName,
127
+ tool_result: toolResult,
128
+ status,
129
+ };
130
+ }
131
+
132
+ /**
133
+ * 创建文件变化 trace
134
+ */
135
+ protected createFileChangeTrace(
136
+ sessionId: string,
137
+ turnId: string,
138
+ filesChanged: string[]
139
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
140
+ return {
141
+ session_id: sessionId,
142
+ turn_id: turnId,
143
+ event_type: 'file_change',
144
+ timestamp: new Date().toISOString(),
145
+ files_changed: filesChanged,
146
+ status: 'success',
147
+ };
148
+ }
149
+
150
+ /**
151
+ * 创建重试 trace
152
+ */
153
+ protected createRetryTrace(
154
+ sessionId: string,
155
+ turnId: string,
156
+ reason?: string
157
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
158
+ return {
159
+ session_id: sessionId,
160
+ turn_id: turnId,
161
+ event_type: 'retry',
162
+ timestamp: new Date().toISOString(),
163
+ status: 'retry',
164
+ metadata: reason ? { reason } : undefined,
165
+ };
166
+ }
167
+
168
+ /**
169
+ * 创建状态 trace
170
+ */
171
+ protected createStatusTrace(
172
+ sessionId: string,
173
+ turnId: string,
174
+ status: TraceStatus,
175
+ metadata?: Record<string, unknown>
176
+ ): Omit<Trace, 'trace_id' | 'runtime'> {
177
+ return {
178
+ session_id: sessionId,
179
+ turn_id: turnId,
180
+ event_type: 'status',
181
+ timestamp: new Date().toISOString(),
182
+ status,
183
+ metadata,
184
+ };
185
+ }
186
+
187
+ /**
188
+ * 检查是否正在运行
189
+ */
190
+ isActive(): boolean {
191
+ return this.isRunning;
192
+ }
193
+
194
+ /**
195
+ * 获取 runtime 类型
196
+ */
197
+ getRuntime(): RuntimeType {
198
+ return this.runtime;
199
+ }
200
+ }