@wix/pathgrade 0.29.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.
- package/bin/pathgrade.js +2 -0
- package/dist/affected/anchor.d.ts +18 -0
- package/dist/affected/anchor.js +42 -0
- package/dist/affected/config.d.ts +25 -0
- package/dist/affected/config.js +98 -0
- package/dist/affected/format.d.ts +45 -0
- package/dist/affected/format.js +87 -0
- package/dist/affected/git.d.ts +33 -0
- package/dist/affected/git.js +68 -0
- package/dist/affected/glob.d.ts +17 -0
- package/dist/affected/glob.js +25 -0
- package/dist/affected/meta.d.ts +26 -0
- package/dist/affected/meta.js +158 -0
- package/dist/affected/select.d.ts +30 -0
- package/dist/affected/select.js +101 -0
- package/dist/affected/sidecar.d.ts +32 -0
- package/dist/affected/sidecar.js +86 -0
- package/dist/affected/types.d.ts +43 -0
- package/dist/affected/types.js +7 -0
- package/dist/agents/claude/ask-user-answer-store.d.ts +28 -0
- package/dist/agents/claude/ask-user-answer-store.js +29 -0
- package/dist/agents/claude/ask-user-bridge.d.ts +56 -0
- package/dist/agents/claude/ask-user-bridge.js +162 -0
- package/dist/agents/claude/sdk-message-projector.d.ts +43 -0
- package/dist/agents/claude/sdk-message-projector.js +208 -0
- package/dist/agents/claude/sdk-options.d.ts +52 -0
- package/dist/agents/claude/sdk-options.js +79 -0
- package/dist/agents/claude.d.ts +56 -0
- package/dist/agents/claude.js +143 -0
- package/dist/agents/codex-app-server/agent.d.ts +35 -0
- package/dist/agents/codex-app-server/agent.js +388 -0
- package/dist/agents/codex-app-server/fixtures/app-server-client.d.ts +19 -0
- package/dist/agents/codex-app-server/fixtures/app-server-client.js +104 -0
- package/dist/agents/codex-app-server/fixtures/run-gate.d.ts +25 -0
- package/dist/agents/codex-app-server/fixtures/run-gate.js +48 -0
- package/dist/agents/codex-app-server/protocol/ClientRequest.d.ts +27 -0
- package/dist/agents/codex-app-server/protocol/ClientRequest.js +7 -0
- package/dist/agents/codex-app-server/protocol/DynamicToolCallParams.d.ts +9 -0
- package/dist/agents/codex-app-server/protocol/DynamicToolCallParams.js +4 -0
- package/dist/agents/codex-app-server/protocol/GrantedPermissionProfile.d.ts +6 -0
- package/dist/agents/codex-app-server/protocol/GrantedPermissionProfile.js +7 -0
- package/dist/agents/codex-app-server/protocol/McpElicitationRequestParams.d.ts +23 -0
- package/dist/agents/codex-app-server/protocol/McpElicitationRequestParams.js +8 -0
- package/dist/agents/codex-app-server/protocol/Op.d.ts +11 -0
- package/dist/agents/codex-app-server/protocol/Op.js +5 -0
- package/dist/agents/codex-app-server/protocol/PermissionsRequestApprovalParams.d.ts +10 -0
- package/dist/agents/codex-app-server/protocol/PermissionsRequestApprovalParams.js +6 -0
- package/dist/agents/codex-app-server/protocol/PermissionsRequestApprovalResponse.d.ts +15 -0
- package/dist/agents/codex-app-server/protocol/PermissionsRequestApprovalResponse.js +4 -0
- package/dist/agents/codex-app-server/protocol/SandboxMode.d.ts +1 -0
- package/dist/agents/codex-app-server/protocol/SandboxMode.js +4 -0
- package/dist/agents/codex-app-server/protocol/ServerRequest.d.ts +42 -0
- package/dist/agents/codex-app-server/protocol/ServerRequest.js +7 -0
- package/dist/agents/codex-app-server/protocol/ThreadStartParams.d.ts +45 -0
- package/dist/agents/codex-app-server/protocol/ThreadStartParams.js +10 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputAnswer.d.ts +6 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputAnswer.js +4 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputOption.d.ts +7 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputOption.js +4 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputParams.d.ts +10 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputParams.js +4 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputQuestion.d.ts +12 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputQuestion.js +4 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputResponse.d.ts +9 -0
- package/dist/agents/codex-app-server/protocol/ToolRequestUserInputResponse.js +4 -0
- package/dist/agents/codex-app-server/protocol/TurnCompletedNotification.d.ts +5 -0
- package/dist/agents/codex-app-server/protocol/TurnCompletedNotification.js +4 -0
- package/dist/agents/codex-app-server/protocol/index.d.ts +16 -0
- package/dist/agents/codex-app-server/protocol/index.js +11 -0
- package/dist/agents/codex-app-server/transport.d.ts +84 -0
- package/dist/agents/codex-app-server/transport.js +246 -0
- package/dist/agents/codex-app-server/wire-translators.d.ts +19 -0
- package/dist/agents/codex-app-server/wire-translators.js +52 -0
- package/dist/agents/codex.d.ts +7 -0
- package/dist/agents/codex.js +164 -0
- package/dist/agents/cursor.d.ts +39 -0
- package/dist/agents/cursor.js +233 -0
- package/dist/agents/registry.d.ts +17 -0
- package/dist/agents/registry.js +27 -0
- package/dist/agents/transcript-agent.d.ts +14 -0
- package/dist/agents/transcript-agent.js +59 -0
- package/dist/analytics/engine.d.ts +18 -0
- package/dist/analytics/engine.js +66 -0
- package/dist/commands/affected.d.ts +31 -0
- package/dist/commands/affected.js +150 -0
- package/dist/commands/analyze.d.ts +21 -0
- package/dist/commands/analyze.js +167 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +242 -0
- package/dist/commands/preview-reactions.d.ts +10 -0
- package/dist/commands/preview-reactions.js +88 -0
- package/dist/commands/preview.d.ts +5 -0
- package/dist/commands/preview.js +17 -0
- package/dist/commands/report.d.ts +39 -0
- package/dist/commands/report.js +108 -0
- package/dist/commands/run-args.d.ts +22 -0
- package/dist/commands/run-args.js +69 -0
- package/dist/commands/run-changed.d.ts +26 -0
- package/dist/commands/run-changed.js +138 -0
- package/dist/commands/validate.d.ts +13 -0
- package/dist/commands/validate.js +233 -0
- package/dist/core/mcp-mock.d.ts +3 -0
- package/dist/core/mcp-mock.js +23 -0
- package/dist/core/mcp-mock.types.d.ts +15 -0
- package/dist/core/mcp-mock.types.js +1 -0
- package/dist/core/skills.d.ts +15 -0
- package/dist/core/skills.js +76 -0
- package/dist/evals/discovery.d.ts +7 -0
- package/dist/evals/discovery.js +69 -0
- package/dist/mcp-mock-server.d.ts +1 -0
- package/dist/mcp-mock-server.js +116 -0
- package/dist/pathgrade.d.ts +10 -0
- package/dist/pathgrade.js +243 -0
- package/dist/plugin/index.d.ts +9 -0
- package/dist/plugin/index.js +81 -0
- package/dist/plugin/lifecycle.d.ts +45 -0
- package/dist/plugin/lifecycle.js +146 -0
- package/dist/plugin/reporter.d.ts +36 -0
- package/dist/plugin/reporter.js +275 -0
- package/dist/plugin/setup.d.ts +1 -0
- package/dist/plugin/setup.js +3 -0
- package/dist/providers/copy-filter.d.ts +18 -0
- package/dist/providers/copy-filter.js +66 -0
- package/dist/providers/credentials.d.ts +36 -0
- package/dist/providers/credentials.js +202 -0
- package/dist/providers/mcp-config.d.ts +34 -0
- package/dist/providers/mcp-config.js +55 -0
- package/dist/providers/sandbox-exec.d.ts +8 -0
- package/dist/providers/sandbox-exec.js +82 -0
- package/dist/providers/sandbox.d.ts +22 -0
- package/dist/providers/sandbox.js +158 -0
- package/dist/providers/sandboxed-claude-spawn.d.ts +24 -0
- package/dist/providers/sandboxed-claude-spawn.js +57 -0
- package/dist/providers/workspace.d.ts +15 -0
- package/dist/providers/workspace.js +73 -0
- package/dist/reporters/browser.d.ts +2 -0
- package/dist/reporters/browser.js +85 -0
- package/dist/reporters/cli.d.ts +2 -0
- package/dist/reporters/cli.js +131 -0
- package/dist/reporters/diagnostics.d.ts +46 -0
- package/dist/reporters/diagnostics.js +147 -0
- package/dist/reporters/github-comment.d.ts +67 -0
- package/dist/reporters/github-comment.js +252 -0
- package/dist/reporters/loader.d.ts +8 -0
- package/dist/reporters/loader.js +36 -0
- package/dist/reporters/results-path.d.ts +2 -0
- package/dist/reporters/results-path.js +10 -0
- package/dist/reporters/verbose-emitter.d.ts +69 -0
- package/dist/reporters/verbose-emitter.js +103 -0
- package/dist/sdk/agent-crash.d.ts +19 -0
- package/dist/sdk/agent-crash.js +20 -0
- package/dist/sdk/agent-resolution.d.ts +12 -0
- package/dist/sdk/agent-resolution.js +21 -0
- package/dist/sdk/agent-result-log.d.ts +19 -0
- package/dist/sdk/agent-result-log.js +45 -0
- package/dist/sdk/agent.d.ts +4 -0
- package/dist/sdk/agent.js +354 -0
- package/dist/sdk/ask-bus/bus.d.ts +21 -0
- package/dist/sdk/ask-bus/bus.js +129 -0
- package/dist/sdk/ask-bus/handler.d.ts +31 -0
- package/dist/sdk/ask-bus/handler.js +244 -0
- package/dist/sdk/ask-bus/parsers.d.ts +9 -0
- package/dist/sdk/ask-bus/parsers.js +30 -0
- package/dist/sdk/ask-bus/projection.d.ts +26 -0
- package/dist/sdk/ask-bus/projection.js +45 -0
- package/dist/sdk/ask-bus/types.d.ts +69 -0
- package/dist/sdk/ask-bus/types.js +1 -0
- package/dist/sdk/chat.d.ts +29 -0
- package/dist/sdk/chat.js +93 -0
- package/dist/sdk/conversation-window.d.ts +14 -0
- package/dist/sdk/conversation-window.js +38 -0
- package/dist/sdk/converse.d.ts +42 -0
- package/dist/sdk/converse.js +329 -0
- package/dist/sdk/eval-runtime.d.ts +10 -0
- package/dist/sdk/eval-runtime.js +17 -0
- package/dist/sdk/evaluate.d.ts +13 -0
- package/dist/sdk/evaluate.js +325 -0
- package/dist/sdk/index.d.ts +31 -0
- package/dist/sdk/index.js +20 -0
- package/dist/sdk/judge-pipeline.d.ts +7 -0
- package/dist/sdk/judge-pipeline.js +178 -0
- package/dist/sdk/judge-prompt-builder.d.ts +7 -0
- package/dist/sdk/judge-prompt-builder.js +76 -0
- package/dist/sdk/judge-tool-runner.d.ts +19 -0
- package/dist/sdk/judge-tool-runner.js +51 -0
- package/dist/sdk/judge-tool-session.d.ts +47 -0
- package/dist/sdk/judge-tool-session.js +213 -0
- package/dist/sdk/judge-tools.d.ts +29 -0
- package/dist/sdk/judge-tools.js +283 -0
- package/dist/sdk/managed-session.d.ts +50 -0
- package/dist/sdk/managed-session.js +110 -0
- package/dist/sdk/persona.d.ts +5 -0
- package/dist/sdk/persona.js +33 -0
- package/dist/sdk/reaction-loader.d.ts +4 -0
- package/dist/sdk/reaction-loader.js +119 -0
- package/dist/sdk/reaction-preview.d.ts +6 -0
- package/dist/sdk/reaction-preview.js +94 -0
- package/dist/sdk/run-scorer.d.ts +10 -0
- package/dist/sdk/run-scorer.js +124 -0
- package/dist/sdk/runtime-policy.d.ts +21 -0
- package/dist/sdk/runtime-policy.js +89 -0
- package/dist/sdk/scorer-utils.d.ts +6 -0
- package/dist/sdk/scorer-utils.js +39 -0
- package/dist/sdk/scorers.d.ts +64 -0
- package/dist/sdk/scorers.js +80 -0
- package/dist/sdk/snapshots.d.ts +41 -0
- package/dist/sdk/snapshots.js +148 -0
- package/dist/sdk/types.d.ts +416 -0
- package/dist/sdk/types.js +17 -0
- package/dist/sdk/visible-turn.d.ts +4 -0
- package/dist/sdk/visible-turn.js +23 -0
- package/dist/tool-events.d.ts +45 -0
- package/dist/tool-events.js +167 -0
- package/dist/types.d.ts +372 -0
- package/dist/types.js +37 -0
- package/dist/utils/cli.d.ts +55 -0
- package/dist/utils/cli.js +131 -0
- package/dist/utils/env.d.ts +8 -0
- package/dist/utils/env.js +26 -0
- package/dist/utils/llm-mocks.d.ts +43 -0
- package/dist/utils/llm-mocks.js +108 -0
- package/dist/utils/llm-providers/anthropic.d.ts +2 -0
- package/dist/utils/llm-providers/anthropic.js +132 -0
- package/dist/utils/llm-providers/cli.d.ts +20 -0
- package/dist/utils/llm-providers/cli.js +162 -0
- package/dist/utils/llm-providers/openai.d.ts +2 -0
- package/dist/utils/llm-providers/openai.js +56 -0
- package/dist/utils/llm-types.d.ts +107 -0
- package/dist/utils/llm-types.js +1 -0
- package/dist/utils/llm.d.ts +36 -0
- package/dist/utils/llm.js +209 -0
- package/dist/utils/shutdown.d.ts +15 -0
- package/dist/utils/shutdown.js +41 -0
- package/dist/utils/timeout.d.ts +8 -0
- package/dist/utils/timeout.js +32 -0
- package/dist/viewer.html +1178 -0
- package/package.json +88 -0
- package/templates/eval.ts.template +28 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { buildAskBatchLogEntries, buildModelAgentResultLogEntry, } from './agent-result-log.js';
|
|
2
|
+
import { inspectReactions } from './reaction-preview.js';
|
|
3
|
+
import { getVisibleAssistantMessage, normalizeTurnResult } from './visible-turn.js';
|
|
4
|
+
import { AskBusTimeoutError } from './ask-bus/bus.js';
|
|
5
|
+
import { createAskUserHandler } from './ask-bus/handler.js';
|
|
6
|
+
import { AgentCrashError } from './agent-crash.js';
|
|
7
|
+
function isTimeoutError(err) {
|
|
8
|
+
return err instanceof Error && /timed out/i.test(err.message);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Translate a non-zero-exit `AgentTurnResult` into the Error the conversation
|
|
12
|
+
* loop throws after `pushModelAgentMessage` records the partial turn. The
|
|
13
|
+
* message shape mirrors what `AgentImpl.sendTurn` previously threw so
|
|
14
|
+
* downstream catch blocks (`isTimeoutError`, `AgentCrashError`,
|
|
15
|
+
* `AskBusTimeoutError`) keep matching by error class and message.
|
|
16
|
+
*/
|
|
17
|
+
function buildTurnExitError(turnResult, timeoutSec) {
|
|
18
|
+
if (turnResult.timedOut) {
|
|
19
|
+
const limit = timeoutSec !== undefined ? `Agent (limit: ${timeoutSec}s)` : 'Agent';
|
|
20
|
+
return new Error(`${limit} timed out (agent killed)`);
|
|
21
|
+
}
|
|
22
|
+
const detail = turnResult.rawOutput?.trim();
|
|
23
|
+
const suffix = detail ? `: ${detail}` : '';
|
|
24
|
+
if (turnResult.crashInfo) {
|
|
25
|
+
return new AgentCrashError(`Agent crashed${suffix}`, {
|
|
26
|
+
...(turnResult.crashInfo.pid !== undefined ? { pid: turnResult.crashInfo.pid } : {}),
|
|
27
|
+
...(turnResult.crashInfo.signal !== undefined ? { signal: turnResult.crashInfo.signal } : {}),
|
|
28
|
+
...(turnResult.crashInfo.exitCode !== undefined ? { exitCode: turnResult.crashInfo.exitCode } : {}),
|
|
29
|
+
partialToolEvents: turnResult.toolEvents,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return new Error(`Agent exited with code ${turnResult.exitCode}${suffix}`);
|
|
33
|
+
}
|
|
34
|
+
export async function runConversation(opts, deps) {
|
|
35
|
+
const maxTurns = opts.maxTurns ?? 30;
|
|
36
|
+
const reactions = opts.reactions ?? [];
|
|
37
|
+
const stepScorers = opts.stepScorers ?? [];
|
|
38
|
+
const firedOnce = new Set();
|
|
39
|
+
const stepResults = [];
|
|
40
|
+
const turnTimings = [];
|
|
41
|
+
const turnDetails = [];
|
|
42
|
+
const reactionsFired = [];
|
|
43
|
+
let turn = 0;
|
|
44
|
+
const conversationStart = Date.now();
|
|
45
|
+
const askUserHandlerApi = deps.askBus
|
|
46
|
+
? createAskUserHandler({
|
|
47
|
+
reactions,
|
|
48
|
+
onUnmatchedAskUser: opts.onUnmatchedAskUser ?? 'error',
|
|
49
|
+
firedOnce,
|
|
50
|
+
})
|
|
51
|
+
: null;
|
|
52
|
+
const unsubscribeAsk = askUserHandlerApi && deps.askBus
|
|
53
|
+
? deps.askBus.onAsk(askUserHandlerApi.handler)
|
|
54
|
+
: null;
|
|
55
|
+
const checkAskUserUnmatched = () => {
|
|
56
|
+
if (!askUserHandlerApi)
|
|
57
|
+
return null;
|
|
58
|
+
const err = askUserHandlerApi.getUnmatchedError();
|
|
59
|
+
if (!err)
|
|
60
|
+
return null;
|
|
61
|
+
// Include the first question text so the surfaced detail names
|
|
62
|
+
// *what* the agent asked, not just that some batch on some
|
|
63
|
+
// turn failed. Multi-question batches list only the first to keep
|
|
64
|
+
// detail strings bounded — full list ships on the structured
|
|
65
|
+
// signal for any tooling that needs it.
|
|
66
|
+
const firstText = err.questionTexts[0];
|
|
67
|
+
const detail = firstText
|
|
68
|
+
? `unmatched ask_user on turn ${err.turnNumber}: ${err.batchId}: ${firstText}`
|
|
69
|
+
: `unmatched ask_user on turn ${err.turnNumber}: ${err.batchId}`;
|
|
70
|
+
return buildResult('error', detail);
|
|
71
|
+
};
|
|
72
|
+
const MAX_TURN_RETRIES = 2;
|
|
73
|
+
const RETRY_DELAY_MS = 2_000;
|
|
74
|
+
const buildResult = (completionReason, completionDetail, crashDiagnostic) => {
|
|
75
|
+
deps.log.push({
|
|
76
|
+
type: 'conversation_end',
|
|
77
|
+
timestamp: new Date().toISOString(),
|
|
78
|
+
turn_number: turn,
|
|
79
|
+
completion_reason: completionReason,
|
|
80
|
+
completion_detail: completionDetail,
|
|
81
|
+
turn_timings: turnTimings,
|
|
82
|
+
turn_details: turnDetails,
|
|
83
|
+
reactions_fired: reactionsFired,
|
|
84
|
+
});
|
|
85
|
+
deps.verbose?.conversationEnd({
|
|
86
|
+
reason: completionReason,
|
|
87
|
+
turns: turn,
|
|
88
|
+
durationMs: Date.now() - conversationStart,
|
|
89
|
+
...(completionDetail ? { detail: completionDetail } : {}),
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
turns: turn,
|
|
93
|
+
completionReason,
|
|
94
|
+
completionDetail,
|
|
95
|
+
turnTimings,
|
|
96
|
+
turnDetails,
|
|
97
|
+
reactionsFired,
|
|
98
|
+
stepResults,
|
|
99
|
+
...(crashDiagnostic ? { crashDiagnostic } : {}),
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
const buildCrashDiagnostic = (err) => {
|
|
103
|
+
const allAsks = deps.askBus?.snapshot() ?? [];
|
|
104
|
+
const nonAskEvents = (err.partialToolEvents ?? []).filter((e) => e.action !== 'ask_user');
|
|
105
|
+
return {
|
|
106
|
+
pid: err.pid,
|
|
107
|
+
signal: err.signal ?? null,
|
|
108
|
+
exitCode: err.exitCode ?? null,
|
|
109
|
+
lastTurnNumber: turn,
|
|
110
|
+
partialAsks: allAsks,
|
|
111
|
+
partialToolEvents: nonAskEvents,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
// Send a message to the agent, update messages/log, return response.
|
|
115
|
+
// Turn counter increments only after the agent responds successfully.
|
|
116
|
+
// Retries transient agent errors (non-zero exit) up to MAX_TURN_RETRIES times.
|
|
117
|
+
const isFirstTurn = () => turn === 0;
|
|
118
|
+
const pushUserMessage = (message, kind, turnNumber) => {
|
|
119
|
+
deps.messages.push({ role: 'user', content: message });
|
|
120
|
+
deps.log.push({
|
|
121
|
+
type: kind,
|
|
122
|
+
timestamp: new Date().toISOString(),
|
|
123
|
+
instruction: message,
|
|
124
|
+
...(kind === 'user_reply' ? { turn_number: turnNumber } : {}),
|
|
125
|
+
});
|
|
126
|
+
deps.verbose?.turnStart({
|
|
127
|
+
turn: turnNumber ?? turn + 1,
|
|
128
|
+
kind,
|
|
129
|
+
message,
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
const pushModelAgentMessage = (response, turnNumber, durationMs, turnResult) => {
|
|
133
|
+
turnTimings.push({ turn: turnNumber, durationMs });
|
|
134
|
+
turnDetails.push({
|
|
135
|
+
turn: turnNumber,
|
|
136
|
+
durationMs,
|
|
137
|
+
outputLines: response.split('\n').length,
|
|
138
|
+
outputChars: response.length,
|
|
139
|
+
});
|
|
140
|
+
deps.messages.push({ role: 'agent', content: response });
|
|
141
|
+
const timestamp = new Date().toISOString();
|
|
142
|
+
if (deps.askBus) {
|
|
143
|
+
for (const entry of buildAskBatchLogEntries({
|
|
144
|
+
askBus: deps.askBus,
|
|
145
|
+
turnNumber,
|
|
146
|
+
timestamp,
|
|
147
|
+
})) {
|
|
148
|
+
deps.log.push(entry);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
deps.log.push(buildModelAgentResultLogEntry({
|
|
152
|
+
timestamp,
|
|
153
|
+
turnNumber,
|
|
154
|
+
durationMs,
|
|
155
|
+
turnResult,
|
|
156
|
+
assistantMessage: response,
|
|
157
|
+
}));
|
|
158
|
+
for (const toolEvent of turnResult.toolEvents) {
|
|
159
|
+
deps.verbose?.toolEvent({
|
|
160
|
+
action: toolEvent.action,
|
|
161
|
+
summary: toolEvent.summary,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
deps.verbose?.turnEnd({
|
|
165
|
+
turn: turnNumber,
|
|
166
|
+
durationMs,
|
|
167
|
+
outputLines: response.split('\n').length,
|
|
168
|
+
messagePreview: response,
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
const doModelTurn = async (message, options = {}) => {
|
|
172
|
+
if (!options.preLogged) {
|
|
173
|
+
pushUserMessage(message, options.kind ?? (isFirstTurn() ? 'agent_start' : 'user_reply'), turn + 1);
|
|
174
|
+
}
|
|
175
|
+
const turnStart = Date.now();
|
|
176
|
+
// Under app-server the child process holds thread state; a crashed
|
|
177
|
+
// turn is not safely replayable, so retries are suppressed.
|
|
178
|
+
const maxRetries = deps.transport === 'app-server' ? 0 : MAX_TURN_RETRIES;
|
|
179
|
+
let lastError;
|
|
180
|
+
let turnResult;
|
|
181
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
182
|
+
try {
|
|
183
|
+
turnResult = normalizeTurnResult(await deps.sendTurn(message));
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
lastError = err;
|
|
188
|
+
// Don't retry timeouts — only transient agent errors
|
|
189
|
+
if (isTimeoutError(err))
|
|
190
|
+
throw err;
|
|
191
|
+
// Subprocess crashes bypass retries regardless of transport —
|
|
192
|
+
// the error itself is the signal that replay is unsafe.
|
|
193
|
+
if (err instanceof AgentCrashError)
|
|
194
|
+
throw err;
|
|
195
|
+
// Ask-bus rejections (no subscriber, slow subscriber) do
|
|
196
|
+
// not recover on retry — retrying just burns the retry
|
|
197
|
+
// window before the same `error` completion. Surface the
|
|
198
|
+
// bus error immediately.
|
|
199
|
+
if (err instanceof AskBusTimeoutError)
|
|
200
|
+
throw err;
|
|
201
|
+
if (attempt < maxRetries) {
|
|
202
|
+
deps.log.push({
|
|
203
|
+
type: 'agent_result',
|
|
204
|
+
timestamp: new Date().toISOString(),
|
|
205
|
+
assistant_message: `[retry ${attempt + 1}/${maxRetries}] ${err.message}`,
|
|
206
|
+
});
|
|
207
|
+
deps.verbose?.retry({
|
|
208
|
+
attempt: attempt + 1,
|
|
209
|
+
maxAttempts: maxRetries,
|
|
210
|
+
errorMessage: err.message,
|
|
211
|
+
});
|
|
212
|
+
// Remove the user message we pushed so it gets re-pushed on retry
|
|
213
|
+
if (!options.preLogged) {
|
|
214
|
+
deps.messages.pop();
|
|
215
|
+
}
|
|
216
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS * (attempt + 1)));
|
|
217
|
+
if (!options.preLogged) {
|
|
218
|
+
deps.messages.push({ role: 'user', content: message });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (turnResult === undefined)
|
|
224
|
+
throw lastError;
|
|
225
|
+
turn++;
|
|
226
|
+
const response = getVisibleAssistantMessage(turnResult);
|
|
227
|
+
const durationMs = Date.now() - turnStart;
|
|
228
|
+
// Project the partial turn (`pushModelAgentMessage`) BEFORE any
|
|
229
|
+
// exit-code throw so the failure mode is observable in the same
|
|
230
|
+
// shape as a successful turn — `model_agent_result`, `ask_batch`,
|
|
231
|
+
// turn timings/details all capture the rejected turn before the
|
|
232
|
+
// runner propagates the error. Exit-code failures bypass retry by
|
|
233
|
+
// construction (already logged): retrying would re-emit those log
|
|
234
|
+
// entries on a successful retry, double-counting the turn.
|
|
235
|
+
pushModelAgentMessage(response, turn, durationMs, turnResult);
|
|
236
|
+
if (turnResult.exitCode !== 0) {
|
|
237
|
+
throw buildTurnExitError(turnResult, deps.agentTimeoutSec);
|
|
238
|
+
}
|
|
239
|
+
return response;
|
|
240
|
+
};
|
|
241
|
+
try {
|
|
242
|
+
// Preflight: transport 'exec' + AskUserReaction is unreachable. Fail fast
|
|
243
|
+
// (before any turn runs) unless the caller opted out.
|
|
244
|
+
if (deps.transport === 'exec'
|
|
245
|
+
&& !opts.allowUnreachableReactions
|
|
246
|
+
&& reactions.some((r) => 'whenAsked' in r)) {
|
|
247
|
+
return buildResult('error', "AskUserReaction defined but transport is 'exec'; the handshake cannot fire under exec mode.");
|
|
248
|
+
}
|
|
249
|
+
// Turn 1: send opener
|
|
250
|
+
let agentMessage = await doModelTurn(opts.firstMessage, { kind: 'agent_start' });
|
|
251
|
+
const unmatchedAfterOpener = checkAskUserUnmatched();
|
|
252
|
+
if (unmatchedAfterOpener)
|
|
253
|
+
return unmatchedAfterOpener;
|
|
254
|
+
while (true) {
|
|
255
|
+
// Check until predicate
|
|
256
|
+
if (opts.until) {
|
|
257
|
+
const done = await opts.until({
|
|
258
|
+
turn,
|
|
259
|
+
lastMessage: agentMessage,
|
|
260
|
+
workspace: deps.workspace,
|
|
261
|
+
messages: deps.messages,
|
|
262
|
+
hasFile: deps.hasFile,
|
|
263
|
+
});
|
|
264
|
+
if (done)
|
|
265
|
+
return buildResult('until');
|
|
266
|
+
}
|
|
267
|
+
// Check maxTurns
|
|
268
|
+
if (turn >= maxTurns) {
|
|
269
|
+
return buildResult('maxTurns');
|
|
270
|
+
}
|
|
271
|
+
// Run step scorers scheduled for this turn
|
|
272
|
+
for (const sg of stepScorers) {
|
|
273
|
+
if (sg.afterTurn === turn && deps.runStepScorers) {
|
|
274
|
+
const result = await deps.runStepScorers(sg.scorers);
|
|
275
|
+
stepResults.push({ afterTurn: sg.afterTurn, result });
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Pick reply: reactions first, then persona fallback.
|
|
279
|
+
// Only text-variant reactions fire from assistant free text; ask_user
|
|
280
|
+
// reactions are handled by the bus subscription (slice #4).
|
|
281
|
+
const reactionEvaluations = inspectReactions(agentMessage, reactions, firedOnce);
|
|
282
|
+
const firedTextEvaluation = reactionEvaluations.find((reaction) => reaction.fired && reaction.kind === 'text');
|
|
283
|
+
let reply = firedTextEvaluation && firedTextEvaluation.kind === 'text'
|
|
284
|
+
? firedTextEvaluation.reply ?? null
|
|
285
|
+
: null;
|
|
286
|
+
if (firedTextEvaluation && firedTextEvaluation.kind === 'text') {
|
|
287
|
+
const firedReactionCfg = reactions[firedTextEvaluation.reactionIndex];
|
|
288
|
+
const pattern = firedReactionCfg && 'when' in firedReactionCfg
|
|
289
|
+
? String(firedReactionCfg.when)
|
|
290
|
+
: '';
|
|
291
|
+
reactionsFired.push({
|
|
292
|
+
turn,
|
|
293
|
+
reactionIndex: firedTextEvaluation.reactionIndex,
|
|
294
|
+
pattern,
|
|
295
|
+
reply: firedTextEvaluation.reply ?? '',
|
|
296
|
+
});
|
|
297
|
+
deps.verbose?.reactionFired({
|
|
298
|
+
turn,
|
|
299
|
+
reactionIndex: firedTextEvaluation.reactionIndex,
|
|
300
|
+
pattern,
|
|
301
|
+
reply: firedTextEvaluation.reply ?? '',
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
if (reply === null && deps.personaReply) {
|
|
305
|
+
reply = await deps.personaReply();
|
|
306
|
+
}
|
|
307
|
+
if (reply === null) {
|
|
308
|
+
return buildResult('noReply');
|
|
309
|
+
}
|
|
310
|
+
agentMessage = await doModelTurn(reply, { kind: 'user_reply' });
|
|
311
|
+
const unmatched = checkAskUserUnmatched();
|
|
312
|
+
if (unmatched)
|
|
313
|
+
return unmatched;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
if (err instanceof AgentCrashError) {
|
|
318
|
+
return buildResult('agent_crashed', err.message, buildCrashDiagnostic(err));
|
|
319
|
+
}
|
|
320
|
+
const reason = isTimeoutError(err) ? 'timeout' : 'error';
|
|
321
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
322
|
+
return buildResult(reason, detail);
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
if (unsubscribeAsk)
|
|
326
|
+
unsubscribeAsk();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
export { previewReactions } from './reaction-preview.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LLMPort } from '../utils/llm-types.js';
|
|
2
|
+
import type { Agent, RecordedEvalResult } from './types.js';
|
|
3
|
+
export type { LLMPort } from '../utils/llm-types.js';
|
|
4
|
+
export interface EvalRuntime {
|
|
5
|
+
llm: LLMPort;
|
|
6
|
+
onResult: (result: RecordedEvalResult, agent: Agent) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function getRuntime(): EvalRuntime;
|
|
9
|
+
export declare function setRuntime(partial: Partial<EvalRuntime>): void;
|
|
10
|
+
export declare function resetRuntime(): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { callLLM } from '../utils/llm.js';
|
|
2
|
+
function makeDefaultRuntime() {
|
|
3
|
+
return {
|
|
4
|
+
llm: { call: (prompt, opts) => callLLM(prompt, opts) },
|
|
5
|
+
onResult: () => { },
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
let current = makeDefaultRuntime();
|
|
9
|
+
export function getRuntime() {
|
|
10
|
+
return current;
|
|
11
|
+
}
|
|
12
|
+
export function setRuntime(partial) {
|
|
13
|
+
current = { ...current, ...partial };
|
|
14
|
+
}
|
|
15
|
+
export function resetRuntime() {
|
|
16
|
+
current = makeDefaultRuntime();
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Agent, Scorer, EvalResult, RecordedEvalResult, ScorerResultEntry, EvaluateOptions } from './types.js';
|
|
2
|
+
export type OnScorerErrorMode = NonNullable<EvaluateOptions['onScorerError']>;
|
|
3
|
+
export declare class EvalScorerError extends Error {
|
|
4
|
+
readonly scorerErrors: ScorerResultEntry[];
|
|
5
|
+
readonly result: RecordedEvalResult;
|
|
6
|
+
constructor(result: RecordedEvalResult, scorerErrors: ScorerResultEntry[]);
|
|
7
|
+
}
|
|
8
|
+
type EvaluateFromSnapshot = (snapshotPath: string, scorers: Scorer[], opts?: EvaluateOptions) => Promise<EvalResult>;
|
|
9
|
+
type EvaluateFn = ((agent: Agent, scorers: Scorer[], opts?: EvaluateOptions) => Promise<EvalResult>) & {
|
|
10
|
+
fromSnapshot: EvaluateFromSnapshot;
|
|
11
|
+
};
|
|
12
|
+
export declare const evaluate: EvaluateFn;
|
|
13
|
+
export {};
|