@infinitedusky/indusk-mcp 1.11.8 → 1.12.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.
|
@@ -48,6 +48,12 @@ export async function evalSummary(projectRoot, opts) {
|
|
|
48
48
|
console.info(` ${id.padEnd(20)} ${bar} ${(rate * 100).toFixed(0)}%`);
|
|
49
49
|
}
|
|
50
50
|
console.info(`\nGraphiti writes: ${summary.totalGraphitiWrites}`);
|
|
51
|
+
if (summary.totalCostUsd > 0) {
|
|
52
|
+
console.info(`\nCost:`);
|
|
53
|
+
console.info(` total: $${summary.totalCostUsd.toFixed(2)}`);
|
|
54
|
+
console.info(` per eval: $${(summary.totalCostUsd / scorecards.length).toFixed(2)}`);
|
|
55
|
+
console.info(` tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out`);
|
|
56
|
+
}
|
|
51
57
|
if (summary.evalCount >= 10) {
|
|
52
58
|
console.info(`\nTrend (last 10 vs previous 10):`);
|
|
53
59
|
for (const [id, delta] of Object.entries(summary.trend)) {
|
|
@@ -94,6 +100,9 @@ function computeSummary(scorecards) {
|
|
|
94
100
|
baselineCount: baselineCards.length,
|
|
95
101
|
passRates,
|
|
96
102
|
totalGraphitiWrites: scorecards.reduce((sum, s) => sum + s.graphitiWrites, 0),
|
|
103
|
+
totalCostUsd: scorecards.reduce((sum, s) => sum + (s.usage?.costUsd ?? 0), 0),
|
|
104
|
+
totalInputTokens: scorecards.reduce((sum, s) => sum + (s.usage?.inputTokens ?? 0) + (s.usage?.cacheReadTokens ?? 0), 0),
|
|
105
|
+
totalOutputTokens: scorecards.reduce((sum, s) => sum + (s.usage?.outputTokens ?? 0), 0),
|
|
97
106
|
trend,
|
|
98
107
|
};
|
|
99
108
|
}
|
|
@@ -91,12 +91,24 @@ export function runJudgeBackground(opts) {
|
|
|
91
91
|
if (code !== 0) {
|
|
92
92
|
throw new Error(`claude exited with code ${code}: ${stderr.slice(0, 500)}`);
|
|
93
93
|
}
|
|
94
|
-
// --output-format json wraps the result; extract the text content
|
|
94
|
+
// --output-format json wraps the result; extract the text content and usage
|
|
95
95
|
let scorecardText = stdout;
|
|
96
|
+
let usage;
|
|
96
97
|
try {
|
|
97
98
|
const jsonOutput = JSON.parse(stdout);
|
|
98
|
-
// claude --print --output-format json returns { result: string } or similar
|
|
99
99
|
scorecardText = jsonOutput.result ?? jsonOutput.text ?? jsonOutput.content ?? stdout;
|
|
100
|
+
// Capture usage data from claude --print output
|
|
101
|
+
if (jsonOutput.total_cost_usd !== undefined || jsonOutput.usage) {
|
|
102
|
+
const u = jsonOutput.usage ?? {};
|
|
103
|
+
usage = {
|
|
104
|
+
costUsd: jsonOutput.total_cost_usd ?? 0,
|
|
105
|
+
inputTokens: u.input_tokens ?? 0,
|
|
106
|
+
outputTokens: u.output_tokens ?? 0,
|
|
107
|
+
cacheCreationTokens: u.cache_creation_input_tokens ?? 0,
|
|
108
|
+
cacheReadTokens: u.cache_read_input_tokens ?? 0,
|
|
109
|
+
durationMs: jsonOutput.duration_ms ?? 0,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
100
112
|
}
|
|
101
113
|
catch {
|
|
102
114
|
// stdout might be raw JSON scorecard already
|
|
@@ -107,6 +119,8 @@ export function runJudgeBackground(opts) {
|
|
|
107
119
|
scorecardText = jsonMatch[1];
|
|
108
120
|
}
|
|
109
121
|
const scorecard = JSON.parse(scorecardText.trim());
|
|
122
|
+
if (usage)
|
|
123
|
+
scorecard.usage = usage;
|
|
110
124
|
scorecard.telemetryPosted = false;
|
|
111
125
|
if (opts.evalEndpoint) {
|
|
112
126
|
await postTelemetry(opts.evalEndpoint, scorecard);
|
|
@@ -184,9 +198,21 @@ export async function runJudgeSync(opts) {
|
|
|
184
198
|
throw new Error(`claude exited with code ${code}: ${stderr.slice(0, 500)}`);
|
|
185
199
|
}
|
|
186
200
|
let scorecardText = stdout;
|
|
201
|
+
let syncUsage;
|
|
187
202
|
try {
|
|
188
203
|
const jsonOutput = JSON.parse(stdout);
|
|
189
204
|
scorecardText = jsonOutput.result ?? jsonOutput.text ?? jsonOutput.content ?? stdout;
|
|
205
|
+
if (jsonOutput.total_cost_usd !== undefined || jsonOutput.usage) {
|
|
206
|
+
const u = jsonOutput.usage ?? {};
|
|
207
|
+
syncUsage = {
|
|
208
|
+
costUsd: jsonOutput.total_cost_usd ?? 0,
|
|
209
|
+
inputTokens: u.input_tokens ?? 0,
|
|
210
|
+
outputTokens: u.output_tokens ?? 0,
|
|
211
|
+
cacheCreationTokens: u.cache_creation_input_tokens ?? 0,
|
|
212
|
+
cacheReadTokens: u.cache_read_input_tokens ?? 0,
|
|
213
|
+
durationMs: jsonOutput.duration_ms ?? 0,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
190
216
|
}
|
|
191
217
|
catch {
|
|
192
218
|
// raw JSON
|
|
@@ -196,6 +222,8 @@ export async function runJudgeSync(opts) {
|
|
|
196
222
|
scorecardText = jsonMatch[1];
|
|
197
223
|
}
|
|
198
224
|
const scorecard = JSON.parse(scorecardText.trim());
|
|
225
|
+
if (syncUsage)
|
|
226
|
+
scorecard.usage = syncUsage;
|
|
199
227
|
scorecard.telemetryPosted = false;
|
|
200
228
|
if (opts.evalEndpoint) {
|
|
201
229
|
await postTelemetry(opts.evalEndpoint, scorecard);
|
package/dist/lib/eval/types.d.ts
CHANGED
|
@@ -17,6 +17,14 @@ export interface EvalQuestion {
|
|
|
17
17
|
evidence: string;
|
|
18
18
|
finding: string;
|
|
19
19
|
}
|
|
20
|
+
export interface EvalUsage {
|
|
21
|
+
costUsd: number;
|
|
22
|
+
inputTokens: number;
|
|
23
|
+
outputTokens: number;
|
|
24
|
+
cacheCreationTokens: number;
|
|
25
|
+
cacheReadTokens: number;
|
|
26
|
+
durationMs: number;
|
|
27
|
+
}
|
|
20
28
|
export interface EvalScorecard {
|
|
21
29
|
version: 1;
|
|
22
30
|
timestamp: string;
|
|
@@ -27,6 +35,7 @@ export interface EvalScorecard {
|
|
|
27
35
|
summary: string;
|
|
28
36
|
graphitiWrites: number;
|
|
29
37
|
telemetryPosted: boolean;
|
|
38
|
+
usage?: EvalUsage;
|
|
30
39
|
}
|
|
31
40
|
export interface EvalErrorEntry {
|
|
32
41
|
version: 1;
|
package/dist/server/index.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
process.on("uncaughtException", (err) => {
|
|
2
|
+
console.error(`[indusk] uncaught exception: ${err.message}`);
|
|
3
|
+
if (err.stack)
|
|
4
|
+
console.error(err.stack);
|
|
5
|
+
process.exit(1);
|
|
6
|
+
});
|
|
7
|
+
process.on("unhandledRejection", (reason) => {
|
|
8
|
+
console.error(`[indusk] unhandled rejection: ${reason}`);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
});
|
|
1
11
|
import { readFileSync } from "node:fs";
|
|
2
12
|
import { dirname, join, resolve } from "node:path";
|
|
3
13
|
import { fileURLToPath } from "node:url";
|
|
@@ -32,19 +42,32 @@ function checkForUpdates(currentVersion) {
|
|
|
32
42
|
export async function startServer() {
|
|
33
43
|
const projectRoot = resolve(process.env.PROJECT_ROOT ?? ".");
|
|
34
44
|
const version = getLocalVersion();
|
|
45
|
+
console.error(`[indusk] v${version} starting (project: ${projectRoot})`);
|
|
35
46
|
// Non-blocking version check
|
|
36
47
|
checkForUpdates(version);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
try {
|
|
49
|
+
const server = new McpServer({
|
|
50
|
+
name: "indusk",
|
|
51
|
+
version,
|
|
52
|
+
});
|
|
53
|
+
console.error("[indusk] registering tools...");
|
|
54
|
+
registerPlanTools(server, projectRoot);
|
|
55
|
+
registerContextTools(server, projectRoot);
|
|
56
|
+
registerQualityTools(server, projectRoot);
|
|
57
|
+
registerDocumentTools(server, projectRoot);
|
|
58
|
+
registerSystemTools(server, projectRoot);
|
|
59
|
+
registerGraphTools(server, projectRoot);
|
|
60
|
+
registerLessonTools(server, projectRoot);
|
|
61
|
+
console.error("[indusk] tools registered");
|
|
62
|
+
const transport = new StdioServerTransport();
|
|
63
|
+
await server.connect(transport);
|
|
64
|
+
console.error("[indusk] connected via stdio");
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error(`[indusk] FATAL: ${err instanceof Error ? err.message : String(err)}`);
|
|
68
|
+
if (err instanceof Error && err.stack) {
|
|
69
|
+
console.error(err.stack);
|
|
70
|
+
}
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
50
73
|
}
|