@devflow-tools/server 0.12.5 → 0.12.6

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 (201) hide show
  1. package/package.json +2 -2
  2. package/dist/app.module.d.ts +0 -3
  3. package/dist/app.module.d.ts.map +0 -1
  4. package/dist/app.module.js +0 -42
  5. package/dist/app.module.js.map +0 -1
  6. package/dist/auth/api-key.decorator.d.ts +0 -3
  7. package/dist/auth/api-key.decorator.d.ts.map +0 -1
  8. package/dist/auth/api-key.decorator.js +0 -4
  9. package/dist/auth/api-key.decorator.js.map +0 -1
  10. package/dist/auth/api-key.guard.d.ts +0 -8
  11. package/dist/auth/api-key.guard.d.ts.map +0 -1
  12. package/dist/auth/api-key.guard.js +0 -61
  13. package/dist/auth/api-key.guard.js.map +0 -1
  14. package/dist/auth/auth.module.d.ts +0 -3
  15. package/dist/auth/auth.module.d.ts.map +0 -1
  16. package/dist/auth/auth.module.js +0 -19
  17. package/dist/auth/auth.module.js.map +0 -1
  18. package/dist/auth/errors.d.ts +0 -6
  19. package/dist/auth/errors.d.ts.map +0 -1
  20. package/dist/auth/errors.js +0 -5
  21. package/dist/auth/errors.js.map +0 -1
  22. package/dist/benchmark/benchmark.controller.d.ts +0 -11
  23. package/dist/benchmark/benchmark.controller.d.ts.map +0 -1
  24. package/dist/benchmark/benchmark.controller.js +0 -35
  25. package/dist/benchmark/benchmark.controller.js.map +0 -1
  26. package/dist/benchmark/benchmark.module.d.ts +0 -3
  27. package/dist/benchmark/benchmark.module.d.ts.map +0 -1
  28. package/dist/benchmark/benchmark.module.js +0 -16
  29. package/dist/benchmark/benchmark.module.js.map +0 -1
  30. package/dist/benchmark/benchmark.service.d.ts +0 -12
  31. package/dist/benchmark/benchmark.service.d.ts.map +0 -1
  32. package/dist/benchmark/benchmark.service.js +0 -58
  33. package/dist/benchmark/benchmark.service.js.map +0 -1
  34. package/dist/common/dto.d.ts +0 -12
  35. package/dist/common/dto.d.ts.map +0 -1
  36. package/dist/common/dto.js +0 -2
  37. package/dist/common/dto.js.map +0 -1
  38. package/dist/common/error-codes.d.ts +0 -17
  39. package/dist/common/error-codes.d.ts.map +0 -1
  40. package/dist/common/error-codes.js +0 -16
  41. package/dist/common/error-codes.js.map +0 -1
  42. package/dist/common/http-exception.filter.d.ts +0 -6
  43. package/dist/common/http-exception.filter.d.ts.map +0 -1
  44. package/dist/common/http-exception.filter.js +0 -77
  45. package/dist/common/http-exception.filter.js.map +0 -1
  46. package/dist/common/response.interceptor.d.ts +0 -6
  47. package/dist/common/response.interceptor.d.ts.map +0 -1
  48. package/dist/common/response.interceptor.js +0 -23
  49. package/dist/common/response.interceptor.js.map +0 -1
  50. package/dist/common/response.interceptor.test.d.ts +0 -2
  51. package/dist/common/response.interceptor.test.d.ts.map +0 -1
  52. package/dist/common/response.interceptor.test.js +0 -23
  53. package/dist/common/response.interceptor.test.js.map +0 -1
  54. package/dist/common/root-path.decorator.d.ts +0 -2
  55. package/dist/common/root-path.decorator.d.ts.map +0 -1
  56. package/dist/common/root-path.decorator.js +0 -6
  57. package/dist/common/root-path.decorator.js.map +0 -1
  58. package/dist/context/context.controller.d.ts +0 -43
  59. package/dist/context/context.controller.d.ts.map +0 -1
  60. package/dist/context/context.controller.js +0 -120
  61. package/dist/context/context.controller.js.map +0 -1
  62. package/dist/context/context.controller.spec.d.ts +0 -2
  63. package/dist/context/context.controller.spec.d.ts.map +0 -1
  64. package/dist/context/context.controller.spec.js +0 -191
  65. package/dist/context/context.controller.spec.js.map +0 -1
  66. package/dist/context/context.module.d.ts +0 -3
  67. package/dist/context/context.module.d.ts.map +0 -1
  68. package/dist/context/context.module.js +0 -18
  69. package/dist/context/context.module.js.map +0 -1
  70. package/dist/context/context.service.d.ts +0 -47
  71. package/dist/context/context.service.d.ts.map +0 -1
  72. package/dist/context/context.service.js +0 -104
  73. package/dist/context/context.service.js.map +0 -1
  74. package/dist/data/data.controller.d.ts +0 -19
  75. package/dist/data/data.controller.d.ts.map +0 -1
  76. package/dist/data/data.controller.js +0 -78
  77. package/dist/data/data.controller.js.map +0 -1
  78. package/dist/data/data.controller.spec.d.ts +0 -2
  79. package/dist/data/data.controller.spec.d.ts.map +0 -1
  80. package/dist/data/data.controller.spec.js +0 -85
  81. package/dist/data/data.controller.spec.js.map +0 -1
  82. package/dist/data/data.module.d.ts +0 -3
  83. package/dist/data/data.module.d.ts.map +0 -1
  84. package/dist/data/data.module.js +0 -22
  85. package/dist/data/data.module.js.map +0 -1
  86. package/dist/data/data.service.d.ts +0 -54
  87. package/dist/data/data.service.d.ts.map +0 -1
  88. package/dist/data/data.service.js +0 -99
  89. package/dist/data/data.service.js.map +0 -1
  90. package/dist/data/data.service.spec.d.ts +0 -2
  91. package/dist/data/data.service.spec.d.ts.map +0 -1
  92. package/dist/data/data.service.spec.js +0 -148
  93. package/dist/data/data.service.spec.js.map +0 -1
  94. package/dist/database/database.module.d.ts +0 -3
  95. package/dist/database/database.module.d.ts.map +0 -1
  96. package/dist/database/database.module.js +0 -28
  97. package/dist/database/database.module.js.map +0 -1
  98. package/dist/graph/graph.controller.d.ts +0 -15
  99. package/dist/graph/graph.controller.d.ts.map +0 -1
  100. package/dist/graph/graph.controller.js +0 -78
  101. package/dist/graph/graph.controller.js.map +0 -1
  102. package/dist/graph/graph.module.d.ts +0 -3
  103. package/dist/graph/graph.module.d.ts.map +0 -1
  104. package/dist/graph/graph.module.js +0 -18
  105. package/dist/graph/graph.module.js.map +0 -1
  106. package/dist/graph/graph.service.d.ts +0 -11
  107. package/dist/graph/graph.service.d.ts.map +0 -1
  108. package/dist/graph/graph.service.js +0 -45
  109. package/dist/graph/graph.service.js.map +0 -1
  110. package/dist/knowledge/knowledge.controller.d.ts +0 -15
  111. package/dist/knowledge/knowledge.controller.d.ts.map +0 -1
  112. package/dist/knowledge/knowledge.controller.js +0 -71
  113. package/dist/knowledge/knowledge.controller.js.map +0 -1
  114. package/dist/knowledge/knowledge.module.d.ts +0 -3
  115. package/dist/knowledge/knowledge.module.d.ts.map +0 -1
  116. package/dist/knowledge/knowledge.module.js +0 -18
  117. package/dist/knowledge/knowledge.module.js.map +0 -1
  118. package/dist/knowledge/knowledge.service.d.ts +0 -14
  119. package/dist/knowledge/knowledge.service.d.ts.map +0 -1
  120. package/dist/knowledge/knowledge.service.js +0 -75
  121. package/dist/knowledge/knowledge.service.js.map +0 -1
  122. package/dist/main.d.ts +0 -4
  123. package/dist/main.d.ts.map +0 -1
  124. package/dist/main.js +0 -79
  125. package/dist/main.js.map +0 -1
  126. package/dist/memory/memory.controller.d.ts +0 -69
  127. package/dist/memory/memory.controller.d.ts.map +0 -1
  128. package/dist/memory/memory.controller.js +0 -196
  129. package/dist/memory/memory.controller.js.map +0 -1
  130. package/dist/memory/memory.module.d.ts +0 -3
  131. package/dist/memory/memory.module.d.ts.map +0 -1
  132. package/dist/memory/memory.module.js +0 -18
  133. package/dist/memory/memory.module.js.map +0 -1
  134. package/dist/memory/memory.service.d.ts +0 -72
  135. package/dist/memory/memory.service.d.ts.map +0 -1
  136. package/dist/memory/memory.service.js +0 -128
  137. package/dist/memory/memory.service.js.map +0 -1
  138. package/dist/projects/projects.controller.d.ts +0 -32
  139. package/dist/projects/projects.controller.d.ts.map +0 -1
  140. package/dist/projects/projects.controller.js +0 -123
  141. package/dist/projects/projects.controller.js.map +0 -1
  142. package/dist/projects/projects.controller.spec.d.ts +0 -2
  143. package/dist/projects/projects.controller.spec.d.ts.map +0 -1
  144. package/dist/projects/projects.controller.spec.js +0 -81
  145. package/dist/projects/projects.controller.spec.js.map +0 -1
  146. package/dist/projects/projects.module.d.ts +0 -3
  147. package/dist/projects/projects.module.d.ts.map +0 -1
  148. package/dist/projects/projects.module.js +0 -16
  149. package/dist/projects/projects.module.js.map +0 -1
  150. package/dist/projects/projects.service.d.ts +0 -67
  151. package/dist/projects/projects.service.d.ts.map +0 -1
  152. package/dist/projects/projects.service.js +0 -100
  153. package/dist/projects/projects.service.js.map +0 -1
  154. package/dist/registry/registry.controller.d.ts +0 -28
  155. package/dist/registry/registry.controller.d.ts.map +0 -1
  156. package/dist/registry/registry.controller.js +0 -90
  157. package/dist/registry/registry.controller.js.map +0 -1
  158. package/dist/registry/registry.module.d.ts +0 -3
  159. package/dist/registry/registry.module.d.ts.map +0 -1
  160. package/dist/registry/registry.module.js +0 -17
  161. package/dist/registry/registry.module.js.map +0 -1
  162. package/dist/registry/registry.service.d.ts +0 -38
  163. package/dist/registry/registry.service.d.ts.map +0 -1
  164. package/dist/registry/registry.service.js +0 -146
  165. package/dist/registry/registry.service.js.map +0 -1
  166. package/dist/server.controller.d.ts +0 -8
  167. package/dist/server.controller.d.ts.map +0 -1
  168. package/dist/server.controller.js +0 -31
  169. package/dist/server.controller.js.map +0 -1
  170. package/dist/telemetry/auto-checker.d.ts +0 -23
  171. package/dist/telemetry/auto-checker.d.ts.map +0 -1
  172. package/dist/telemetry/auto-checker.js +0 -121
  173. package/dist/telemetry/auto-checker.js.map +0 -1
  174. package/dist/telemetry/telemetry.controller.d.ts +0 -201
  175. package/dist/telemetry/telemetry.controller.d.ts.map +0 -1
  176. package/dist/telemetry/telemetry.controller.js +0 -399
  177. package/dist/telemetry/telemetry.controller.js.map +0 -1
  178. package/dist/telemetry/telemetry.controller.spec.d.ts +0 -2
  179. package/dist/telemetry/telemetry.controller.spec.d.ts.map +0 -1
  180. package/dist/telemetry/telemetry.controller.spec.js +0 -78
  181. package/dist/telemetry/telemetry.controller.spec.js.map +0 -1
  182. package/dist/telemetry/telemetry.module.d.ts +0 -3
  183. package/dist/telemetry/telemetry.module.d.ts.map +0 -1
  184. package/dist/telemetry/telemetry.module.js +0 -23
  185. package/dist/telemetry/telemetry.module.js.map +0 -1
  186. package/dist/telemetry/telemetry.service.d.ts +0 -224
  187. package/dist/telemetry/telemetry.service.d.ts.map +0 -1
  188. package/dist/telemetry/telemetry.service.js +0 -663
  189. package/dist/telemetry/telemetry.service.js.map +0 -1
  190. package/dist/workflow/workflow.controller.d.ts +0 -50
  191. package/dist/workflow/workflow.controller.d.ts.map +0 -1
  192. package/dist/workflow/workflow.controller.js +0 -111
  193. package/dist/workflow/workflow.controller.js.map +0 -1
  194. package/dist/workflow/workflow.module.d.ts +0 -3
  195. package/dist/workflow/workflow.module.d.ts.map +0 -1
  196. package/dist/workflow/workflow.module.js +0 -16
  197. package/dist/workflow/workflow.module.js.map +0 -1
  198. package/dist/workflow/workflow.service.d.ts +0 -56
  199. package/dist/workflow/workflow.service.d.ts.map +0 -1
  200. package/dist/workflow/workflow.service.js +0 -224
  201. package/dist/workflow/workflow.service.js.map +0 -1
