@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2
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/CHANGELOG.md +49 -0
- package/dist/acp/agent.js +155 -167
- package/dist/acp/agent.js.map +1 -1
- package/dist/acp/event-mapper.js +193 -168
- package/dist/acp/event-mapper.js.map +1 -1
- package/dist/acp/index.js +60 -49
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/server.js +31 -30
- package/dist/acp/server.js.map +1 -1
- package/dist/acp.js +1 -4
- package/dist/agents/credential-resolver.js +40 -29
- package/dist/agents/credential-resolver.js.map +1 -1
- package/dist/agents/custom-provider-source.js +16 -9
- package/dist/agents/custom-provider-source.js.map +1 -1
- package/dist/agents/instructions.js +27 -36
- package/dist/agents/instructions.js.map +1 -1
- package/dist/agents/mastracode-gateway.js +355 -428
- package/dist/agents/mastracode-gateway.js.map +1 -1
- package/dist/agents/memory.js +87 -78
- package/dist/agents/memory.js.map +1 -1
- package/dist/agents/model.js +114 -119
- package/dist/agents/model.js.map +1 -1
- package/dist/agents/modes/build.js +12 -13
- package/dist/agents/modes/build.js.map +1 -1
- package/dist/agents/modes/explore.js +14 -13
- package/dist/agents/modes/explore.js.map +1 -1
- package/dist/agents/modes/plan.js +14 -15
- package/dist/agents/modes/plan.js.map +1 -1
- package/dist/agents/prompts/agent-instructions.js +78 -69
- package/dist/agents/prompts/agent-instructions.js.map +1 -1
- package/dist/agents/prompts/build.js +19 -16
- package/dist/agents/prompts/build.js.map +1 -1
- package/dist/agents/prompts/fast.js +8 -4
- package/dist/agents/prompts/fast.js.map +1 -1
- package/dist/agents/prompts/index.js +48 -47
- package/dist/agents/prompts/index.js.map +1 -1
- package/dist/agents/prompts/model.js +6 -5
- package/dist/agents/prompts/model.js.map +1 -1
- package/dist/agents/prompts/plan.js +20 -16
- package/dist/agents/prompts/plan.js.map +1 -1
- package/dist/agents/prompts/tool-guidance.js +77 -109
- package/dist/agents/prompts/tool-guidance.js.map +1 -1
- package/dist/agents/sandbox-filesystem.js +245 -259
- package/dist/agents/sandbox-filesystem.js.map +1 -1
- package/dist/agents/sandbox-reattach.js +9 -11
- package/dist/agents/sandbox-reattach.js.map +1 -1
- package/dist/agents/thread-caveman-state.js +92 -81
- package/dist/agents/thread-caveman-state.js.map +1 -1
- package/dist/agents/tool-availability.js +62 -80
- package/dist/agents/tool-availability.js.map +1 -1
- package/dist/agents/tools.js +99 -139
- package/dist/agents/tools.js.map +1 -1
- package/dist/agents/workspace.js +232 -225
- package/dist/agents/workspace.js.map +1 -1
- package/dist/analytics.js +139 -128
- package/dist/analytics.js.map +1 -1
- package/dist/auth/authorization-input.js +39 -25
- package/dist/auth/authorization-input.js.map +1 -1
- package/dist/auth/device-code.js +112 -80
- package/dist/auth/device-code.js.map +1 -1
- package/dist/auth/index.js +2 -9
- package/dist/auth/pkce.js +27 -16
- package/dist/auth/pkce.js.map +1 -1
- package/dist/auth/providers/anthropic.js +107 -93
- package/dist/auth/providers/anthropic.js.map +1 -1
- package/dist/auth/providers/github-copilot.js +304 -293
- package/dist/auth/providers/github-copilot.js.map +1 -1
- package/dist/auth/providers/openai-codex.js +442 -460
- package/dist/auth/providers/openai-codex.js.map +1 -1
- package/dist/auth/providers/xai.js +179 -145
- package/dist/auth/providers/xai.js.map +1 -1
- package/dist/auth/storage.js +182 -175
- package/dist/auth/storage.js.map +1 -1
- package/dist/auth/types.js +1 -1
- package/dist/clipboard/index.js +206 -172
- package/dist/clipboard/index.js.map +1 -1
- package/dist/constants.js +11 -16
- package/dist/constants.js.map +1 -1
- package/dist/error-classification.js +19 -11
- package/dist/error-classification.js.map +1 -1
- package/dist/evals/context-builder.js +145 -104
- package/dist/evals/context-builder.js.map +1 -1
- package/dist/evals/index.js +4 -7
- package/dist/evals/scorers/classify-command.js +62 -41
- package/dist/evals/scorers/classify-command.js.map +1 -1
- package/dist/evals/scorers/efficiency.js +239 -181
- package/dist/evals/scorers/efficiency.js.map +1 -1
- package/dist/evals/scorers/extract-tools.js +51 -47
- package/dist/evals/scorers/extract-tools.js.map +1 -1
- package/dist/evals/scorers/index.js +1 -5
- package/dist/evals/scorers/outcome.js +321 -212
- package/dist/evals/scorers/outcome.js.map +1 -1
- package/dist/goal-manager.js +266 -261
- package/dist/goal-manager.js.map +1 -1
- package/dist/goal-signal.js +14 -13
- package/dist/goal-signal.js.map +1 -1
- package/dist/headless/cli.js +153 -154
- package/dist/headless/cli.js.map +1 -1
- package/dist/headless/flags.js +180 -178
- package/dist/headless/flags.js.map +1 -1
- package/dist/headless/format.js +72 -71
- package/dist/headless/format.js.map +1 -1
- package/dist/headless/index.js +5 -31
- package/dist/headless/policy.js +35 -31
- package/dist/headless/policy.js.map +1 -1
- package/dist/headless/run-mc.js +332 -334
- package/dist/headless/run-mc.js.map +1 -1
- package/dist/headless/types.js +16 -7
- package/dist/headless/types.js.map +1 -1
- package/dist/hooks/config.js +56 -61
- package/dist/hooks/config.js.map +1 -1
- package/dist/hooks/executor.js +118 -116
- package/dist/hooks/executor.js.map +1 -1
- package/dist/hooks/index.js +4 -15
- package/dist/hooks/manager.js +221 -280
- package/dist/hooks/manager.js.map +1 -1
- package/dist/hooks/types.js +5 -4
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +632 -712
- package/dist/index.js.map +1 -1
- package/dist/ipc/ipc-reporter.js +19 -22
- package/dist/ipc/ipc-reporter.js.map +1 -1
- package/dist/lsp/client.js +248 -306
- package/dist/lsp/client.js.map +1 -1
- package/dist/lsp/index.js +1 -6
- package/dist/lsp/language.js +39 -43
- package/dist/lsp/language.js.map +1 -1
- package/dist/lsp/manager.js +78 -93
- package/dist/lsp/manager.js.map +1 -1
- package/dist/lsp/server.js +151 -120
- package/dist/lsp/server.js.map +1 -1
- package/dist/lsp/workspace.js +50 -47
- package/dist/lsp/workspace.js.map +1 -1
- package/dist/mcp/config.js +210 -199
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/index.js +2 -9
- package/dist/mcp/manager.js +482 -475
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/types.js +1 -1
- package/dist/onboarding/custom-packs.js +14 -17
- package/dist/onboarding/custom-packs.js.map +1 -1
- package/dist/onboarding/custom-providers.js +22 -20
- package/dist/onboarding/custom-providers.js.map +1 -1
- package/dist/onboarding/index.d.ts +1 -1
- package/dist/onboarding/index.d.ts.map +1 -1
- package/dist/onboarding/index.js +3 -21
- package/dist/onboarding/om-settings.d.ts +5 -0
- package/dist/onboarding/om-settings.d.ts.map +1 -1
- package/dist/onboarding/om-settings.js +41 -20
- package/dist/onboarding/om-settings.js.map +1 -1
- package/dist/onboarding/packs.d.ts +4 -6
- package/dist/onboarding/packs.d.ts.map +1 -1
- package/dist/onboarding/packs.js +154 -105
- package/dist/onboarding/packs.js.map +1 -1
- package/dist/onboarding/settings.js +575 -517
- package/dist/onboarding/settings.js.map +1 -1
- package/dist/permissions.js +112 -99
- package/dist/permissions.js.map +1 -1
- package/dist/plugin.js +21 -23
- package/dist/plugin.js.map +1 -1
- package/dist/plugins/dependencies.js +64 -87
- package/dist/plugins/dependencies.js.map +1 -1
- package/dist/plugins/install.js +159 -169
- package/dist/plugins/install.js.map +1 -1
- package/dist/plugins/loader.js +170 -185
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/manager.js +374 -380
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/manifest.js +38 -63
- package/dist/plugins/manifest.js.map +1 -1
- package/dist/plugins/package-link.js +48 -64
- package/dist/plugins/package-link.js.map +1 -1
- package/dist/plugins/paths.js +18 -19
- package/dist/plugins/paths.js.map +1 -1
- package/dist/plugins/registry.js +97 -81
- package/dist/plugins/registry.js.map +1 -1
- package/dist/plugins/scaffold.js +62 -98
- package/dist/plugins/scaffold.js.map +1 -1
- package/dist/plugins/types.js +1 -1
- package/dist/processors/plan-rejection-abort.js +45 -44
- package/dist/processors/plan-rejection-abort.js.map +1 -1
- package/dist/providers/amazon-bedrock-gateway.js +134 -125
- package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
- package/dist/providers/amazon-bedrock.js +68 -47
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/claude-max.js +153 -133
- package/dist/providers/claude-max.js.map +1 -1
- package/dist/providers/github-copilot.js +232 -230
- package/dist/providers/github-copilot.js.map +1 -1
- package/dist/providers/openai-codex.js +271 -260
- package/dist/providers/openai-codex.js.map +1 -1
- package/dist/providers/xai.js +57 -50
- package/dist/providers/xai.js.map +1 -1
- package/dist/schema.js +91 -89
- package/dist/schema.js.map +1 -1
- package/dist/theme-palette.js +18 -14
- package/dist/theme-palette.js.map +1 -1
- package/dist/tool-names.js +46 -37
- package/dist/tool-names.js.map +1 -1
- package/dist/tools/index.js +2 -8
- package/dist/tools/request-sandbox-access.js +71 -80
- package/dist/tools/request-sandbox-access.js.map +1 -1
- package/dist/tools/utils.js +26 -16
- package/dist/tools/utils.js.map +1 -1
- package/dist/tools/web-search.js +51 -55
- package/dist/tools/web-search.js.map +1 -1
- package/dist/utils/binaries.js +65 -61
- package/dist/utils/binaries.js.map +1 -1
- package/dist/utils/debug-log.js +51 -47
- package/dist/utils/debug-log.js.map +1 -1
- package/dist/utils/errors.js +157 -192
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/gateway-sync.js +49 -37
- package/dist/utils/gateway-sync.js.map +1 -1
- package/dist/utils/path-security.js +7 -6
- package/dist/utils/path-security.js.map +1 -1
- package/dist/utils/plan-diff.js +58 -39
- package/dist/utils/plan-diff.js.map +1 -1
- package/dist/utils/plans.js +92 -74
- package/dist/utils/plans.js.map +1 -1
- package/dist/utils/project.js +318 -256
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/signals-pubsub.js +117 -99
- package/dist/utils/signals-pubsub.js.map +1 -1
- package/dist/utils/slash-command-loader.js +118 -154
- package/dist/utils/slash-command-loader.js.map +1 -1
- package/dist/utils/slash-command-processor.js +92 -83
- package/dist/utils/slash-command-processor.js.map +1 -1
- package/dist/utils/stdin-pipe.js +87 -63
- package/dist/utils/stdin-pipe.js.map +1 -1
- package/dist/utils/storage-factory.js +104 -84
- package/dist/utils/storage-factory.js.map +1 -1
- package/dist/utils/storage-maintenance.js +249 -211
- package/dist/utils/storage-maintenance.js.map +1 -1
- package/dist/utils/thread-lock.js +96 -92
- package/dist/utils/thread-lock.js.map +1 -1
- package/dist/utils/token-estimator.js +12 -12
- package/dist/utils/token-estimator.js.map +1 -1
- package/dist/utils/update-check.d.ts +1 -1
- package/dist/utils/update-check.js +341 -259
- package/dist/utils/update-check.js.map +1 -1
- package/dist/voice/stt-registry.js +131 -113
- package/dist/voice/stt-registry.js.map +1 -1
- package/package.json +11 -11
- package/dist/acp.js.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/evals/index.js.map +0 -1
- package/dist/evals/scorers/index.js.map +0 -1
- package/dist/headless/index.js.map +0 -1
- package/dist/hooks/index.js.map +0 -1
- package/dist/lsp/index.js.map +0 -1
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/types.js.map +0 -1
- package/dist/onboarding/index.js.map +0 -1
- package/dist/plugins/types.js.map +0 -1
- package/dist/tools/index.js.map +0 -1
|
@@ -1,120 +1,161 @@
|
|
|
1
1
|
import { extractTrajectoryFromTrace } from "@mastra/core/evals";
|
|
2
|
+
//#region src/evals/context-builder.ts
|
|
3
|
+
/**
|
|
4
|
+
* Build an evaluation context from a AgentController session.
|
|
5
|
+
*
|
|
6
|
+
* This extracts messages from storage, builds trajectory from trace spans,
|
|
7
|
+
* and packages everything into the format scorers expect.
|
|
8
|
+
*/
|
|
2
9
|
async function buildEvalContext(options) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
trajectory,
|
|
24
|
-
requestContext,
|
|
25
|
-
threadId,
|
|
26
|
-
traceId
|
|
27
|
-
};
|
|
10
|
+
const { controller, session, lastNTurns } = options;
|
|
11
|
+
const threadId = options.threadId ?? session.thread.getId();
|
|
12
|
+
if (!threadId) throw new Error("No thread ID available. Start a session before building eval context.");
|
|
13
|
+
const storage = controller.getMastra()?.getStorage();
|
|
14
|
+
const { inputMessages, systemMessages, outputMessages } = categorizeMessages(await getRawMessages(storage, threadId, lastNTurns));
|
|
15
|
+
const { trajectory, traceId } = await extractSessionTrajectory(storage, threadId);
|
|
16
|
+
const requestContext = buildRequestContext(session, threadId);
|
|
17
|
+
return {
|
|
18
|
+
agentInput: {
|
|
19
|
+
inputMessages,
|
|
20
|
+
rememberedMessages: [],
|
|
21
|
+
systemMessages,
|
|
22
|
+
taggedSystemMessages: {}
|
|
23
|
+
},
|
|
24
|
+
agentOutput: outputMessages,
|
|
25
|
+
trajectory,
|
|
26
|
+
requestContext,
|
|
27
|
+
threadId,
|
|
28
|
+
traceId
|
|
29
|
+
};
|
|
28
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Fetch raw MastraDBMessage[] from memory storage for a thread.
|
|
33
|
+
*/
|
|
29
34
|
async function getRawMessages(storage, threadId, lastNTurns) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
messages = trimToLastNTurns(messages, lastNTurns);
|
|
40
|
-
}
|
|
41
|
-
return messages;
|
|
35
|
+
if (!storage) return [];
|
|
36
|
+
const memoryStore = await storage.getStore("memory");
|
|
37
|
+
if (!memoryStore) return [];
|
|
38
|
+
let messages = (await memoryStore.listMessages({
|
|
39
|
+
threadId,
|
|
40
|
+
perPage: false
|
|
41
|
+
})).messages;
|
|
42
|
+
if (lastNTurns !== void 0 && lastNTurns > 0) messages = trimToLastNTurns(messages, lastNTurns);
|
|
43
|
+
return messages;
|
|
42
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Trim messages to the last N user-assistant turn pairs.
|
|
47
|
+
*/
|
|
43
48
|
function trimToLastNTurns(messages, turns) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
return messages.slice(cutoffIndex);
|
|
49
|
+
let turnCount = 0;
|
|
50
|
+
let cutoffIndex = 0;
|
|
51
|
+
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") {
|
|
52
|
+
turnCount++;
|
|
53
|
+
if (turnCount === turns) {
|
|
54
|
+
cutoffIndex = i;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return messages.slice(cutoffIndex);
|
|
56
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Categorize messages into input (user), system, and output (assistant) groups.
|
|
62
|
+
*/
|
|
57
63
|
function categorizeMessages(messages) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
const inputMessages = [];
|
|
65
|
+
const systemMessages = [];
|
|
66
|
+
const outputMessages = [];
|
|
67
|
+
for (const msg of messages) switch (msg.role) {
|
|
68
|
+
case "user":
|
|
69
|
+
inputMessages.push(msg);
|
|
70
|
+
break;
|
|
71
|
+
case "system":
|
|
72
|
+
systemMessages.push({
|
|
73
|
+
role: "system",
|
|
74
|
+
content: extractTextContent(msg)
|
|
75
|
+
});
|
|
76
|
+
break;
|
|
77
|
+
case "assistant":
|
|
78
|
+
outputMessages.push(msg);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
inputMessages,
|
|
83
|
+
systemMessages,
|
|
84
|
+
outputMessages
|
|
85
|
+
};
|
|
78
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract plain text content from a MastraDBMessage.
|
|
89
|
+
*/
|
|
79
90
|
function extractTextContent(msg) {
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
if (!msg.content?.parts) return "";
|
|
92
|
+
return msg.content.parts.filter((p) => p.type === "text" && "text" in p).map((p) => p.text).join("\n");
|
|
82
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Extract trajectory from trace spans in observability storage.
|
|
96
|
+
* Looks up traces by threadId metadata.
|
|
97
|
+
*/
|
|
83
98
|
async function extractSessionTrajectory(storage, threadId) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
if (!storage) return {
|
|
100
|
+
trajectory: void 0,
|
|
101
|
+
traceId: void 0
|
|
102
|
+
};
|
|
103
|
+
try {
|
|
104
|
+
const observabilityStore = await storage.getStore("observability");
|
|
105
|
+
if (!observabilityStore) return {
|
|
106
|
+
trajectory: void 0,
|
|
107
|
+
traceId: void 0
|
|
108
|
+
};
|
|
109
|
+
const result = await observabilityStore.listTraces({
|
|
110
|
+
filters: { threadId },
|
|
111
|
+
pagination: {
|
|
112
|
+
page: 0,
|
|
113
|
+
perPage: 1
|
|
114
|
+
},
|
|
115
|
+
orderBy: {
|
|
116
|
+
field: "startedAt",
|
|
117
|
+
direction: "DESC"
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
if (!result?.spans?.length) return {
|
|
121
|
+
trajectory: void 0,
|
|
122
|
+
traceId: void 0
|
|
123
|
+
};
|
|
124
|
+
const traceId = result.spans[0].traceId;
|
|
125
|
+
const trace = await observabilityStore.getTrace({ traceId });
|
|
126
|
+
if (!trace?.spans?.length) return {
|
|
127
|
+
trajectory: void 0,
|
|
128
|
+
traceId
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
trajectory: extractTrajectoryFromTrace(trace.spans),
|
|
132
|
+
traceId
|
|
133
|
+
};
|
|
134
|
+
} catch {
|
|
135
|
+
return {
|
|
136
|
+
trajectory: void 0,
|
|
137
|
+
traceId: void 0
|
|
138
|
+
};
|
|
139
|
+
}
|
|
102
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Build request context from AgentController state for scorer evaluation.
|
|
143
|
+
*/
|
|
103
144
|
function buildRequestContext(session, threadId) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
145
|
+
const state = session.state.get();
|
|
146
|
+
return {
|
|
147
|
+
threadId,
|
|
148
|
+
mode: state.currentMode ?? state.mode,
|
|
149
|
+
modelId: session.model.get(),
|
|
150
|
+
projectPath: state.projectPath,
|
|
151
|
+
projectName: state.projectName,
|
|
152
|
+
gitBranch: state.gitBranch,
|
|
153
|
+
thinkingLevel: state.thinkingLevel,
|
|
154
|
+
yolo: state.yolo,
|
|
155
|
+
smartEditing: state.smartEditing
|
|
156
|
+
};
|
|
116
157
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
158
|
+
//#endregion
|
|
159
|
+
export { buildEvalContext };
|
|
160
|
+
|
|
120
161
|
//# sourceMappingURL=context-builder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/evals/context-builder.ts"],"sourcesContent":["/**\n * Eval Context Builder for MastraCode\n *\n * Converts AgentController session data into scorer-compatible format.\n * Supports both agent-type scorers (ScorerRunInputForAgent) and\n * trajectory scorers (Trajectory).\n */\n\nimport type { MastraDBMessage } from '@mastra/core/agent';\nimport type { AgentController, Session } from '@mastra/core/agent-controller';\nimport { extractTrajectoryFromTrace } from '@mastra/core/evals';\nimport type { ScorerRunInputForAgent, ScorerRunOutputForAgent, Trajectory } from '@mastra/core/evals';\nimport type { CoreMessage, CoreSystemMessage } from '@mastra/core/llm';\nimport type { MastraCompositeStore } from '@mastra/core/storage';\n\nexport type MastraCodeEvalContext = {\n /** Scorer-compatible agent input (messages, system prompt, etc.) */\n agentInput: ScorerRunInputForAgent;\n /** Scorer-compatible agent output (response messages) */\n agentOutput: ScorerRunOutputForAgent;\n /** Execution trajectory extracted from trace spans */\n trajectory: Trajectory | undefined;\n /** Request context with session metadata */\n requestContext: Record<string, unknown>;\n /** The thread ID this context was built from */\n threadId: string;\n /** The trace ID for observability linkage */\n traceId: string | undefined;\n};\n\nexport type BuildContextOptions = {\n /** AgentController instance to extract data from */\n controller: AgentController<any>;\n /** Session whose state/model/thread is being evaluated */\n session: Session<any>;\n /** Thread ID to build context for (defaults to current thread) */\n threadId?: string;\n /** Limit messages to the last N turns (user+assistant pairs). Undefined = all messages */\n lastNTurns?: number;\n};\n\n/**\n * Build an evaluation context from a AgentController session.\n *\n * This extracts messages from storage, builds trajectory from trace spans,\n * and packages everything into the format scorers expect.\n */\nexport async function buildEvalContext(options: BuildContextOptions): Promise<MastraCodeEvalContext> {\n const { controller, session, lastNTurns } = options;\n const threadId = options.threadId ?? session.thread.getId();\n\n if (!threadId) {\n throw new Error('No thread ID available. Start a session before building eval context.');\n }\n\n const mastra = controller.getMastra();\n const storage = mastra?.getStorage();\n\n // 1. Get raw MastraDB messages from memory storage\n const rawMessages = await getRawMessages(storage, threadId, lastNTurns);\n\n // 2. Split messages into input/output categories\n const { inputMessages, systemMessages, outputMessages } = categorizeMessages(rawMessages);\n\n // 3. Extract trajectory from observability traces\n const { trajectory, traceId } = await extractSessionTrajectory(storage, threadId);\n\n // 4. Build request context from AgentController state\n const requestContext = buildRequestContext(session, threadId);\n\n return {\n agentInput: {\n inputMessages,\n rememberedMessages: [], // AgentController doesn't separate these; memory recall is transparent\n systemMessages,\n taggedSystemMessages: {},\n },\n agentOutput: outputMessages,\n trajectory,\n requestContext,\n threadId,\n traceId,\n };\n}\n\n/**\n * Fetch raw MastraDBMessage[] from memory storage for a thread.\n */\nasync function getRawMessages(\n storage: MastraCompositeStore | undefined,\n threadId: string,\n lastNTurns?: number,\n): Promise<MastraDBMessage[]> {\n if (!storage) return [];\n\n const memoryStore = await storage.getStore('memory');\n if (!memoryStore) return [];\n\n const result = await memoryStore.listMessages({\n threadId,\n perPage: false,\n });\n\n let messages = result.messages;\n\n if (lastNTurns !== undefined && lastNTurns > 0) {\n messages = trimToLastNTurns(messages, lastNTurns);\n }\n\n return messages;\n}\n\n/**\n * Trim messages to the last N user-assistant turn pairs.\n */\nfunction trimToLastNTurns(messages: MastraDBMessage[], turns: number): MastraDBMessage[] {\n // Walk backward, counting user messages as turn boundaries.\n // When we find the Nth user message, slice from there to include\n // that turn and everything after it.\n let turnCount = 0;\n let cutoffIndex = 0;\n\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]!.role === 'user') {\n turnCount++;\n if (turnCount === turns) {\n cutoffIndex = i;\n break;\n }\n }\n }\n\n return messages.slice(cutoffIndex);\n}\n\n/**\n * Categorize messages into input (user), system, and output (assistant) groups.\n */\nfunction categorizeMessages(messages: MastraDBMessage[]): {\n inputMessages: MastraDBMessage[];\n systemMessages: CoreMessage[];\n outputMessages: MastraDBMessage[];\n} {\n const inputMessages: MastraDBMessage[] = [];\n const systemMessages: CoreSystemMessage[] = [];\n const outputMessages: MastraDBMessage[] = [];\n\n for (const msg of messages) {\n switch (msg.role) {\n case 'user':\n inputMessages.push(msg);\n break;\n case 'system':\n systemMessages.push({\n role: 'system',\n content: extractTextContent(msg),\n });\n break;\n case 'assistant':\n outputMessages.push(msg);\n break;\n }\n }\n\n return { inputMessages, systemMessages, outputMessages };\n}\n\n/**\n * Extract plain text content from a MastraDBMessage.\n */\nfunction extractTextContent(msg: MastraDBMessage): string {\n if (!msg.content?.parts) return '';\n\n return msg.content.parts\n .filter((p): p is { type: 'text'; text: string } => p.type === 'text' && 'text' in p)\n .map(p => p.text)\n .join('\\n');\n}\n\n/**\n * Extract trajectory from trace spans in observability storage.\n * Looks up traces by threadId metadata.\n */\nasync function extractSessionTrajectory(\n storage: MastraCompositeStore | undefined,\n threadId: string,\n): Promise<{ trajectory: Trajectory | undefined; traceId: string | undefined }> {\n if (!storage) return { trajectory: undefined, traceId: undefined };\n\n try {\n const observabilityStore = await storage.getStore('observability');\n if (!observabilityStore) return { trajectory: undefined, traceId: undefined };\n\n // Find traces associated with this thread\n const result = await observabilityStore.listTraces({\n filters: { threadId },\n pagination: { page: 0, perPage: 1 },\n orderBy: { field: 'startedAt', direction: 'DESC' },\n });\n\n if (!result?.spans?.length) return { trajectory: undefined, traceId: undefined };\n\n const traceId = result.spans[0]!.traceId;\n const trace = await observabilityStore.getTrace({ traceId });\n\n if (!trace?.spans?.length) return { trajectory: undefined, traceId };\n\n const trajectory = extractTrajectoryFromTrace(trace.spans);\n return { trajectory, traceId };\n } catch {\n // Trace extraction is best-effort\n return { trajectory: undefined, traceId: undefined };\n }\n}\n\n/**\n * Build request context from AgentController state for scorer evaluation.\n */\nfunction buildRequestContext(session: Session<any>, threadId: string): Record<string, unknown> {\n const state = session.state.get() as Record<string, unknown>;\n\n return {\n threadId,\n mode: state.currentMode ?? state.mode,\n modelId: session.model.get(),\n projectPath: state.projectPath,\n projectName: state.projectName,\n gitBranch: state.gitBranch,\n thinkingLevel: state.thinkingLevel,\n yolo: state.yolo,\n smartEditing: state.smartEditing,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"context-builder.js","names":[],"sources":["../../src/evals/context-builder.ts"],"sourcesContent":["/**\n * Eval Context Builder for MastraCode\n *\n * Converts AgentController session data into scorer-compatible format.\n * Supports both agent-type scorers (ScorerRunInputForAgent) and\n * trajectory scorers (Trajectory).\n */\n\nimport type { MastraDBMessage } from '@mastra/core/agent';\nimport type { AgentController, Session } from '@mastra/core/agent-controller';\nimport { extractTrajectoryFromTrace } from '@mastra/core/evals';\nimport type { ScorerRunInputForAgent, ScorerRunOutputForAgent, Trajectory } from '@mastra/core/evals';\nimport type { CoreMessage, CoreSystemMessage } from '@mastra/core/llm';\nimport type { MastraCompositeStore } from '@mastra/core/storage';\n\nexport type MastraCodeEvalContext = {\n /** Scorer-compatible agent input (messages, system prompt, etc.) */\n agentInput: ScorerRunInputForAgent;\n /** Scorer-compatible agent output (response messages) */\n agentOutput: ScorerRunOutputForAgent;\n /** Execution trajectory extracted from trace spans */\n trajectory: Trajectory | undefined;\n /** Request context with session metadata */\n requestContext: Record<string, unknown>;\n /** The thread ID this context was built from */\n threadId: string;\n /** The trace ID for observability linkage */\n traceId: string | undefined;\n};\n\nexport type BuildContextOptions = {\n /** AgentController instance to extract data from */\n controller: AgentController<any>;\n /** Session whose state/model/thread is being evaluated */\n session: Session<any>;\n /** Thread ID to build context for (defaults to current thread) */\n threadId?: string;\n /** Limit messages to the last N turns (user+assistant pairs). Undefined = all messages */\n lastNTurns?: number;\n};\n\n/**\n * Build an evaluation context from a AgentController session.\n *\n * This extracts messages from storage, builds trajectory from trace spans,\n * and packages everything into the format scorers expect.\n */\nexport async function buildEvalContext(options: BuildContextOptions): Promise<MastraCodeEvalContext> {\n const { controller, session, lastNTurns } = options;\n const threadId = options.threadId ?? session.thread.getId();\n\n if (!threadId) {\n throw new Error('No thread ID available. Start a session before building eval context.');\n }\n\n const mastra = controller.getMastra();\n const storage = mastra?.getStorage();\n\n // 1. Get raw MastraDB messages from memory storage\n const rawMessages = await getRawMessages(storage, threadId, lastNTurns);\n\n // 2. Split messages into input/output categories\n const { inputMessages, systemMessages, outputMessages } = categorizeMessages(rawMessages);\n\n // 3. Extract trajectory from observability traces\n const { trajectory, traceId } = await extractSessionTrajectory(storage, threadId);\n\n // 4. Build request context from AgentController state\n const requestContext = buildRequestContext(session, threadId);\n\n return {\n agentInput: {\n inputMessages,\n rememberedMessages: [], // AgentController doesn't separate these; memory recall is transparent\n systemMessages,\n taggedSystemMessages: {},\n },\n agentOutput: outputMessages,\n trajectory,\n requestContext,\n threadId,\n traceId,\n };\n}\n\n/**\n * Fetch raw MastraDBMessage[] from memory storage for a thread.\n */\nasync function getRawMessages(\n storage: MastraCompositeStore | undefined,\n threadId: string,\n lastNTurns?: number,\n): Promise<MastraDBMessage[]> {\n if (!storage) return [];\n\n const memoryStore = await storage.getStore('memory');\n if (!memoryStore) return [];\n\n const result = await memoryStore.listMessages({\n threadId,\n perPage: false,\n });\n\n let messages = result.messages;\n\n if (lastNTurns !== undefined && lastNTurns > 0) {\n messages = trimToLastNTurns(messages, lastNTurns);\n }\n\n return messages;\n}\n\n/**\n * Trim messages to the last N user-assistant turn pairs.\n */\nfunction trimToLastNTurns(messages: MastraDBMessage[], turns: number): MastraDBMessage[] {\n // Walk backward, counting user messages as turn boundaries.\n // When we find the Nth user message, slice from there to include\n // that turn and everything after it.\n let turnCount = 0;\n let cutoffIndex = 0;\n\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]!.role === 'user') {\n turnCount++;\n if (turnCount === turns) {\n cutoffIndex = i;\n break;\n }\n }\n }\n\n return messages.slice(cutoffIndex);\n}\n\n/**\n * Categorize messages into input (user), system, and output (assistant) groups.\n */\nfunction categorizeMessages(messages: MastraDBMessage[]): {\n inputMessages: MastraDBMessage[];\n systemMessages: CoreMessage[];\n outputMessages: MastraDBMessage[];\n} {\n const inputMessages: MastraDBMessage[] = [];\n const systemMessages: CoreSystemMessage[] = [];\n const outputMessages: MastraDBMessage[] = [];\n\n for (const msg of messages) {\n switch (msg.role) {\n case 'user':\n inputMessages.push(msg);\n break;\n case 'system':\n systemMessages.push({\n role: 'system',\n content: extractTextContent(msg),\n });\n break;\n case 'assistant':\n outputMessages.push(msg);\n break;\n }\n }\n\n return { inputMessages, systemMessages, outputMessages };\n}\n\n/**\n * Extract plain text content from a MastraDBMessage.\n */\nfunction extractTextContent(msg: MastraDBMessage): string {\n if (!msg.content?.parts) return '';\n\n return msg.content.parts\n .filter((p): p is { type: 'text'; text: string } => p.type === 'text' && 'text' in p)\n .map(p => p.text)\n .join('\\n');\n}\n\n/**\n * Extract trajectory from trace spans in observability storage.\n * Looks up traces by threadId metadata.\n */\nasync function extractSessionTrajectory(\n storage: MastraCompositeStore | undefined,\n threadId: string,\n): Promise<{ trajectory: Trajectory | undefined; traceId: string | undefined }> {\n if (!storage) return { trajectory: undefined, traceId: undefined };\n\n try {\n const observabilityStore = await storage.getStore('observability');\n if (!observabilityStore) return { trajectory: undefined, traceId: undefined };\n\n // Find traces associated with this thread\n const result = await observabilityStore.listTraces({\n filters: { threadId },\n pagination: { page: 0, perPage: 1 },\n orderBy: { field: 'startedAt', direction: 'DESC' },\n });\n\n if (!result?.spans?.length) return { trajectory: undefined, traceId: undefined };\n\n const traceId = result.spans[0]!.traceId;\n const trace = await observabilityStore.getTrace({ traceId });\n\n if (!trace?.spans?.length) return { trajectory: undefined, traceId };\n\n const trajectory = extractTrajectoryFromTrace(trace.spans);\n return { trajectory, traceId };\n } catch {\n // Trace extraction is best-effort\n return { trajectory: undefined, traceId: undefined };\n }\n}\n\n/**\n * Build request context from AgentController state for scorer evaluation.\n */\nfunction buildRequestContext(session: Session<any>, threadId: string): Record<string, unknown> {\n const state = session.state.get() as Record<string, unknown>;\n\n return {\n threadId,\n mode: state.currentMode ?? state.mode,\n modelId: session.model.get(),\n projectPath: state.projectPath,\n projectName: state.projectName,\n gitBranch: state.gitBranch,\n thinkingLevel: state.thinkingLevel,\n yolo: state.yolo,\n smartEditing: state.smartEditing,\n };\n}\n"],"mappings":"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"}
|
package/dist/evals/index.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
+
import { createOutcomeScorer } from "./scorers/outcome.js";
|
|
2
|
+
import { createEfficiencyScorer } from "./scorers/efficiency.js";
|
|
3
|
+
import "./scorers/index.js";
|
|
1
4
|
import { buildEvalContext } from "./context-builder.js";
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
buildEvalContext,
|
|
5
|
-
createEfficiencyScorer,
|
|
6
|
-
createOutcomeScorer
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
|
5
|
+
export { buildEvalContext, createEfficiencyScorer, createOutcomeScorer };
|
|
@@ -1,52 +1,73 @@
|
|
|
1
|
+
//#region src/evals/scorers/classify-command.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared command classification utilities for scoring.
|
|
4
|
+
*
|
|
5
|
+
* Used by both live scorers (outcome.ts) and offline scorers (outcome-match.ts)
|
|
6
|
+
* to consistently identify build, test, and other command types.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Check if a command string is a build/typecheck command.
|
|
10
|
+
* Handles compound commands (e.g. `pnpm build && pnpm test`) by checking each segment.
|
|
11
|
+
*/
|
|
1
12
|
function isBuildCommand(command) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
});
|
|
13
|
+
return command.split(/\s*(?:&&|\|\||;)\s*/).some((seg) => {
|
|
14
|
+
const trimmed = seg.trim();
|
|
15
|
+
if (!/\b(tsc|typecheck|type-check|build)\b/.test(trimmed)) return false;
|
|
16
|
+
const primaryVerb = trimmed.replace(/^(?:pnpm|npm|yarn|npx|bunx?|turbo)\s+(?:run\s+)?/, "").split(/\s/)[0] ?? "";
|
|
17
|
+
return !/^(test|vitest|jest|mocha|pytest)$/.test(primaryVerb);
|
|
18
|
+
});
|
|
9
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if a command string is a test command.
|
|
22
|
+
*/
|
|
10
23
|
function isTestCommand(command) {
|
|
11
|
-
|
|
24
|
+
return /\b(test|vitest|jest|mocha|pytest|spec)\b/.test(command);
|
|
12
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Extract exit code from an `execute_command` result.
|
|
28
|
+
* Only trusts explicit exitCode/code fields — no heuristic fallbacks.
|
|
29
|
+
*/
|
|
13
30
|
function getExitCode(result) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
if (result == null) return null;
|
|
32
|
+
if (typeof result === "string") {
|
|
33
|
+
const exitMatch = result.match(/exit(?:ed)?\s+(?:with\s+)?(?:code\s+)?(\d+)/i);
|
|
34
|
+
if (exitMatch) return parseInt(exitMatch[1], 10);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (typeof result === "object") {
|
|
38
|
+
const obj = result;
|
|
39
|
+
if ("exitCode" in obj && typeof obj.exitCode === "number") return obj.exitCode;
|
|
40
|
+
if ("code" in obj && typeof obj.code === "number") return obj.code;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
26
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Determine if a tool call result indicates success (exit code 0, no explicit error).
|
|
46
|
+
* Works with both structured result objects and string results.
|
|
47
|
+
*/
|
|
27
48
|
function isSuccessResult(result, error) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
if (error) return false;
|
|
50
|
+
if (!result) return false;
|
|
51
|
+
if (typeof result === "object") {
|
|
52
|
+
const obj = result;
|
|
53
|
+
const exitCode = obj.exitCode ?? obj.code;
|
|
54
|
+
if (typeof exitCode === "number") return exitCode === 0;
|
|
55
|
+
}
|
|
56
|
+
if (typeof result === "string") {
|
|
57
|
+
const exitMatch = result.match(/exit(?:ed)?\s+(?:with\s+)?(?:code\s+)?(\d+)/i);
|
|
58
|
+
if (exitMatch) return exitMatch[1] === "0";
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
40
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Match a file path from tool output against an expected path.
|
|
64
|
+
* Supports exact match and suffix match (e.g. "src/foo.ts" matches "/abs/path/src/foo.ts").
|
|
65
|
+
*/
|
|
41
66
|
function matchFilePath(actual, expected) {
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
if (actual === expected) return true;
|
|
68
|
+
return actual.endsWith(`/${expected}`) || expected.endsWith(`/${actual}`);
|
|
44
69
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
isSuccessResult,
|
|
49
|
-
isTestCommand,
|
|
50
|
-
matchFilePath
|
|
51
|
-
};
|
|
70
|
+
//#endregion
|
|
71
|
+
export { getExitCode, isBuildCommand, isSuccessResult, isTestCommand, matchFilePath };
|
|
72
|
+
|
|
52
73
|
//# sourceMappingURL=classify-command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/evals/scorers/classify-command.ts"],"sourcesContent":["/**\n * Shared command classification utilities for scoring.\n *\n * Used by both live scorers (outcome.ts) and offline scorers (outcome-match.ts)\n * to consistently identify build, test, and other command types.\n */\n\n/**\n * Check if a command string is a build/typecheck command.\n * Handles compound commands (e.g. `pnpm build && pnpm test`) by checking each segment.\n */\nexport function isBuildCommand(command: string): boolean {\n const segments = command.split(/\\s*(?:&&|\\|\\||;)\\s*/);\n return segments.some(seg => {\n const trimmed = seg.trim();\n if (!/\\b(tsc|typecheck|type-check|build)\\b/.test(trimmed)) return false;\n // Don't reject if \"test\" only appears as a substring (e.g. \"build-test-output\").\n // Only reject if a test runner is the primary verb of this segment.\n const primaryVerb = trimmed.replace(/^(?:pnpm|npm|yarn|npx|bunx?|turbo)\\s+(?:run\\s+)?/, '').split(/\\s/)[0] ?? '';\n return !/^(test|vitest|jest|mocha|pytest)$/.test(primaryVerb);\n });\n}\n\n/**\n * Check if a command string is a test command.\n */\nexport function isTestCommand(command: string): boolean {\n return /\\b(test|vitest|jest|mocha|pytest|spec)\\b/.test(command);\n}\n\n/**\n * Extract exit code from an `execute_command` result.\n * Only trusts explicit exitCode/code fields — no heuristic fallbacks.\n */\nexport function getExitCode(result: unknown): number | null {\n if (result == null) return null;\n\n if (typeof result === 'string') {\n const exitMatch = result.match(/exit(?:ed)?\\s+(?:with\\s+)?(?:code\\s+)?(\\d+)/i);\n if (exitMatch) return parseInt(exitMatch[1]!, 10);\n return null;\n }\n\n if (typeof result === 'object') {\n const obj = result as Record<string, unknown>;\n if ('exitCode' in obj && typeof obj.exitCode === 'number') return obj.exitCode;\n if ('code' in obj && typeof obj.code === 'number') return obj.code;\n }\n\n return null;\n}\n\n/**\n * Determine if a tool call result indicates success (exit code 0, no explicit error).\n * Works with both structured result objects and string results.\n */\nexport function isSuccessResult(result: unknown, error?: unknown): boolean {\n if (error) return false;\n if (!result) return false;\n\n if (typeof result === 'object') {\n const obj = result as Record<string, unknown>;\n const exitCode = (obj.exitCode as number | undefined) ?? (obj.code as number | undefined);\n if (typeof exitCode === 'number') return exitCode === 0;\n }\n\n if (typeof result === 'string') {\n const exitMatch = result.match(/exit(?:ed)?\\s+(?:with\\s+)?(?:code\\s+)?(\\d+)/i);\n if (exitMatch) return exitMatch[1] === '0';\n }\n\n // No explicit exit code — can't determine\n return false;\n}\n\n/**\n * Match a file path from tool output against an expected path.\n * Supports exact match and suffix match (e.g. \"src/foo.ts\" matches \"/abs/path/src/foo.ts\").\n */\nexport function matchFilePath(actual: string, expected: string): boolean {\n if (actual === expected) return true;\n return actual.endsWith(`/${expected}`) || expected.endsWith(`/${actual}`);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"classify-command.js","names":[],"sources":["../../../src/evals/scorers/classify-command.ts"],"sourcesContent":["/**\n * Shared command classification utilities for scoring.\n *\n * Used by both live scorers (outcome.ts) and offline scorers (outcome-match.ts)\n * to consistently identify build, test, and other command types.\n */\n\n/**\n * Check if a command string is a build/typecheck command.\n * Handles compound commands (e.g. `pnpm build && pnpm test`) by checking each segment.\n */\nexport function isBuildCommand(command: string): boolean {\n const segments = command.split(/\\s*(?:&&|\\|\\||;)\\s*/);\n return segments.some(seg => {\n const trimmed = seg.trim();\n if (!/\\b(tsc|typecheck|type-check|build)\\b/.test(trimmed)) return false;\n // Don't reject if \"test\" only appears as a substring (e.g. \"build-test-output\").\n // Only reject if a test runner is the primary verb of this segment.\n const primaryVerb = trimmed.replace(/^(?:pnpm|npm|yarn|npx|bunx?|turbo)\\s+(?:run\\s+)?/, '').split(/\\s/)[0] ?? '';\n return !/^(test|vitest|jest|mocha|pytest)$/.test(primaryVerb);\n });\n}\n\n/**\n * Check if a command string is a test command.\n */\nexport function isTestCommand(command: string): boolean {\n return /\\b(test|vitest|jest|mocha|pytest|spec)\\b/.test(command);\n}\n\n/**\n * Extract exit code from an `execute_command` result.\n * Only trusts explicit exitCode/code fields — no heuristic fallbacks.\n */\nexport function getExitCode(result: unknown): number | null {\n if (result == null) return null;\n\n if (typeof result === 'string') {\n const exitMatch = result.match(/exit(?:ed)?\\s+(?:with\\s+)?(?:code\\s+)?(\\d+)/i);\n if (exitMatch) return parseInt(exitMatch[1]!, 10);\n return null;\n }\n\n if (typeof result === 'object') {\n const obj = result as Record<string, unknown>;\n if ('exitCode' in obj && typeof obj.exitCode === 'number') return obj.exitCode;\n if ('code' in obj && typeof obj.code === 'number') return obj.code;\n }\n\n return null;\n}\n\n/**\n * Determine if a tool call result indicates success (exit code 0, no explicit error).\n * Works with both structured result objects and string results.\n */\nexport function isSuccessResult(result: unknown, error?: unknown): boolean {\n if (error) return false;\n if (!result) return false;\n\n if (typeof result === 'object') {\n const obj = result as Record<string, unknown>;\n const exitCode = (obj.exitCode as number | undefined) ?? (obj.code as number | undefined);\n if (typeof exitCode === 'number') return exitCode === 0;\n }\n\n if (typeof result === 'string') {\n const exitMatch = result.match(/exit(?:ed)?\\s+(?:with\\s+)?(?:code\\s+)?(\\d+)/i);\n if (exitMatch) return exitMatch[1] === '0';\n }\n\n // No explicit exit code — can't determine\n return false;\n}\n\n/**\n * Match a file path from tool output against an expected path.\n * Supports exact match and suffix match (e.g. \"src/foo.ts\" matches \"/abs/path/src/foo.ts\").\n */\nexport function matchFilePath(actual: string, expected: string): boolean {\n if (actual === expected) return true;\n return actual.endsWith(`/${expected}`) || expected.endsWith(`/${actual}`);\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,eAAe,SAA0B;CAEvD,OADiB,QAAQ,MAAM,qBACjB,CAAC,CAAC,MAAK,QAAO;EAC1B,MAAM,UAAU,IAAI,KAAK;EACzB,IAAI,CAAC,uCAAuC,KAAK,OAAO,GAAG,OAAO;EAGlE,MAAM,cAAc,QAAQ,QAAQ,oDAAoD,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM;EAC9G,OAAO,CAAC,oCAAoC,KAAK,WAAW;CAC9D,CAAC;AACH;;;;AAKA,SAAgB,cAAc,SAA0B;CACtD,OAAO,2CAA2C,KAAK,OAAO;AAChE;;;;;AAMA,SAAgB,YAAY,QAAgC;CAC1D,IAAI,UAAU,MAAM,OAAO;CAE3B,IAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,YAAY,OAAO,MAAM,8CAA8C;EAC7E,IAAI,WAAW,OAAO,SAAS,UAAU,IAAK,EAAE;EAChD,OAAO;CACT;CAEA,IAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,MAAM;EACZ,IAAI,cAAc,OAAO,OAAO,IAAI,aAAa,UAAU,OAAO,IAAI;EACtE,IAAI,UAAU,OAAO,OAAO,IAAI,SAAS,UAAU,OAAO,IAAI;CAChE;CAEA,OAAO;AACT;;;;;AAMA,SAAgB,gBAAgB,QAAiB,OAA0B;CACzE,IAAI,OAAO,OAAO;CAClB,IAAI,CAAC,QAAQ,OAAO;CAEpB,IAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,MAAM;EACZ,MAAM,WAAY,IAAI,YAAoC,IAAI;EAC9D,IAAI,OAAO,aAAa,UAAU,OAAO,aAAa;CACxD;CAEA,IAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,YAAY,OAAO,MAAM,8CAA8C;EAC7E,IAAI,WAAW,OAAO,UAAU,OAAO;CACzC;CAGA,OAAO;AACT;;;;;AAMA,SAAgB,cAAc,QAAgB,UAA2B;CACvE,IAAI,WAAW,UAAU,OAAO;CAChC,OAAO,OAAO,SAAS,IAAI,UAAU,KAAK,SAAS,SAAS,IAAI,QAAQ;AAC1E"}
|