@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.
- package/package.json +2 -2
- package/dist/app.module.d.ts +0 -3
- package/dist/app.module.d.ts.map +0 -1
- package/dist/app.module.js +0 -42
- package/dist/app.module.js.map +0 -1
- package/dist/auth/api-key.decorator.d.ts +0 -3
- package/dist/auth/api-key.decorator.d.ts.map +0 -1
- package/dist/auth/api-key.decorator.js +0 -4
- package/dist/auth/api-key.decorator.js.map +0 -1
- package/dist/auth/api-key.guard.d.ts +0 -8
- package/dist/auth/api-key.guard.d.ts.map +0 -1
- package/dist/auth/api-key.guard.js +0 -61
- package/dist/auth/api-key.guard.js.map +0 -1
- package/dist/auth/auth.module.d.ts +0 -3
- package/dist/auth/auth.module.d.ts.map +0 -1
- package/dist/auth/auth.module.js +0 -19
- package/dist/auth/auth.module.js.map +0 -1
- package/dist/auth/errors.d.ts +0 -6
- package/dist/auth/errors.d.ts.map +0 -1
- package/dist/auth/errors.js +0 -5
- package/dist/auth/errors.js.map +0 -1
- package/dist/benchmark/benchmark.controller.d.ts +0 -11
- package/dist/benchmark/benchmark.controller.d.ts.map +0 -1
- package/dist/benchmark/benchmark.controller.js +0 -35
- package/dist/benchmark/benchmark.controller.js.map +0 -1
- package/dist/benchmark/benchmark.module.d.ts +0 -3
- package/dist/benchmark/benchmark.module.d.ts.map +0 -1
- package/dist/benchmark/benchmark.module.js +0 -16
- package/dist/benchmark/benchmark.module.js.map +0 -1
- package/dist/benchmark/benchmark.service.d.ts +0 -12
- package/dist/benchmark/benchmark.service.d.ts.map +0 -1
- package/dist/benchmark/benchmark.service.js +0 -58
- package/dist/benchmark/benchmark.service.js.map +0 -1
- package/dist/common/dto.d.ts +0 -12
- package/dist/common/dto.d.ts.map +0 -1
- package/dist/common/dto.js +0 -2
- package/dist/common/dto.js.map +0 -1
- package/dist/common/error-codes.d.ts +0 -17
- package/dist/common/error-codes.d.ts.map +0 -1
- package/dist/common/error-codes.js +0 -16
- package/dist/common/error-codes.js.map +0 -1
- package/dist/common/http-exception.filter.d.ts +0 -6
- package/dist/common/http-exception.filter.d.ts.map +0 -1
- package/dist/common/http-exception.filter.js +0 -77
- package/dist/common/http-exception.filter.js.map +0 -1
- package/dist/common/response.interceptor.d.ts +0 -6
- package/dist/common/response.interceptor.d.ts.map +0 -1
- package/dist/common/response.interceptor.js +0 -23
- package/dist/common/response.interceptor.js.map +0 -1
- package/dist/common/response.interceptor.test.d.ts +0 -2
- package/dist/common/response.interceptor.test.d.ts.map +0 -1
- package/dist/common/response.interceptor.test.js +0 -23
- package/dist/common/response.interceptor.test.js.map +0 -1
- package/dist/common/root-path.decorator.d.ts +0 -2
- package/dist/common/root-path.decorator.d.ts.map +0 -1
- package/dist/common/root-path.decorator.js +0 -6
- package/dist/common/root-path.decorator.js.map +0 -1
- package/dist/context/context.controller.d.ts +0 -43
- package/dist/context/context.controller.d.ts.map +0 -1
- package/dist/context/context.controller.js +0 -120
- package/dist/context/context.controller.js.map +0 -1
- package/dist/context/context.controller.spec.d.ts +0 -2
- package/dist/context/context.controller.spec.d.ts.map +0 -1
- package/dist/context/context.controller.spec.js +0 -191
- package/dist/context/context.controller.spec.js.map +0 -1
- package/dist/context/context.module.d.ts +0 -3
- package/dist/context/context.module.d.ts.map +0 -1
- package/dist/context/context.module.js +0 -18
- package/dist/context/context.module.js.map +0 -1
- package/dist/context/context.service.d.ts +0 -47
- package/dist/context/context.service.d.ts.map +0 -1
- package/dist/context/context.service.js +0 -104
- package/dist/context/context.service.js.map +0 -1
- package/dist/data/data.controller.d.ts +0 -19
- package/dist/data/data.controller.d.ts.map +0 -1
- package/dist/data/data.controller.js +0 -78
- package/dist/data/data.controller.js.map +0 -1
- package/dist/data/data.controller.spec.d.ts +0 -2
- package/dist/data/data.controller.spec.d.ts.map +0 -1
- package/dist/data/data.controller.spec.js +0 -85
- package/dist/data/data.controller.spec.js.map +0 -1
- package/dist/data/data.module.d.ts +0 -3
- package/dist/data/data.module.d.ts.map +0 -1
- package/dist/data/data.module.js +0 -22
- package/dist/data/data.module.js.map +0 -1
- package/dist/data/data.service.d.ts +0 -54
- package/dist/data/data.service.d.ts.map +0 -1
- package/dist/data/data.service.js +0 -99
- package/dist/data/data.service.js.map +0 -1
- package/dist/data/data.service.spec.d.ts +0 -2
- package/dist/data/data.service.spec.d.ts.map +0 -1
- package/dist/data/data.service.spec.js +0 -148
- package/dist/data/data.service.spec.js.map +0 -1
- package/dist/database/database.module.d.ts +0 -3
- package/dist/database/database.module.d.ts.map +0 -1
- package/dist/database/database.module.js +0 -28
- package/dist/database/database.module.js.map +0 -1
- package/dist/graph/graph.controller.d.ts +0 -15
- package/dist/graph/graph.controller.d.ts.map +0 -1
- package/dist/graph/graph.controller.js +0 -78
- package/dist/graph/graph.controller.js.map +0 -1
- package/dist/graph/graph.module.d.ts +0 -3
- package/dist/graph/graph.module.d.ts.map +0 -1
- package/dist/graph/graph.module.js +0 -18
- package/dist/graph/graph.module.js.map +0 -1
- package/dist/graph/graph.service.d.ts +0 -11
- package/dist/graph/graph.service.d.ts.map +0 -1
- package/dist/graph/graph.service.js +0 -45
- package/dist/graph/graph.service.js.map +0 -1
- package/dist/knowledge/knowledge.controller.d.ts +0 -15
- package/dist/knowledge/knowledge.controller.d.ts.map +0 -1
- package/dist/knowledge/knowledge.controller.js +0 -71
- package/dist/knowledge/knowledge.controller.js.map +0 -1
- package/dist/knowledge/knowledge.module.d.ts +0 -3
- package/dist/knowledge/knowledge.module.d.ts.map +0 -1
- package/dist/knowledge/knowledge.module.js +0 -18
- package/dist/knowledge/knowledge.module.js.map +0 -1
- package/dist/knowledge/knowledge.service.d.ts +0 -14
- package/dist/knowledge/knowledge.service.d.ts.map +0 -1
- package/dist/knowledge/knowledge.service.js +0 -75
- package/dist/knowledge/knowledge.service.js.map +0 -1
- package/dist/main.d.ts +0 -4
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -79
- package/dist/main.js.map +0 -1
- package/dist/memory/memory.controller.d.ts +0 -69
- package/dist/memory/memory.controller.d.ts.map +0 -1
- package/dist/memory/memory.controller.js +0 -196
- package/dist/memory/memory.controller.js.map +0 -1
- package/dist/memory/memory.module.d.ts +0 -3
- package/dist/memory/memory.module.d.ts.map +0 -1
- package/dist/memory/memory.module.js +0 -18
- package/dist/memory/memory.module.js.map +0 -1
- package/dist/memory/memory.service.d.ts +0 -72
- package/dist/memory/memory.service.d.ts.map +0 -1
- package/dist/memory/memory.service.js +0 -128
- package/dist/memory/memory.service.js.map +0 -1
- package/dist/projects/projects.controller.d.ts +0 -32
- package/dist/projects/projects.controller.d.ts.map +0 -1
- package/dist/projects/projects.controller.js +0 -123
- package/dist/projects/projects.controller.js.map +0 -1
- package/dist/projects/projects.controller.spec.d.ts +0 -2
- package/dist/projects/projects.controller.spec.d.ts.map +0 -1
- package/dist/projects/projects.controller.spec.js +0 -81
- package/dist/projects/projects.controller.spec.js.map +0 -1
- package/dist/projects/projects.module.d.ts +0 -3
- package/dist/projects/projects.module.d.ts.map +0 -1
- package/dist/projects/projects.module.js +0 -16
- package/dist/projects/projects.module.js.map +0 -1
- package/dist/projects/projects.service.d.ts +0 -67
- package/dist/projects/projects.service.d.ts.map +0 -1
- package/dist/projects/projects.service.js +0 -100
- package/dist/projects/projects.service.js.map +0 -1
- package/dist/registry/registry.controller.d.ts +0 -28
- package/dist/registry/registry.controller.d.ts.map +0 -1
- package/dist/registry/registry.controller.js +0 -90
- package/dist/registry/registry.controller.js.map +0 -1
- package/dist/registry/registry.module.d.ts +0 -3
- package/dist/registry/registry.module.d.ts.map +0 -1
- package/dist/registry/registry.module.js +0 -17
- package/dist/registry/registry.module.js.map +0 -1
- package/dist/registry/registry.service.d.ts +0 -38
- package/dist/registry/registry.service.d.ts.map +0 -1
- package/dist/registry/registry.service.js +0 -146
- package/dist/registry/registry.service.js.map +0 -1
- package/dist/server.controller.d.ts +0 -8
- package/dist/server.controller.d.ts.map +0 -1
- package/dist/server.controller.js +0 -31
- package/dist/server.controller.js.map +0 -1
- package/dist/telemetry/auto-checker.d.ts +0 -23
- package/dist/telemetry/auto-checker.d.ts.map +0 -1
- package/dist/telemetry/auto-checker.js +0 -121
- package/dist/telemetry/auto-checker.js.map +0 -1
- package/dist/telemetry/telemetry.controller.d.ts +0 -201
- package/dist/telemetry/telemetry.controller.d.ts.map +0 -1
- package/dist/telemetry/telemetry.controller.js +0 -399
- package/dist/telemetry/telemetry.controller.js.map +0 -1
- package/dist/telemetry/telemetry.controller.spec.d.ts +0 -2
- package/dist/telemetry/telemetry.controller.spec.d.ts.map +0 -1
- package/dist/telemetry/telemetry.controller.spec.js +0 -78
- package/dist/telemetry/telemetry.controller.spec.js.map +0 -1
- package/dist/telemetry/telemetry.module.d.ts +0 -3
- package/dist/telemetry/telemetry.module.d.ts.map +0 -1
- package/dist/telemetry/telemetry.module.js +0 -23
- package/dist/telemetry/telemetry.module.js.map +0 -1
- package/dist/telemetry/telemetry.service.d.ts +0 -224
- package/dist/telemetry/telemetry.service.d.ts.map +0 -1
- package/dist/telemetry/telemetry.service.js +0 -663
- package/dist/telemetry/telemetry.service.js.map +0 -1
- package/dist/workflow/workflow.controller.d.ts +0 -50
- package/dist/workflow/workflow.controller.d.ts.map +0 -1
- package/dist/workflow/workflow.controller.js +0 -111
- package/dist/workflow/workflow.controller.js.map +0 -1
- package/dist/workflow/workflow.module.d.ts +0 -3
- package/dist/workflow/workflow.module.d.ts.map +0 -1
- package/dist/workflow/workflow.module.js +0 -16
- package/dist/workflow/workflow.module.js.map +0 -1
- package/dist/workflow/workflow.service.d.ts +0 -56
- package/dist/workflow/workflow.service.d.ts.map +0 -1
- package/dist/workflow/workflow.service.js +0 -224
- 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
|