@@ -1,663 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
13
- import { Inject, Injectable, NotFoundException, Optional } from "@nestjs/common";
14
- import { TelemetryEngine } from "@devflow-tools/telemetry";
15
- import { DevFlowDatabase } from "@devflow-tools/database";
16
- import { ErrorCode } from "../common/error-codes.js";
17
- import { AutoChecker } from './auto-checker.js';
18
- let TelemetryService = class TelemetryService {
19
- constructor(database) {
20
- this.engine = new TelemetryEngine(); // Legacy in-memory store — real data goes through this.db
21
- this.db = database ?? null;
22
- }
23
- async recordEvent(event) {
24
- if (!this.db)
25
- return;
26
- this.db.insertEvent?.({
27
- runId: event.runId,
28
- kind: event.kind,
29
- timestamp: event.timestamp,
30
- duration: event.duration,
31
- toolName: event.data?.toolName,
32
- pluginName: event.data?.mcpToolName,
33
- metadata: event.data,
34
- });
35
- }
36
- // ---- Sessions ----
37
- async createSession(params) {
38
- if (!this.db)
39
- return;
40
- this.db.insertSession({
41
- id: params.id,
42
- projectRoot: params.projectRoot,
43
- label: params.label,
44
- startedAt: params.startedAt,
45
- });
46
- }
47
- async getSession(id) {
48
- if (!this.db)
49
- throw new NotFoundException({ error: { code: ErrorCode.RUN_NOT_FOUND, message: `Session "${id}" not found`, details: {} } });
50
- const session = this.db.getSession(id);
51
- if (!session)
52
- throw new NotFoundException({ error: { code: ErrorCode.RUN_NOT_FOUND, message: `Session "${id}" not found`, details: {} } });
53
- return session;
54
- }
55
- async listSessions(limit, offset, projectRoot) {
56
- if (!this.db)
57
- return [];
58
- return this.db.listSessions(limit, offset, projectRoot);
59
- }
60
- async getSessionEvents(sessionId) {
61
- if (!this.db)
62
- return [];
63
- return this.db.listToolCallEventsBySession?.(sessionId) ?? [];
64
- }
65
- async closeSession(id, finishedAt) {
66
- if (!this.db)
67
- return;
68
- this.db.closeSession(id, finishedAt);
69
- }
70
- async createSkillExecution(params) {
71
- if (!this.db)
72
- return;
73
- this.db.insertSkillExecution({
74
- executionId: params.executionId,
75
- sessionId: params.sessionId,
76
- skillName: params.skillName,
77
- startedAt: params.startedAt,
78
- status: 'running',
79
- });
80
- }
81
- // ---- Runs (now backed by sessions) ----
82
- async listRuns(limit, offset, source) {
83
- if (this.db) {
84
- try {
85
- const sessions = this.db.listSessions(limit, offset);
86
- return sessions.map((s) => ({
87
- id: s.id,
88
- agent: "claude-code",
89
- mode: "hook",
90
- source: "hook",
91
- status: s.status,
92
- startedAt: s.startedAt,
93
- totalToolCalls: s.totalToolCalls,
94
- mcpToolCalls: s.mcpToolCalls,
95
- mcpComplianceRate: s.mcpToolCalls > 0 ? Math.round(s.mcpToolCalls / s.totalToolCalls * 100) / 100 : 0,
96
- }));
97
- }
98
- catch { }
99
- }
100
- return [];
101
- }
102
- async getRun(id) {
103
- // Try session first, then skill execution, then engine
104
- if (this.db) {
105
- try {
106
- const s = this.db.getSession(id);
107
- if (s) {
108
- return {
109
- meta: { runId: s.id, agent: "claude-code", mode: "hook", source: "hook" },
110
- status: s.status,
111
- startedAt: s.startedAt,
112
- finishedAt: s.finishedAt,
113
- totalToolCalls: s.totalToolCalls,
114
- mcpToolCalls: s.mcpToolCalls,
115
- steps: [],
116
- };
117
- }
118
- const exec = this.db.getSkillExecution(id);
119
- if (exec) {
120
- return {
121
- meta: { runId: exec.executionId, agent: "claude-code", mode: "hook", source: "hook" },
122
- status: exec.status,
123
- startedAt: exec.startedAt,
124
- finishedAt: exec.finishedAt,
125
- skillName: exec.skillName,
126
- totalToolCalls: exec.totalToolCalls,
127
- mcpToolCalls: exec.mcpToolCalls,
128
- mcpComplianceRate: exec.mcpComplianceRate,
129
- steps: [],
130
- };
131
- }
132
- }
133
- catch { }
134
- }
135
- const run = this.engine.runs.get(id);
136
- if (run)
137
- return run;
138
- throw new NotFoundException({ error: { code: ErrorCode.RUN_NOT_FOUND, message: `Run "${id}" not found`, details: {} } });
139
- }
140
- async getTimeline(from, to) {
141
- if (!this.db)
142
- return [];
143
- try {
144
- const sessions = this.db.listSessions(500, 0);
145
- return sessions
146
- .filter((s) => {
147
- if (from && s.startedAt < Number(from))
148
- return false;
149
- if (to && s.startedAt > Number(to))
150
- return false;
151
- return true;
152
- })
153
- .map((s) => ({
154
- runId: s.id,
155
- stepId: s.id,
156
- type: "session",
157
- duration: s.durationMs,
158
- timestamp: s.startedAt,
159
- }));
160
- }
161
- catch {
162
- return [];
163
- }
164
- }
165
- async getRunEvents(runId) {
166
- // Try session events first
167
- if (this.db) {
168
- try {
169
- const events = this.db.listToolCallEventsBySession(runId);
170
- if (events && events.length > 0)
171
- return events;
172
- const execEvents = this.db.listToolCallEvents(runId);
173
- if (execEvents && execEvents.length > 0)
174
- return execEvents;
175
- }
176
- catch { }
177
- }
178
- const engineEvents = await this.engine.listEvents(runId);
179
- return engineEvents ?? [];
180
- }
181
- async getRunStats(runId) {
182
- if (this.db) {
183
- try {
184
- const events = this.db.listToolCallEventsBySession(runId) ?? this.db.listToolCallEvents(runId) ?? [];
185
- if (events.length > 0) {
186
- return {
187
- totalEvents: events.length,
188
- llmCalls: 0,
189
- totalTokens: 0,
190
- toolUses: events.length,
191
- fileReads: 0,
192
- fileWrites: 0,
193
- bashCommands: 0,
194
- errors: events.filter((e) => e.error).length,
195
- totalDuration: 0,
196
- mcpToolCalls: events.filter((e) => e.isMcpTool).length,
197
- directToolCalls: events.filter((e) => !e.isMcpTool).length,
198
- mcpComplianceRate: events.length > 0
199
- ? events.filter((e) => e.isMcpTool).length / events.length : 0,
200
- };
201
- }
202
- }
203
- catch { }
204
- }
205
- return this.engine.getRunStats(runId);
206
- }
207
- async endRun(runId, result) {
208
- await this.engine.endRun(runId, result);
209
- }
210
- // ---- Telemetry Stats (from sessions + tool_call_events) ----
211
- async getStats(periodDays = 7) {
212
- if (!this.db)
213
- return this.emptyStats();
214
- const now = Date.now();
215
- const cutoff = now - periodDays * 24 * 60 * 60 * 1000;
216
- try {
217
- const sessions = this.db.listSessions(1000, 0);
218
- const periodSessions = sessions.filter((s) => s.startedAt >= cutoff);
219
- const days = {};
220
- let totalToolCalls = 0;
221
- for (const s of periodSessions) {
222
- const day = new Date(s.startedAt).toISOString().slice(0, 10);
223
- if (!days[day])
224
- days[day] = { runs: 0 };
225
- days[day].runs++;
226
- totalToolCalls += s.totalToolCalls ?? 0;
227
- }
228
- // Aggregate from tool_call_events for period sessions
229
- const sessionIds = periodSessions.map((s) => s.id);
230
- const eventsBySession = this.db.listToolCallEventsBySessions?.(sessionIds) ?? {};
231
- let totalTokens = 0;
232
- let totalLlmCalls = 0;
233
- const workflowCounts = {};
234
- const pluginCounts = {};
235
- for (const [, events] of Object.entries(eventsBySession)) {
236
- for (const e of events) {
237
- totalTokens += e.tokensUsed ?? 0;
238
- if (e.kind === 'llm_call')
239
- totalLlmCalls++;
240
- // Derive workflow from tool name (e.g., react_diagnose_bug → react)
241
- const wf = e.toolName?.split('_')?.[1];
242
- if (wf) {
243
- workflowCounts[wf] = (workflowCounts[wf] ?? 0) + 1;
244
- }
245
- // Derive plugin from mcpToolName prefix
246
- const plugin = e.mcpToolName?.split('_')?.[0];
247
- if (plugin) {
248
- pluginCounts[plugin] = (pluginCounts[plugin] ?? 0) + 1;
249
- }
250
- }
251
- }
252
- return {
253
- period: {
254
- from: new Date(cutoff).toISOString().slice(0, 10),
255
- to: new Date(now).toISOString().slice(0, 10),
256
- },
257
- summary: {
258
- totalRuns: periodSessions.length,
259
- completedRuns: periodSessions.filter((s) => s.status === 'completed').length,
260
- failedRuns: periodSessions.filter((s) => s.status === 'failed').length,
261
- totalTokens,
262
- totalLlmCalls,
263
- totalToolUses: totalToolCalls,
264
- avgRunDuration: periodSessions.length > 0
265
- ? Math.round(periodSessions.reduce((sum, s) => sum + (s.durationMs ?? 0), 0) / periodSessions.length)
266
- : 0,
267
- },
268
- byDay: Object.entries(days)
269
- .map(([date, d]) => ({ date, tokens: 0, ...d }))
270
- .sort((a, b) => a.date.localeCompare(b.date)),
271
- byWorkflow: Object.entries(workflowCounts)
272
- .map(([name, count]) => ({ workflow: name, count }))
273
- .sort((a, b) => b.count - a.count),
274
- byPlugin: Object.entries(pluginCounts)
275
- .map(([name, count]) => ({ plugin: name, count }))
276
- .sort((a, b) => b.count - a.count),
277
- };
278
- }
279
- catch {
280
- return this.emptyStats();
281
- }
282
- }
283
- emptyStats() {
284
- return {
285
- period: { from: '', to: '' },
286
- summary: { totalRuns: 0, completedRuns: 0, failedRuns: 0, totalTokens: 0, totalLlmCalls: 0, totalToolUses: 0, avgRunDuration: 0 },
287
- byDay: [],
288
- byWorkflow: [],
289
- byPlugin: [],
290
- };
291
- }
292
- // ---- ROI Summary (from sessions + tool_call_events) ----
293
- async getRoiSummary(periodDays = 7) {
294
- if (!this.db)
295
- return this.emptyRoiSummary();
296
- const now = Date.now();
297
- const cutoff = now - periodDays * 24 * 60 * 60 * 1000;
298
- try {
299
- const sessions = this.db.listSessions(1000, 0);
300
- const periodSessions = sessions.filter((s) => s.startedAt >= cutoff);
301
- const totalRuns = periodSessions.length;
302
- const completedRuns = periodSessions.filter((s) => s.status === 'completed').length;
303
- const failedRuns = periodSessions.filter((s) => s.status === 'failed').length;
304
- const avgDuration = totalRuns > 0
305
- ? Math.round(periodSessions.reduce((sum, s) => sum + (s.durationMs ?? 0), 0) / totalRuns)
306
- : 0;
307
- // Daily breakdown
308
- const days = {};
309
- for (const s of periodSessions) {
310
- const day = new Date(s.startedAt).toISOString().slice(0, 10);
311
- if (!days[day])
312
- days[day] = { runs: 0, failures: 0 };
313
- days[day].runs++;
314
- if (s.status === 'failed')
315
- days[day].failures++;
316
- }
317
- // Batch fetch all events for all period sessions
318
- const allEventGroups = this.db.listToolCallEventsBySessions(periodSessions.map((s) => s.id));
319
- // Failure breakdown from tool_call_events errors
320
- const failureBreakdown = {
321
- tool_error: 0,
322
- mcp_unavailable: 0,
323
- unknown: 0,
324
- };
325
- const byPlugin = {};
326
- for (const s of periodSessions) {
327
- const events = (allEventGroups[s.id] ?? []);
328
- for (const e of events) {
329
- if (e.error) {
330
- const err = e.error.toLowerCase();
331
- if (err.includes('mcp') || err.includes('unavailable') || err.includes('not found'))
332
- failureBreakdown.mcp_unavailable++;
333
- else if (err.includes('tool') || err.includes('command') || err.includes('error'))
334
- failureBreakdown.tool_error++;
335
- else
336
- failureBreakdown.unknown++;
337
- }
338
- if (e.mcpToolName) {
339
- const prefix = e.mcpToolName.split('_')[0];
340
- if (prefix)
341
- byPlugin[prefix] = (byPlugin[prefix] ?? 0) + 1;
342
- }
343
- }
344
- }
345
- return {
346
- period: {
347
- from: new Date(cutoff).toISOString().slice(0, 10),
348
- to: new Date(now).toISOString().slice(0, 10),
349
- },
350
- overview: {
351
- totalRuns,
352
- completedRuns,
353
- failedRuns,
354
- avgDuration,
355
- firstPassSuccessRate: totalRuns > 0 ? Math.round((completedRuns / totalRuns) * 10000) / 100 : 0,
356
- },
357
- efficiency: {
358
- avgTimePerTask: avgDuration,
359
- },
360
- failures: {
361
- total: failedRuns,
362
- breakdown: failureBreakdown,
363
- },
364
- workflows: [],
365
- plugins: Object.entries(byPlugin).map(([name, runs]) => {
366
- const pluginSessions = periodSessions.filter((s) => {
367
- const evts = (allEventGroups[s.id] ?? []);
368
- return evts.some((e) => e.mcpToolName?.startsWith(name + '_'));
369
- });
370
- const completed = pluginSessions.filter((s) => s.status === 'completed').length;
371
- const successRate = pluginSessions.length > 0
372
- ? Math.round((completed / pluginSessions.length) * 10000) / 100
373
- : 0;
374
- return { name, runs, successRate };
375
- }),
376
- byDay: Object.entries(days)
377
- .map(([date, d]) => ({ date, ...d, tokens: 0 }))
378
- .sort((a, b) => a.date.localeCompare(b.date)),
379
- };
380
- }
381
- catch {
382
- return this.emptyRoiSummary();
383
- }
384
- }
385
- emptyRoiSummary() {
386
- return {
387
- period: { from: '', to: '' },
388
- overview: { totalRuns: 0, completedRuns: 0, failedRuns: 0, avgDuration: 0, firstPassSuccessRate: 0 },
389
- efficiency: { avgTimePerTask: 0 },
390
- failures: { total: 0, breakdown: { tool_error: 0, mcp_unavailable: 0, unknown: 0 } },
391
- workflows: [],
392
- plugins: [],
393
- byDay: [],
394
- };
395
- }
396
- // ---- Skill Execution Tracking ----
397
- async recordExecutionStart(params) {
398
- if (!this.db)
399
- return;
400
- this.db.insertSkillExecution({
401
- executionId: params.executionId,
402
- sessionId: params.sessionId,
403
- skillName: params.skillName,
404
- startedAt: params.startedAt,
405
- status: 'running',
406
- });
407
- }
408
- async recordToolCall(event) {
409
- if (!this.db)
410
- return;
411
- try {
412
- this.db.insertToolCallEvent({
413
- eventId: event.eventId,
414
- executionId: event.executionId,
415
- sessionId: event.sessionId,
416
- timestamp: event.timestamp,
417
- toolName: event.toolName,
418
- toolType: event.toolType,
419
- isMcpTool: event.isMcpTool,
420
- mcpToolName: event.mcpToolName,
421
- mcpEnforced: event.mcpEnforced,
422
- mcpFallback: event.mcpFallback,
423
- kind: event.kind ?? 'tool_use',
424
- input: event.input,
425
- duration: event.duration,
426
- parentToolCallId: event.parentToolCallId,
427
- subagentId: event.subagentId,
428
- error: event.error,
429
- blocked: event.blocked,
430
- blockReason: event.blockReason,
431
- });
432
- }
433
- catch { }
434
- }
435
- async updateToolCallOutput(eventId, output, completedAt, duration) {
436
- if (!this.db)
437
- return;
438
- try {
439
- this.db.updateToolCallEvent(eventId, { output: JSON.stringify(output), duration });
440
- }
441
- catch { }
442
- }
443
- async recordExecutionComplete(params) {
444
- if (!this.db)
445
- return;
446
- this.db.updateSkillExecution(params.executionId, {
447
- status: params.status,
448
- finishedAt: params.finishedAt,
449
- totalDuration: params.summary.totalDuration,
450
- mcpComplianceRate: params.summary.mcpComplianceRate,
451
- totalToolCalls: params.summary.totalToolCalls,
452
- mcpToolCalls: params.summary.mcpToolCalls,
453
- directToolCalls: params.summary.directToolCalls,
454
- subagentCount: params.summary.subagentCount,
455
- });
456
- }
457
- async getExecutions(limit, skillName) {
458
- if (!this.db)
459
- return [];
460
- return this.db.listSkillExecutions(limit, skillName);
461
- }
462
- async getExecutionEvents(executionId) {
463
- if (!this.db)
464
- return [];
465
- return this.db.listToolCallEvents(executionId);
466
- }
467
- async getMcpCompliance() {
468
- if (!this.db)
469
- return { overall: 0, bySkill: {}, missedTools: [] };
470
- return this.db.getMcpCompliance();
471
- }
472
- // ---- Failure classification (unchanged) ----
473
- async classifyFailure(runId) {
474
- const run = await this.getRun(runId).catch(() => null);
475
- if (!run || run.status !== "failed")
476
- return {};
477
- const failedStep = run.steps?.find((s) => s.status === "failed");
478
- if (!failedStep)
479
- return {};
480
- const error = failedStep.error?.toLowerCase() ?? "";
481
- if (error.includes("context") || error.includes("insufficient")) {
482
- return {
483
- failureCategory: "context_insufficient",
484
- failureReason: "Context provided was insufficient for the task",
485
- suggestedActions: [
486
- { action: "Supplement task context", priority: "high" },
487
- { action: "View graph roots", priority: "medium" },
488
- { action: "Add related memory", priority: "medium" },
489
- ],
490
- };
491
- }
492
- if (error.includes("knowledge") || error.includes("docs")) {
493
- return {
494
- failureCategory: "knowledge_missing",
495
- failureReason: "Required knowledge was not available",
496
- suggestedActions: [
497
- { action: "Sync knowledge source", priority: "high" },
498
- { action: "Add docs source", priority: "medium" },
499
- ],
500
- };
501
- }
502
- if (error.includes("workflow") || error.includes("step")) {
503
- return {
504
- failureCategory: "workflow_design_issue",
505
- failureReason: "Workflow design issue detected",
506
- suggestedActions: [
507
- { action: "Adjust specific step", priority: "high" },
508
- { action: "Split workflow", priority: "medium" },
509
- ],
510
- };
511
- }
512
- if (error.includes("tool") || error.includes("connection")) {
513
- return {
514
- failureCategory: "tool_error",
515
- failureReason: "Tool execution error",
516
- suggestedActions: [
517
- { action: "Check tool connectivity", priority: "high" },
518
- { action: "Retry or fallback", priority: "medium" },
519
- ],
520
- };
521
- }
522
- return {
523
- failureCategory: "agent_override",
524
- failureReason: "Agent override detected",
525
- suggestedActions: [
526
- { action: "Enable/strengthen enforcer", priority: "high" },
527
- ],
528
- };
529
- }
530
- async cleanup(olderThanDays) {
531
- if (!this.db)
532
- return 0;
533
- try {
534
- this.db.cleanupStaleRecords?.();
535
- }
536
- catch { }
537
- // Also clean up legacy engine runs
538
- const runs = this.engine.runs;
539
- const cutoff = Date.now() - olderThanDays * 24 * 60 * 60 * 1000;
540
- let removed = 0;
541
- for (const [id, run] of runs) {
542
- if (run.startedAt && run.startedAt < cutoff) {
543
- runs.delete(id);
544
- removed++;
545
- }
546
- }
547
- return removed;
548
- }
549
- // @Interval(5 * 60 * 1000) — uncomment when @nestjs/schedule is available
550
- async cleanupStaleRecords() {
551
- if (!this.db)
552
- return;
553
- try {
554
- this.db.cleanupStaleRecords?.();
555
- }
556
- catch { /* best-effort */ }
557
- }
558
- // ---- Stub methods for external callers that reference old API ----
559
- // ---- Tool Metrics ----
560
- async recordToolMetric(metric) {
561
- if (!this.db)
562
- return;
563
- this.db.insertToolMetric({ ...metric, createdAt: Date.now() });
564
- }
565
- async getToolMetrics(sessionId, toolName, limit = 100, offset = 0) {
566
- if (!this.db)
567
- return [];
568
- return this.db.getToolMetrics(sessionId, toolName, limit, offset);
569
- }
570
- async getToolMetricsSummary(days = 7) {
571
- if (!this.db)
572
- return [];
573
- return this.db.getToolMetricsSummary(days);
574
- }
575
- // ---- Accuracy Queries ----
576
- async recordAccuracyQuery(params) {
577
- if (!this.db)
578
- return;
579
- this.db.insertAccuracyQuery({ ...params, createdAt: Date.now() });
580
- }
581
- async getAccuracyQueries(options) {
582
- if (!this.db)
583
- return [];
584
- return this.db.getAccuracyQueries(options);
585
- }
586
- async updateAccuracyFeedback(id, feedback) {
587
- if (!this.db)
588
- return;
589
- this.db.updateAccuracyFeedback(id, feedback);
590
- }
591
- async getAccuracyStats(engine, since) {
592
- if (!this.db)
593
- return { totalQueries: 0, annotatedQueries: 0, hitRate: null };
594
- return this.db.getAccuracyStats(engine, since);
595
- }
596
- // ---- Auto Checker ----
597
- async runAutoCheck() {
598
- if (!this.db)
599
- return [];
600
- const checker = new AutoChecker(this.db);
601
- return checker.checkAll();
602
- }
603
- // ---- Stub methods ----
604
- async getFeedbackStats(_projectRoot, _periodDays) {
605
- return { total: 0, hits: 0, partials: 0, misses: 0, hitRate: 0, partialRate: 0, missRate: 0 };
606
- }
607
- async getOpsRoiSummary() {
608
- return {
609
- period: "all-time",
610
- totalRuns: 0,
611
- successfulRuns: 0,
612
- successRate: 0,
613
- avgDuration: 0,
614
- trend: "stable",
615
- };
616
- }
617
- async getExperimentalRoiSummary() {
618
- return {
619
- totalScenarios: 0,
620
- avgTimeSavedRate: null,
621
- avgTokenReductionRate: null,
622
- avgFirstPassLift: null,
623
- avgReworkReductionRate: null,
624
- conclusion: "No experimental data available yet",
625
- };
626
- }
627
- async getPluginEffectiveness(pluginName, _projectRoot) {
628
- if (!this.db)
629
- return { name: pluginName, totalRuns: 0, successRate: 0, lastUsedAt: null };
630
- const sessions = this.db.listSessions(1000, 0);
631
- let useCount = 0;
632
- for (const s of sessions) {
633
- const events = this.db.listToolCallEventsBySession(s.id);
634
- for (const e of events) {
635
- if (e.mcpToolName?.startsWith(pluginName + '_'))
636
- useCount++;
637
- }
638
- }
639
- return {
640
- name: pluginName,
641
- totalRuns: useCount,
642
- successRate: 0,
643
- lastUsedAt: null,
644
- };
645
- }
646
- async getPluginUsageStats(pluginName) {
647
- const eff = await this.getPluginEffectiveness(pluginName);
648
- return {
649
- activeProjects: 0,
650
- totalRuns: eff.totalRuns,
651
- successfulRuns: 0,
652
- lastUsedAt: eff.lastUsedAt ?? undefined,
653
- };
654
- }
655
- };
656
- TelemetryService = __decorate([
657
- Injectable(),
658
- __param(0, Optional()),
659
- __param(0, Inject('DATABASE')),
660
- __metadata("design:paramtypes", [DevFlowDatabase])
661
- ], TelemetryService);
662
- export { TelemetryService };
663
- //# sourceMappingURL=telemetry.service.js.map