@granular-software/sdk 0.4.46 → 0.4.47
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/dist/agent-evals.d.mts +3 -0
- package/dist/agent-evals.d.ts +3 -0
- package/dist/agent-evals.js +692 -419
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +692 -419
- package/dist/agent-evals.mjs.map +1 -1
- package/package.json +1 -1
package/dist/agent-evals.js
CHANGED
|
@@ -19888,6 +19888,202 @@ async function writeJson(filePath, value) {
|
|
|
19888
19888
|
await promises.writeFile(filePath, `${JSON.stringify(value, null, 2)}
|
|
19889
19889
|
`);
|
|
19890
19890
|
}
|
|
19891
|
+
function safePathSegment(value, fallback) {
|
|
19892
|
+
const normalized = (value || "").trim().toLowerCase();
|
|
19893
|
+
const sanitized = normalized.replace(/[^a-z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, 128);
|
|
19894
|
+
return sanitized || fallback;
|
|
19895
|
+
}
|
|
19896
|
+
function extractToolCalls(rawGeneration) {
|
|
19897
|
+
const raw = asRecord6(rawGeneration);
|
|
19898
|
+
if (!raw) return null;
|
|
19899
|
+
const choices = asArray3(raw.choices);
|
|
19900
|
+
const firstChoiceMessage = asRecord6(choices[0]);
|
|
19901
|
+
const message = asRecord6(firstChoiceMessage?.message);
|
|
19902
|
+
const toolCalls = asArray3(message?.tool_calls);
|
|
19903
|
+
if (toolCalls.length > 0) return toolCalls;
|
|
19904
|
+
return asArray3(raw.tool_calls).length > 0 ? asArray3(raw.tool_calls) : null;
|
|
19905
|
+
}
|
|
19906
|
+
function buildTurnMdxReport(input) {
|
|
19907
|
+
const {
|
|
19908
|
+
status,
|
|
19909
|
+
conversation,
|
|
19910
|
+
request,
|
|
19911
|
+
requestTimestamp,
|
|
19912
|
+
turnLog,
|
|
19913
|
+
responseText,
|
|
19914
|
+
terminalKind,
|
|
19915
|
+
actionSummary = [],
|
|
19916
|
+
promptInteractions = [],
|
|
19917
|
+
result,
|
|
19918
|
+
prompts = [],
|
|
19919
|
+
verification,
|
|
19920
|
+
error
|
|
19921
|
+
} = input;
|
|
19922
|
+
const iterationLines = [];
|
|
19923
|
+
for (const iteration of turnLog.iterations) {
|
|
19924
|
+
iterationLines.push(`### Iteration ${iteration.iteration}`);
|
|
19925
|
+
iterationLines.push(
|
|
19926
|
+
`- Request: ${iteration.request}`,
|
|
19927
|
+
`- Generation duration: ${iteration.generationDurationMs !== void 0 ? `${iteration.generationDurationMs}ms` : "unknown"}`
|
|
19928
|
+
);
|
|
19929
|
+
if (iteration.templateId) {
|
|
19930
|
+
iterationLines.push(
|
|
19931
|
+
`- Template: ${iteration.templateId}@${iteration.templateVersion || "unknown"}`
|
|
19932
|
+
);
|
|
19933
|
+
}
|
|
19934
|
+
if (iteration.templateHash) {
|
|
19935
|
+
iterationLines.push(`- Template hash: ${iteration.templateHash}`);
|
|
19936
|
+
}
|
|
19937
|
+
if (iteration.promptInstanceHash) {
|
|
19938
|
+
iterationLines.push(`- Prompt hash: ${iteration.promptInstanceHash}`);
|
|
19939
|
+
}
|
|
19940
|
+
iterationLines.push("", "#### Full prompt sent to LLM", "");
|
|
19941
|
+
iterationLines.push(fenced(iteration.systemPrompt, "text"));
|
|
19942
|
+
if (iteration.generationReply?.trim()) {
|
|
19943
|
+
iterationLines.push(
|
|
19944
|
+
"",
|
|
19945
|
+
"#### LLM reply text",
|
|
19946
|
+
iteration.generationReply.trim(),
|
|
19947
|
+
""
|
|
19948
|
+
);
|
|
19949
|
+
}
|
|
19950
|
+
if (iteration.generatedCode?.trim()) {
|
|
19951
|
+
iterationLines.push("#### Generated code", "", fenced(iteration.generatedCode.trim(), "ts"));
|
|
19952
|
+
}
|
|
19953
|
+
const toolCalls = extractToolCalls(iteration.rawGeneration);
|
|
19954
|
+
iterationLines.push("#### Tool calls / raw generation", "");
|
|
19955
|
+
if (toolCalls) {
|
|
19956
|
+
iterationLines.push(fenced(JSON.stringify(toolCalls, null, 2), "json"));
|
|
19957
|
+
} else if (iteration.rawGeneration) {
|
|
19958
|
+
iterationLines.push(fenced(JSON.stringify(iteration.rawGeneration, null, 2), "json"));
|
|
19959
|
+
} else {
|
|
19960
|
+
iterationLines.push("_No tool call information._");
|
|
19961
|
+
}
|
|
19962
|
+
if (iteration.tokenUsage) {
|
|
19963
|
+
iterationLines.push("", "#### Token usage", ...formatTokenUsage(iteration.tokenUsage));
|
|
19964
|
+
}
|
|
19965
|
+
if (iteration.responseText?.trim()) {
|
|
19966
|
+
iterationLines.push("", "#### Runtime/prompt outcome", iteration.responseText);
|
|
19967
|
+
}
|
|
19968
|
+
if (iteration.actionSummary?.length) {
|
|
19969
|
+
iterationLines.push("", "#### Action summary", "");
|
|
19970
|
+
iterationLines.push(...iteration.actionSummary.map((line) => `- ${line}`));
|
|
19971
|
+
}
|
|
19972
|
+
if (iteration.continuation) {
|
|
19973
|
+
iterationLines.push("", "#### Continuation", "", jsonBlock(iteration.continuation));
|
|
19974
|
+
}
|
|
19975
|
+
if (iteration.result !== void 0) {
|
|
19976
|
+
iterationLines.push("", "#### Result", "", jsonBlock(iteration.result));
|
|
19977
|
+
}
|
|
19978
|
+
if (iteration.error) {
|
|
19979
|
+
iterationLines.push("", `#### Error`, "", iteration.error);
|
|
19980
|
+
}
|
|
19981
|
+
iterationLines.push("", "---", "");
|
|
19982
|
+
}
|
|
19983
|
+
const promptEventLines = conversation.promptEvents.filter((event) => event.receivedAt >= requestTimestamp).map((event, index) => {
|
|
19984
|
+
const prompt = event.prompt;
|
|
19985
|
+
return `${index + 1}. ${prompt.type} ${prompt.title || ""} ${prompt.message ? `\u2014 ${prompt.message}` : ""}`;
|
|
19986
|
+
});
|
|
19987
|
+
const historyLines = conversation.history.map((entry, index) => {
|
|
19988
|
+
const label = `${index + 1}. ${entry.role}`;
|
|
19989
|
+
const detail = entry.content || (entry.code ? "(code)" : "");
|
|
19990
|
+
return `${label}: ${detail || "(no text)"}`;
|
|
19991
|
+
});
|
|
19992
|
+
const lines = [
|
|
19993
|
+
"# Local Agent Query Report",
|
|
19994
|
+
"",
|
|
19995
|
+
`- timestamp: ${new Date(requestTimestamp).toISOString()}`,
|
|
19996
|
+
`- turn: ${turnLog.turnNumber} (${turnLog.turnId})`,
|
|
19997
|
+
`- status: ${status}`,
|
|
19998
|
+
"",
|
|
19999
|
+
"## Table of contents",
|
|
20000
|
+
"- [Metadata](#metadata)",
|
|
20001
|
+
"- [User query and context](#user-query-and-context)",
|
|
20002
|
+
"- [Conversation history](#conversation-history)",
|
|
20003
|
+
"- [Harness loop iterations](#harness-loop-iterations)",
|
|
20004
|
+
"- [Result and interactions](#result-and-interactions)",
|
|
20005
|
+
"",
|
|
20006
|
+
"## Metadata",
|
|
20007
|
+
`- Ontology: ${conversation.environment.ontologyId}`,
|
|
20008
|
+
`- Subject: ${conversation.environment.subjectId}`,
|
|
20009
|
+
`- Session: ${conversation.environment.sessionId}`,
|
|
20010
|
+
`- Environment: ${conversation.environment.environmentId}`,
|
|
20011
|
+
`- Sandbox: ${conversation.environment.sandboxId}`,
|
|
20012
|
+
`- Permission profile: ${conversation.environment.permissionProfileId}`,
|
|
20013
|
+
`- Conversation artifacts: ${turnLog.turnDir}`,
|
|
20014
|
+
"",
|
|
20015
|
+
"## User query and context",
|
|
20016
|
+
"",
|
|
20017
|
+
"### Request",
|
|
20018
|
+
fenced(request, "text"),
|
|
20019
|
+
"",
|
|
20020
|
+
"### Open prompts at/after request time"
|
|
20021
|
+
];
|
|
20022
|
+
if (promptEventLines.length) {
|
|
20023
|
+
lines.push(...promptEventLines.map((line) => `- ${line}`));
|
|
20024
|
+
} else {
|
|
20025
|
+
lines.push("- _None");
|
|
20026
|
+
}
|
|
20027
|
+
lines.push(
|
|
20028
|
+
"",
|
|
20029
|
+
"## Conversation history",
|
|
20030
|
+
...historyLines.map((line) => `- ${line}`),
|
|
20031
|
+
"",
|
|
20032
|
+
"## Harness loop iterations",
|
|
20033
|
+
"",
|
|
20034
|
+
...iterationLines,
|
|
20035
|
+
"## Result and interactions",
|
|
20036
|
+
""
|
|
20037
|
+
);
|
|
20038
|
+
if (responseText) {
|
|
20039
|
+
lines.push("### Final response", responseText, "");
|
|
20040
|
+
}
|
|
20041
|
+
if (terminalKind) {
|
|
20042
|
+
lines.push(`### Terminal kind`, terminalKind, "");
|
|
20043
|
+
}
|
|
20044
|
+
lines.push("### Action summary");
|
|
20045
|
+
if (actionSummary.length) {
|
|
20046
|
+
lines.push(...actionSummary.map((line) => `- ${line}`));
|
|
20047
|
+
} else {
|
|
20048
|
+
lines.push("- None");
|
|
20049
|
+
}
|
|
20050
|
+
lines.push("", "### User interactions");
|
|
20051
|
+
if (promptInteractions.length) {
|
|
20052
|
+
for (const interaction of promptInteractions) {
|
|
20053
|
+
lines.push(
|
|
20054
|
+
`- ${interaction.type} ${interaction.message || interaction.title} -> ${JSON.stringify(interaction.answer)}`
|
|
20055
|
+
);
|
|
20056
|
+
}
|
|
20057
|
+
} else {
|
|
20058
|
+
lines.push("- None");
|
|
20059
|
+
}
|
|
20060
|
+
lines.push("", "### Pending prompts");
|
|
20061
|
+
if (prompts.length) {
|
|
20062
|
+
for (const prompt of prompts) {
|
|
20063
|
+
lines.push(`- ${prompt.type} ${prompt.title || ""} ${prompt.message || ""}`);
|
|
20064
|
+
}
|
|
20065
|
+
} else {
|
|
20066
|
+
lines.push("- None");
|
|
20067
|
+
}
|
|
20068
|
+
if (result !== void 0) {
|
|
20069
|
+
lines.push("", "### Result payload", "", jsonBlock(result));
|
|
20070
|
+
}
|
|
20071
|
+
if (verification !== void 0) {
|
|
20072
|
+
lines.push("", "### Verification", "", jsonBlock(verification));
|
|
20073
|
+
}
|
|
20074
|
+
if (error) {
|
|
20075
|
+
lines.push("", `### Error`, "", error);
|
|
20076
|
+
}
|
|
20077
|
+
if (turnLog.error) {
|
|
20078
|
+
lines.push("", "### Turn log error", "", turnLog.error);
|
|
20079
|
+
}
|
|
20080
|
+
lines.push("");
|
|
20081
|
+
if (iterationLines.length === 0) {
|
|
20082
|
+
lines.splice(lines.indexOf("## Harness loop iterations") + 1, 0, "- _No iterations recorded._");
|
|
20083
|
+
}
|
|
20084
|
+
return `${lines.join("\n")}
|
|
20085
|
+
`;
|
|
20086
|
+
}
|
|
19891
20087
|
function describeScenarioBehavior(result) {
|
|
19892
20088
|
if (result.scenario.description?.trim()) {
|
|
19893
20089
|
return result.scenario.description.trim();
|
|
@@ -20668,6 +20864,16 @@ function createAgentEvalHarness(options) {
|
|
|
20668
20864
|
const chatTimeoutMs = options.chatTimeoutMs ?? 12e4;
|
|
20669
20865
|
const jobTimeoutMs = options.jobTimeoutMs ?? 9e4;
|
|
20670
20866
|
const pollIntervalMs = options.pollIntervalMs ?? 250;
|
|
20867
|
+
const isTruthyEnv = (value) => {
|
|
20868
|
+
return value?.trim().toLowerCase() === "1" || value?.trim().toLowerCase() === "true" || value?.trim().toLowerCase() === "yes" || value?.trim().toLowerCase() === "on";
|
|
20869
|
+
};
|
|
20870
|
+
const localTurnReportsEnabled = (() => {
|
|
20871
|
+
if (typeof options.local === "boolean") return options.local;
|
|
20872
|
+
return process.env.NODE_ENV === "development" || isTruthyEnv(process.env.GRANULAR_LOCAL) || isTruthyEnv(process.env.GRANULAR_USE_LOCAL_ENDPOINTS) || isTruthyEnv(process.env.GRANULAR_USE_LOCAL) || process.env.GRANULAR_ENDPOINT_MODE?.toLowerCase() === "local";
|
|
20873
|
+
})();
|
|
20874
|
+
const localTurnReportBaseDir = path__default.default.resolve(
|
|
20875
|
+
options.localTurnReportBaseDir || process.cwd()
|
|
20876
|
+
);
|
|
20671
20877
|
const resolvedTemplate = resolveHarnessTemplate(
|
|
20672
20878
|
options.harnessTemplateId || process.env.GRANULAR_AGENT_HARNESS_TEMPLATE || "stable");
|
|
20673
20879
|
const promptRenderer = options.promptRenderer || resolvedTemplate.renderPrompt;
|
|
@@ -20716,6 +20922,41 @@ function createAgentEvalHarness(options) {
|
|
|
20716
20922
|
} catch {
|
|
20717
20923
|
}
|
|
20718
20924
|
}
|
|
20925
|
+
async function writeLocalTurnReport(input) {
|
|
20926
|
+
if (!localTurnReportsEnabled) return;
|
|
20927
|
+
const { status, conversation, turnLog, request, requestTimestamp, error } = input;
|
|
20928
|
+
const requestId = safePathSegment(
|
|
20929
|
+
new Date(requestTimestamp).toISOString().replace(/[:.]/g, "-"),
|
|
20930
|
+
"turn"
|
|
20931
|
+
);
|
|
20932
|
+
const reportDir = path__default.default.join(
|
|
20933
|
+
localTurnReportBaseDir,
|
|
20934
|
+
safePathSegment(conversation.environment.ontologyId, "ontology"),
|
|
20935
|
+
safePathSegment(conversation.environment.subjectId, "subject"),
|
|
20936
|
+
safePathSegment(conversation.environment.sessionId, "session")
|
|
20937
|
+
);
|
|
20938
|
+
await ensureDir(reportDir);
|
|
20939
|
+
const completed = input.completed;
|
|
20940
|
+
const pending = input.pending;
|
|
20941
|
+
const report = buildTurnMdxReport({
|
|
20942
|
+
status,
|
|
20943
|
+
conversation,
|
|
20944
|
+
request,
|
|
20945
|
+
requestTimestamp,
|
|
20946
|
+
turnLog,
|
|
20947
|
+
responseText: completed?.responseText,
|
|
20948
|
+
terminalKind: completed?.terminalKind,
|
|
20949
|
+
actionSummary: completed?.actionSummary,
|
|
20950
|
+
promptInteractions: completed?.promptInteractions || pending?.promptInteractions,
|
|
20951
|
+
result: completed?.result,
|
|
20952
|
+
prompts: pending?.prompts,
|
|
20953
|
+
verification: completed?.verification,
|
|
20954
|
+
error
|
|
20955
|
+
});
|
|
20956
|
+
const reportPath = path__default.default.join(reportDir, `${requestId}.mdx`);
|
|
20957
|
+
await promises.writeFile(reportPath, report);
|
|
20958
|
+
console.log(`[agent][local] saved query report: ${reportPath}`);
|
|
20959
|
+
}
|
|
20719
20960
|
async function runCheckJob(code, session) {
|
|
20720
20961
|
const job = await session.submitJob(code);
|
|
20721
20962
|
return withTimeout2(job.result, jobTimeoutMs, `check job ${job.id}`);
|
|
@@ -20975,99 +21216,96 @@ function createAgentEvalHarness(options) {
|
|
|
20975
21216
|
const baselineClosureId = getCurrentClosureId(
|
|
20976
21217
|
cloneJson(conversation.environment.document)
|
|
20977
21218
|
);
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
boundaryTimestamp
|
|
20985
|
-
|
|
20986
|
-
|
|
20987
|
-
|
|
21219
|
+
const writeTurnReport = async (status) => {
|
|
21220
|
+
await writeLocalTurnReport({
|
|
21221
|
+
status: status.type,
|
|
21222
|
+
conversation,
|
|
21223
|
+
turnLog,
|
|
21224
|
+
request: input.request,
|
|
21225
|
+
requestTimestamp: boundaryTimestamp,
|
|
21226
|
+
completed: status.completed,
|
|
21227
|
+
pending: status.pending,
|
|
21228
|
+
error: status.error
|
|
20988
21229
|
});
|
|
20989
|
-
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
...workflowFocus.entryPaths,
|
|
20998
|
-
...referentFocus.entryPaths,
|
|
20999
|
-
...focusedHeapEntryPathsFromUiContext(promptHeap, input.uiContext)
|
|
21000
|
-
]
|
|
21001
|
-
};
|
|
21002
|
-
const tools = conversation.environment.getEffects().map((tool) => ({
|
|
21003
|
-
name: tool.name,
|
|
21004
|
-
description: tool.description,
|
|
21005
|
-
className: tool.className,
|
|
21006
|
-
static: tool.static,
|
|
21007
|
-
ready: tool.ready,
|
|
21008
|
-
inputSchema: tool.inputSchema,
|
|
21009
|
-
outputSchema: tool.outputSchema
|
|
21010
|
-
}));
|
|
21011
|
-
const renderedPrompt = promptRenderer({
|
|
21012
|
-
domainDocumentation: await conversation.environment.getDomainDocumentation(),
|
|
21013
|
-
sessionContext: {
|
|
21014
|
-
sandboxId: conversation.environment.sandboxId,
|
|
21015
|
-
environmentId: conversation.environment.environmentId,
|
|
21016
|
-
domainRevision: conversation.environment.domainRevision,
|
|
21017
|
-
uiContext: input.uiContext || null
|
|
21018
|
-
},
|
|
21019
|
-
heapSummary: projectHeapSummary(asRecord6(liveDoc?.heap), {
|
|
21020
|
-
focus: heapFocus
|
|
21021
|
-
}),
|
|
21022
|
-
fileSummary: projectSessionFileSummary(liveDoc),
|
|
21023
|
-
referentSummary: projectConversationReferentSummary(liveDoc),
|
|
21024
|
-
loopSummary: projectLoopSummary(liveDoc, pendingPrompts, {
|
|
21230
|
+
};
|
|
21231
|
+
try {
|
|
21232
|
+
while (iteration < maxIterations) {
|
|
21233
|
+
const liveDoc = cloneJson(conversation.environment.document);
|
|
21234
|
+
const promptHeap = normalizeHeapSnapshot2(asRecord6(liveDoc?.heap));
|
|
21235
|
+
const pendingPrompts = filterPromptsByBoundary(
|
|
21236
|
+
liveDoc,
|
|
21237
|
+
getOpenPromptsFromDoc(liveDoc),
|
|
21025
21238
|
boundaryTimestamp
|
|
21026
|
-
|
|
21027
|
-
|
|
21239
|
+
);
|
|
21240
|
+
const workflowFocus = projectWorkflowFocus(liveDoc, pendingPrompts, {
|
|
21028
21241
|
boundaryTimestamp
|
|
21029
|
-
})
|
|
21030
|
-
|
|
21031
|
-
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
21035
|
-
|
|
21036
|
-
|
|
21037
|
-
|
|
21038
|
-
|
|
21039
|
-
|
|
21040
|
-
|
|
21041
|
-
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
|
|
21242
|
+
});
|
|
21243
|
+
const referentFocus = projectConversationReferentFocus(liveDoc);
|
|
21244
|
+
const heapFocus = {
|
|
21245
|
+
variableNames: [
|
|
21246
|
+
...workflowFocus.variableNames,
|
|
21247
|
+
...referentFocus.variableNames
|
|
21248
|
+
],
|
|
21249
|
+
listNames: [...workflowFocus.listNames, ...referentFocus.listNames],
|
|
21250
|
+
entryPaths: [
|
|
21251
|
+
...workflowFocus.entryPaths,
|
|
21252
|
+
...referentFocus.entryPaths,
|
|
21253
|
+
...focusedHeapEntryPathsFromUiContext(promptHeap, input.uiContext)
|
|
21254
|
+
]
|
|
21255
|
+
};
|
|
21256
|
+
const tools = conversation.environment.getEffects().map((tool) => ({
|
|
21257
|
+
name: tool.name,
|
|
21258
|
+
description: tool.description,
|
|
21259
|
+
className: tool.className,
|
|
21260
|
+
static: tool.static,
|
|
21261
|
+
ready: tool.ready,
|
|
21262
|
+
inputSchema: tool.inputSchema,
|
|
21263
|
+
outputSchema: tool.outputSchema
|
|
21264
|
+
}));
|
|
21265
|
+
const renderedPrompt = promptRenderer({
|
|
21266
|
+
domainDocumentation: await conversation.environment.getDomainDocumentation(),
|
|
21267
|
+
sessionContext: {
|
|
21268
|
+
sandboxId: conversation.environment.sandboxId,
|
|
21269
|
+
environmentId: conversation.environment.environmentId,
|
|
21270
|
+
domainRevision: conversation.environment.domainRevision,
|
|
21271
|
+
uiContext: input.uiContext || null
|
|
21272
|
+
},
|
|
21273
|
+
heapSummary: projectHeapSummary(asRecord6(liveDoc?.heap), {
|
|
21274
|
+
focus: heapFocus
|
|
21275
|
+
}),
|
|
21276
|
+
fileSummary: projectSessionFileSummary(liveDoc),
|
|
21277
|
+
referentSummary: projectConversationReferentSummary(liveDoc),
|
|
21278
|
+
loopSummary: projectLoopSummary(liveDoc, pendingPrompts, {
|
|
21279
|
+
boundaryTimestamp
|
|
21280
|
+
}),
|
|
21281
|
+
workflowSummary: projectWorkflowSummary(liveDoc, pendingPrompts, {
|
|
21282
|
+
boundaryTimestamp
|
|
21283
|
+
}),
|
|
21284
|
+
tools,
|
|
21285
|
+
checkpoint: latestCheckpoint
|
|
21286
|
+
});
|
|
21287
|
+
const systemPrompt = renderedPrompt.prompt;
|
|
21288
|
+
await emitProgress(onProgress, {
|
|
21289
|
+
phase: "prompt",
|
|
21290
|
+
status: "passed",
|
|
21291
|
+
scenarioId: conversation.label,
|
|
21292
|
+
stepId: turnId,
|
|
21293
|
+
iteration: iteration + 1,
|
|
21045
21294
|
templateId: renderedPrompt.templateId,
|
|
21046
21295
|
templateVersion: renderedPrompt.templateVersion,
|
|
21047
|
-
|
|
21048
|
-
|
|
21049
|
-
|
|
21050
|
-
|
|
21051
|
-
|
|
21052
|
-
|
|
21053
|
-
|
|
21054
|
-
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
|
|
21059
|
-
|
|
21060
|
-
iteration: iteration + 1,
|
|
21061
|
-
templateId: renderedPrompt.templateId,
|
|
21062
|
-
templateVersion: renderedPrompt.templateVersion,
|
|
21063
|
-
title: iteration === 0 ? "Generating agent response" : "Generating continuation",
|
|
21064
|
-
message: request
|
|
21065
|
-
});
|
|
21066
|
-
const emittedGeneratedReasoningLines = /* @__PURE__ */ new Set();
|
|
21067
|
-
let generatedReasoningBuffer = "";
|
|
21068
|
-
const emitGeneratedReasoningLine = async (line) => {
|
|
21069
|
-
if (emittedGeneratedReasoningLines.has(line)) return;
|
|
21070
|
-
emittedGeneratedReasoningLines.add(line);
|
|
21296
|
+
title: "Rendered harness prompt",
|
|
21297
|
+
message: `${systemPrompt.split("\n").length} lines`,
|
|
21298
|
+
data: {
|
|
21299
|
+
templateId: renderedPrompt.templateId,
|
|
21300
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21301
|
+
templateHash: renderedPrompt.templateHash,
|
|
21302
|
+
promptInstanceHash: renderedPrompt.promptInstanceHash,
|
|
21303
|
+
prompt: systemPrompt
|
|
21304
|
+
}
|
|
21305
|
+
});
|
|
21306
|
+
const request = iteration === 0 ? input.request : continuationRenderer(
|
|
21307
|
+
buildContinuationPreview(latestCheckpoint, noProgressCount)
|
|
21308
|
+
).instruction;
|
|
21071
21309
|
await emitProgress(onProgress, {
|
|
21072
21310
|
phase: "generation",
|
|
21073
21311
|
status: "running",
|
|
@@ -21076,190 +21314,231 @@ function createAgentEvalHarness(options) {
|
|
|
21076
21314
|
iteration: iteration + 1,
|
|
21077
21315
|
templateId: renderedPrompt.templateId,
|
|
21078
21316
|
templateVersion: renderedPrompt.templateVersion,
|
|
21079
|
-
title: "
|
|
21080
|
-
message:
|
|
21081
|
-
data: { source: "generated_code_comment" }
|
|
21317
|
+
title: iteration === 0 ? "Generating agent response" : "Generating continuation",
|
|
21318
|
+
message: request
|
|
21082
21319
|
});
|
|
21083
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
21086
|
-
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
|
|
21090
|
-
|
|
21091
|
-
|
|
21092
|
-
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
title: "Generated text reply delta",
|
|
21101
|
-
message: delta,
|
|
21102
|
-
data: { delta }
|
|
21103
|
-
});
|
|
21104
|
-
},
|
|
21105
|
-
onCodeDelta: async (delta) => {
|
|
21106
|
-
const parsed = consumeGranularReasoningOnlyChunk(
|
|
21107
|
-
generatedReasoningBuffer,
|
|
21108
|
-
delta
|
|
21109
|
-
);
|
|
21110
|
-
generatedReasoningBuffer = parsed.buffer;
|
|
21111
|
-
for (const line of parsed.reasoningLines) {
|
|
21112
|
-
await emitGeneratedReasoningLine(line);
|
|
21113
|
-
}
|
|
21114
|
-
},
|
|
21115
|
-
usageContext: {
|
|
21116
|
-
sandboxId: conversation.environment.sandboxId,
|
|
21117
|
-
environmentId: conversation.environment.environmentId,
|
|
21118
|
-
sessionId: conversation.environment.sessionId,
|
|
21119
|
-
subjectId: conversation.environment.subjectId,
|
|
21120
|
-
permissionProfileId: conversation.environment.permissionProfileId
|
|
21121
|
-
}
|
|
21122
|
-
}),
|
|
21123
|
-
chatTimeoutMs,
|
|
21124
|
-
`chat generation for ${conversation.label} iteration ${iteration + 1}`
|
|
21125
|
-
);
|
|
21126
|
-
await emitProgress(onProgress, {
|
|
21127
|
-
phase: "generation",
|
|
21128
|
-
status: "passed",
|
|
21129
|
-
scenarioId: conversation.label,
|
|
21130
|
-
stepId: turnId,
|
|
21131
|
-
iteration: iteration + 1,
|
|
21132
|
-
templateId: renderedPrompt.templateId,
|
|
21133
|
-
templateVersion: renderedPrompt.templateVersion,
|
|
21134
|
-
title: generation.code ? "Generated job code" : "Generated text reply",
|
|
21135
|
-
message: generation.code || generation.reply || "",
|
|
21136
|
-
data: {
|
|
21137
|
-
reply: generation.reply,
|
|
21138
|
-
code: generation.code,
|
|
21139
|
-
attempts: generation.generationAttempts,
|
|
21140
|
-
usage: tokenUsageForGenerationOutput(generation)
|
|
21141
|
-
}
|
|
21142
|
-
});
|
|
21143
|
-
const generatedReasoningLines = generation.code ? consumeGranularReasoningOnlyChunk("", generation.code, {
|
|
21144
|
-
final: true
|
|
21145
|
-
}).reasoningLines : [];
|
|
21146
|
-
for (const line of generatedReasoningLines) {
|
|
21147
|
-
await emitGeneratedReasoningLine(line);
|
|
21148
|
-
}
|
|
21149
|
-
const iterationLog = {
|
|
21150
|
-
iteration: iteration + 1,
|
|
21151
|
-
request,
|
|
21152
|
-
systemPrompt,
|
|
21153
|
-
templateId: renderedPrompt.templateId,
|
|
21154
|
-
templateVersion: renderedPrompt.templateVersion,
|
|
21155
|
-
templateHash: renderedPrompt.templateHash,
|
|
21156
|
-
promptInstanceHash: renderedPrompt.promptInstanceHash,
|
|
21157
|
-
generationReply: generation.reply,
|
|
21158
|
-
generatedCode: generation.code,
|
|
21159
|
-
rawGeneration: generation.raw,
|
|
21160
|
-
generationAttempts: generation.generationAttempts,
|
|
21161
|
-
tokenUsage: tokenUsageForGenerationOutput(generation)
|
|
21162
|
-
};
|
|
21163
|
-
turnLog.iterations.push(iterationLog);
|
|
21164
|
-
await writeJson(
|
|
21165
|
-
path__default.default.join(turnDir, `iteration-${iteration + 1}-generation.json`),
|
|
21166
|
-
generation
|
|
21167
|
-
);
|
|
21168
|
-
if (!generation.code) {
|
|
21169
|
-
const responseText2 = generation.reply?.trim() || "Done.";
|
|
21170
|
-
conversation.history.push({ role: "assistant", content: responseText2 });
|
|
21171
|
-
const completed = {
|
|
21172
|
-
conversation,
|
|
21173
|
-
request: input.request,
|
|
21174
|
-
turnDir,
|
|
21175
|
-
responseText: responseText2,
|
|
21176
|
-
terminalKind: "reply",
|
|
21177
|
-
actionSummary: [],
|
|
21178
|
-
promptInteractions: [],
|
|
21179
|
-
verification: null,
|
|
21180
|
-
result: generation.reply?.trim() || responseText2
|
|
21181
|
-
};
|
|
21182
|
-
if (input.verification) {
|
|
21183
|
-
completed.verification = await runInspection(
|
|
21184
|
-
conversation,
|
|
21185
|
-
input.verification,
|
|
21186
|
-
completed,
|
|
21187
|
-
turnDir
|
|
21188
|
-
);
|
|
21189
|
-
}
|
|
21190
|
-
iterationLog.responseText = responseText2;
|
|
21191
|
-
iterationLog.terminalKind = "reply";
|
|
21192
|
-
iterationLog.actionSummary = [];
|
|
21193
|
-
iterationLog.promptInteractions = [];
|
|
21194
|
-
iterationLog.result = completed.result;
|
|
21195
|
-
turnLog.completed = {
|
|
21196
|
-
responseText: responseText2,
|
|
21197
|
-
terminalKind: "reply",
|
|
21198
|
-
actionSummary: [],
|
|
21199
|
-
promptInteractions: [],
|
|
21200
|
-
result: completed.result
|
|
21320
|
+
const emittedGeneratedReasoningLines = /* @__PURE__ */ new Set();
|
|
21321
|
+
let generatedReasoningBuffer = "";
|
|
21322
|
+
const emitGeneratedReasoningLine = async (line) => {
|
|
21323
|
+
if (emittedGeneratedReasoningLines.has(line)) return;
|
|
21324
|
+
emittedGeneratedReasoningLines.add(line);
|
|
21325
|
+
await emitProgress(onProgress, {
|
|
21326
|
+
phase: "generation",
|
|
21327
|
+
status: "running",
|
|
21328
|
+
scenarioId: conversation.label,
|
|
21329
|
+
stepId: turnId,
|
|
21330
|
+
iteration: iteration + 1,
|
|
21331
|
+
templateId: renderedPrompt.templateId,
|
|
21332
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21333
|
+
title: "Generated reasoning comment",
|
|
21334
|
+
message: line,
|
|
21335
|
+
data: { source: "generated_code_comment" }
|
|
21336
|
+
});
|
|
21201
21337
|
};
|
|
21202
|
-
|
|
21338
|
+
const generationStartedAt = Date.now();
|
|
21339
|
+
const generation = await withTimeout2(
|
|
21340
|
+
generateTurnWithRepair(options.generator, {
|
|
21341
|
+
systemPrompt,
|
|
21342
|
+
history: buildHistory(conversation.history),
|
|
21343
|
+
request,
|
|
21344
|
+
attempt: 1,
|
|
21345
|
+
tools,
|
|
21346
|
+
onReplyDelta: async (delta) => {
|
|
21347
|
+
await emitProgress(onProgress, {
|
|
21348
|
+
phase: "generation",
|
|
21349
|
+
status: "running",
|
|
21350
|
+
scenarioId: conversation.label,
|
|
21351
|
+
stepId: turnId,
|
|
21352
|
+
iteration: iteration + 1,
|
|
21353
|
+
templateId: renderedPrompt.templateId,
|
|
21354
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21355
|
+
title: "Generated text reply delta",
|
|
21356
|
+
message: delta,
|
|
21357
|
+
data: { delta }
|
|
21358
|
+
});
|
|
21359
|
+
},
|
|
21360
|
+
onCodeDelta: async (delta) => {
|
|
21361
|
+
const parsed = consumeGranularReasoningOnlyChunk(
|
|
21362
|
+
generatedReasoningBuffer,
|
|
21363
|
+
delta
|
|
21364
|
+
);
|
|
21365
|
+
generatedReasoningBuffer = parsed.buffer;
|
|
21366
|
+
for (const line of parsed.reasoningLines) {
|
|
21367
|
+
await emitGeneratedReasoningLine(line);
|
|
21368
|
+
}
|
|
21369
|
+
},
|
|
21370
|
+
usageContext: {
|
|
21371
|
+
sandboxId: conversation.environment.sandboxId,
|
|
21372
|
+
environmentId: conversation.environment.environmentId,
|
|
21373
|
+
sessionId: conversation.environment.sessionId,
|
|
21374
|
+
subjectId: conversation.environment.subjectId,
|
|
21375
|
+
permissionProfileId: conversation.environment.permissionProfileId
|
|
21376
|
+
}
|
|
21377
|
+
}),
|
|
21378
|
+
chatTimeoutMs,
|
|
21379
|
+
`chat generation for ${conversation.label} iteration ${iteration + 1}`
|
|
21380
|
+
);
|
|
21381
|
+
const generationDurationMs = Date.now() - generationStartedAt;
|
|
21203
21382
|
await emitProgress(onProgress, {
|
|
21204
|
-
phase: "
|
|
21383
|
+
phase: "generation",
|
|
21205
21384
|
status: "passed",
|
|
21206
21385
|
scenarioId: conversation.label,
|
|
21207
21386
|
stepId: turnId,
|
|
21208
|
-
|
|
21209
|
-
|
|
21210
|
-
|
|
21387
|
+
iteration: iteration + 1,
|
|
21388
|
+
templateId: renderedPrompt.templateId,
|
|
21389
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21390
|
+
title: generation.code ? "Generated job code" : "Generated text reply",
|
|
21391
|
+
message: generation.code || generation.reply || "",
|
|
21392
|
+
data: {
|
|
21393
|
+
reply: generation.reply,
|
|
21394
|
+
code: generation.code,
|
|
21395
|
+
attempts: generation.generationAttempts,
|
|
21396
|
+
usage: tokenUsageForGenerationOutput(generation)
|
|
21397
|
+
}
|
|
21211
21398
|
});
|
|
21212
|
-
|
|
21213
|
-
|
|
21214
|
-
|
|
21215
|
-
|
|
21216
|
-
|
|
21217
|
-
|
|
21218
|
-
|
|
21219
|
-
systemPrompt,
|
|
21220
|
-
history: buildHistory(conversation.history),
|
|
21221
|
-
scenarioLabel: conversation.label,
|
|
21222
|
-
turnId,
|
|
21399
|
+
const generatedReasoningLines = generation.code ? consumeGranularReasoningOnlyChunk("", generation.code, {
|
|
21400
|
+
final: true
|
|
21401
|
+
}).reasoningLines : [];
|
|
21402
|
+
for (const line of generatedReasoningLines) {
|
|
21403
|
+
await emitGeneratedReasoningLine(line);
|
|
21404
|
+
}
|
|
21405
|
+
const iterationLog = {
|
|
21223
21406
|
iteration: iteration + 1,
|
|
21224
|
-
|
|
21407
|
+
request,
|
|
21408
|
+
generationDurationMs,
|
|
21409
|
+
systemPrompt,
|
|
21410
|
+
templateId: renderedPrompt.templateId,
|
|
21411
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21412
|
+
templateHash: renderedPrompt.templateHash,
|
|
21413
|
+
promptInstanceHash: renderedPrompt.promptInstanceHash,
|
|
21225
21414
|
generationReply: generation.reply,
|
|
21415
|
+
generatedCode: generation.code,
|
|
21226
21416
|
rawGeneration: generation.raw,
|
|
21227
|
-
|
|
21228
|
-
|
|
21229
|
-
|
|
21230
|
-
|
|
21231
|
-
|
|
21232
|
-
|
|
21233
|
-
|
|
21234
|
-
|
|
21235
|
-
|
|
21236
|
-
|
|
21237
|
-
|
|
21238
|
-
|
|
21239
|
-
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
|
|
21243
|
-
|
|
21244
|
-
|
|
21245
|
-
|
|
21246
|
-
|
|
21247
|
-
|
|
21248
|
-
|
|
21249
|
-
|
|
21250
|
-
|
|
21251
|
-
|
|
21252
|
-
|
|
21417
|
+
generationAttempts: generation.generationAttempts,
|
|
21418
|
+
tokenUsage: tokenUsageForGenerationOutput(generation)
|
|
21419
|
+
};
|
|
21420
|
+
turnLog.iterations.push(iterationLog);
|
|
21421
|
+
await writeJson(
|
|
21422
|
+
path__default.default.join(turnDir, `iteration-${iteration + 1}-generation.json`),
|
|
21423
|
+
generation
|
|
21424
|
+
);
|
|
21425
|
+
if (!generation.code) {
|
|
21426
|
+
const responseText2 = generation.reply?.trim() || "Done.";
|
|
21427
|
+
conversation.history.push({ role: "assistant", content: responseText2 });
|
|
21428
|
+
const completed = {
|
|
21429
|
+
conversation,
|
|
21430
|
+
request: input.request,
|
|
21431
|
+
turnDir,
|
|
21432
|
+
responseText: responseText2,
|
|
21433
|
+
terminalKind: "reply",
|
|
21434
|
+
actionSummary: [],
|
|
21435
|
+
promptInteractions: [],
|
|
21436
|
+
verification: null,
|
|
21437
|
+
result: generation.reply?.trim() || responseText2
|
|
21438
|
+
};
|
|
21439
|
+
if (input.verification) {
|
|
21440
|
+
completed.verification = await runInspection(
|
|
21441
|
+
conversation,
|
|
21442
|
+
input.verification,
|
|
21443
|
+
completed,
|
|
21444
|
+
turnDir
|
|
21445
|
+
);
|
|
21446
|
+
}
|
|
21447
|
+
iterationLog.responseText = responseText2;
|
|
21448
|
+
iterationLog.terminalKind = "reply";
|
|
21449
|
+
iterationLog.actionSummary = [];
|
|
21450
|
+
iterationLog.promptInteractions = [];
|
|
21451
|
+
iterationLog.result = completed.result;
|
|
21452
|
+
turnLog.completed = {
|
|
21453
|
+
responseText: responseText2,
|
|
21454
|
+
terminalKind: "reply",
|
|
21455
|
+
actionSummary: [],
|
|
21456
|
+
promptInteractions: [],
|
|
21457
|
+
result: completed.result
|
|
21458
|
+
};
|
|
21459
|
+
await writeJson(path__default.default.join(turnDir, "result.json"), completed);
|
|
21460
|
+
await writeTurnReport({ type: "completed", completed });
|
|
21461
|
+
await emitProgress(onProgress, {
|
|
21462
|
+
phase: "step",
|
|
21463
|
+
status: "passed",
|
|
21464
|
+
scenarioId: conversation.label,
|
|
21465
|
+
stepId: turnId,
|
|
21466
|
+
title: "Step completed with text reply",
|
|
21467
|
+
message: responseText2,
|
|
21468
|
+
data: completed
|
|
21469
|
+
});
|
|
21470
|
+
return completed;
|
|
21471
|
+
}
|
|
21472
|
+
const session = conversation.environment;
|
|
21473
|
+
const job = await session.submitJob(generation.code, {
|
|
21474
|
+
agent: {
|
|
21475
|
+
userRequest: input.request,
|
|
21476
|
+
generationRequest: request,
|
|
21477
|
+
systemPrompt,
|
|
21478
|
+
history: buildHistory(conversation.history),
|
|
21479
|
+
scenarioLabel: conversation.label,
|
|
21480
|
+
turnId,
|
|
21481
|
+
iteration: iteration + 1,
|
|
21482
|
+
tools,
|
|
21483
|
+
generationReply: generation.reply,
|
|
21484
|
+
rawGeneration: generation.raw,
|
|
21485
|
+
repairIssues: generation.generationAttempts?.flatMap(
|
|
21486
|
+
(attempt) => attempt.repairIssues || []
|
|
21487
|
+
)
|
|
21488
|
+
}
|
|
21489
|
+
});
|
|
21490
|
+
await emitProgress(onProgress, {
|
|
21491
|
+
phase: "job",
|
|
21492
|
+
status: "running",
|
|
21253
21493
|
scenarioId: conversation.label,
|
|
21254
21494
|
stepId: turnId,
|
|
21255
21495
|
iteration: iteration + 1,
|
|
21496
|
+
jobId: job.id,
|
|
21256
21497
|
templateId: renderedPrompt.templateId,
|
|
21257
|
-
templateVersion: renderedPrompt.templateVersion
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21498
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21499
|
+
title: "Submitted Granular job",
|
|
21500
|
+
message: job.id,
|
|
21501
|
+
data: { code: generation.code }
|
|
21502
|
+
});
|
|
21503
|
+
const outcome = await waitForJobOutcome({
|
|
21504
|
+
environment: conversation.environment,
|
|
21505
|
+
job,
|
|
21506
|
+
boundaryTimestamp,
|
|
21507
|
+
timeoutMs: jobTimeoutMs,
|
|
21508
|
+
pollIntervalMs,
|
|
21509
|
+
onProgress: (event) => void onProgress?.(event),
|
|
21510
|
+
progressContext: {
|
|
21511
|
+
scenarioId: conversation.label,
|
|
21512
|
+
stepId: turnId,
|
|
21513
|
+
iteration: iteration + 1,
|
|
21514
|
+
templateId: renderedPrompt.templateId,
|
|
21515
|
+
templateVersion: renderedPrompt.templateVersion
|
|
21516
|
+
}
|
|
21517
|
+
});
|
|
21518
|
+
if (outcome.kind === "prompt") {
|
|
21519
|
+
if (!autoAnswerPrompts) {
|
|
21520
|
+
const pending2 = {
|
|
21521
|
+
conversation,
|
|
21522
|
+
request: input.request,
|
|
21523
|
+
turnDir,
|
|
21524
|
+
boundaryTimestamp,
|
|
21525
|
+
finalCode: generation.code,
|
|
21526
|
+
finalReply: generation.reply?.trim() || "",
|
|
21527
|
+
stdout: outcome.stdout,
|
|
21528
|
+
stderr: outcome.stderr,
|
|
21529
|
+
prompts: outcome.prompts,
|
|
21530
|
+
promptInteractions: [],
|
|
21531
|
+
job
|
|
21532
|
+
};
|
|
21533
|
+
await writeTurnReport({ type: "pending", pending: pending2 });
|
|
21534
|
+
return pending2;
|
|
21535
|
+
}
|
|
21536
|
+
if (!input.human) {
|
|
21537
|
+
throw new Error(
|
|
21538
|
+
"This turn reached a human prompt but no responder was provided"
|
|
21539
|
+
);
|
|
21540
|
+
}
|
|
21541
|
+
let pending = {
|
|
21263
21542
|
conversation,
|
|
21264
21543
|
request: input.request,
|
|
21265
21544
|
turnDir,
|
|
@@ -21272,187 +21551,180 @@ function createAgentEvalHarness(options) {
|
|
|
21272
21551
|
promptInteractions: [],
|
|
21273
21552
|
job
|
|
21274
21553
|
};
|
|
21554
|
+
while ("prompts" in pending) {
|
|
21555
|
+
const resumed = await resumePendingTurn(pending, input.human);
|
|
21556
|
+
if ("prompts" in resumed) {
|
|
21557
|
+
pending = resumed;
|
|
21558
|
+
continue;
|
|
21559
|
+
}
|
|
21560
|
+
if (input.verification) {
|
|
21561
|
+
resumed.verification = await runInspection(
|
|
21562
|
+
conversation,
|
|
21563
|
+
input.verification,
|
|
21564
|
+
resumed,
|
|
21565
|
+
turnDir
|
|
21566
|
+
);
|
|
21567
|
+
}
|
|
21568
|
+
turnLog.completed = {
|
|
21569
|
+
responseText: resumed.responseText,
|
|
21570
|
+
terminalKind: resumed.terminalKind,
|
|
21571
|
+
actionSummary: resumed.actionSummary,
|
|
21572
|
+
promptInteractions: resumed.promptInteractions,
|
|
21573
|
+
result: resumed.result
|
|
21574
|
+
};
|
|
21575
|
+
await writeTurnReport({ type: "completed", completed: resumed });
|
|
21576
|
+
return resumed;
|
|
21577
|
+
}
|
|
21275
21578
|
}
|
|
21276
|
-
if (
|
|
21579
|
+
if (outcome.kind !== "completed") {
|
|
21277
21580
|
throw new Error(
|
|
21278
|
-
"
|
|
21581
|
+
"Unexpected non-completed outcome after prompt handling"
|
|
21279
21582
|
);
|
|
21280
21583
|
}
|
|
21281
|
-
|
|
21282
|
-
|
|
21283
|
-
|
|
21284
|
-
|
|
21285
|
-
|
|
21286
|
-
|
|
21287
|
-
|
|
21584
|
+
await sleep2(350);
|
|
21585
|
+
const settledLiveDoc = cloneJson(
|
|
21586
|
+
conversation.environment.document
|
|
21587
|
+
);
|
|
21588
|
+
const sessionHeap = normalizeHeapSnapshot2(asRecord6(settledLiveDoc?.heap));
|
|
21589
|
+
const presentation = resolveJobPresentation({
|
|
21590
|
+
jobId: job.id,
|
|
21591
|
+
result: outcome.result,
|
|
21288
21592
|
stdout: outcome.stdout,
|
|
21289
|
-
|
|
21290
|
-
|
|
21291
|
-
|
|
21292
|
-
|
|
21593
|
+
agentMessages: getJobAgentMessages(settledLiveDoc, job.id),
|
|
21594
|
+
sessionHeap
|
|
21595
|
+
});
|
|
21596
|
+
const responseText = presentation.responseText || generation.reply?.trim() || "Done.";
|
|
21597
|
+
const verifierSnapshot = createHarnessVerifierSnapshot({
|
|
21598
|
+
finalCode: generation.code,
|
|
21599
|
+
resultPreview: JSON.stringify(outcome.result, null, 2),
|
|
21600
|
+
liveDoc: settledLiveDoc,
|
|
21601
|
+
projectionOptions: { boundaryTimestamp }
|
|
21602
|
+
});
|
|
21603
|
+
const continuation = evaluateContinuation({
|
|
21604
|
+
iteration,
|
|
21605
|
+
budgets: controllerBudgets,
|
|
21606
|
+
baselineClosureId,
|
|
21607
|
+
currentClosureId: getCurrentClosureId(settledLiveDoc),
|
|
21608
|
+
liveDoc: settledLiveDoc,
|
|
21609
|
+
pendingPrompts: filterPromptsByBoundary(
|
|
21610
|
+
settledLiveDoc,
|
|
21611
|
+
getOpenPromptsFromDoc(settledLiveDoc),
|
|
21612
|
+
boundaryTimestamp
|
|
21613
|
+
),
|
|
21614
|
+
projectionOptions: { boundaryTimestamp },
|
|
21615
|
+
latestResponseText: responseText,
|
|
21616
|
+
previousSnapshot,
|
|
21617
|
+
currentSnapshot: verifierSnapshot,
|
|
21618
|
+
previousNoProgressCount: noProgressCount
|
|
21619
|
+
});
|
|
21620
|
+
latestCheckpoint = {
|
|
21621
|
+
iteration: iteration + 1,
|
|
21622
|
+
latestJobStatus: "succeeded",
|
|
21623
|
+
latestJobResult: JSON.stringify(outcome.result, null, 2),
|
|
21624
|
+
latestActionSummary: getActionSummary(settledLiveDoc, job.id),
|
|
21625
|
+
controllerOutcome: continuation.outcome,
|
|
21626
|
+
controllerReason: continuation.reason,
|
|
21627
|
+
noProgressCount: continuation.nextNoProgressCount
|
|
21293
21628
|
};
|
|
21294
|
-
|
|
21295
|
-
|
|
21296
|
-
|
|
21297
|
-
|
|
21298
|
-
|
|
21629
|
+
await emitProgress(onProgress, {
|
|
21630
|
+
phase: "continuation",
|
|
21631
|
+
status: continuation.shouldContinue ? "running" : "passed",
|
|
21632
|
+
scenarioId: conversation.label,
|
|
21633
|
+
stepId: turnId,
|
|
21634
|
+
iteration: iteration + 1,
|
|
21635
|
+
jobId: job.id,
|
|
21636
|
+
templateId: renderedPrompt.templateId,
|
|
21637
|
+
templateVersion: renderedPrompt.templateVersion,
|
|
21638
|
+
title: continuation.shouldContinue ? "Harness requested another loop" : "Harness accepted completion",
|
|
21639
|
+
message: `${continuation.reason}; ${continuation.outcome}`,
|
|
21640
|
+
data: {
|
|
21641
|
+
continuation,
|
|
21642
|
+
checkpoint: latestCheckpoint,
|
|
21643
|
+
verifierSnapshot
|
|
21644
|
+
}
|
|
21645
|
+
});
|
|
21646
|
+
previousSnapshot = verifierSnapshot;
|
|
21647
|
+
noProgressCount = continuation.nextNoProgressCount;
|
|
21648
|
+
conversation.history.push({
|
|
21649
|
+
role: "assistant",
|
|
21650
|
+
content: responseText,
|
|
21651
|
+
code: generation.code,
|
|
21652
|
+
jobStatus: "succeeded",
|
|
21653
|
+
jobResultPreview: JSON.stringify(outcome.result, null, 2)
|
|
21654
|
+
});
|
|
21655
|
+
await writeJson(
|
|
21656
|
+
path__default.default.join(turnDir, `iteration-${iteration + 1}-result.json`),
|
|
21657
|
+
{
|
|
21658
|
+
responseText,
|
|
21659
|
+
continuation,
|
|
21660
|
+
actionSummary: latestCheckpoint.latestActionSummary,
|
|
21661
|
+
result: outcome.result
|
|
21299
21662
|
}
|
|
21663
|
+
);
|
|
21664
|
+
iterationLog.responseText = responseText;
|
|
21665
|
+
iterationLog.terminalKind = getCurrentClosureId(settledLiveDoc) ? "closure" : "reply";
|
|
21666
|
+
iterationLog.actionSummary = latestCheckpoint.latestActionSummary || [];
|
|
21667
|
+
iterationLog.promptInteractions = [];
|
|
21668
|
+
iterationLog.continuation = continuation;
|
|
21669
|
+
iterationLog.result = outcome.result;
|
|
21670
|
+
if (!continuation.shouldContinue) {
|
|
21671
|
+
const completed = {
|
|
21672
|
+
conversation,
|
|
21673
|
+
request: input.request,
|
|
21674
|
+
turnDir,
|
|
21675
|
+
responseText,
|
|
21676
|
+
terminalKind: getCurrentClosureId(settledLiveDoc) ? "closure" : "reply",
|
|
21677
|
+
finalCode: generation.code,
|
|
21678
|
+
actionSummary: latestCheckpoint.latestActionSummary || [],
|
|
21679
|
+
promptInteractions: [],
|
|
21680
|
+
verification: null,
|
|
21681
|
+
result: outcome.result
|
|
21682
|
+
};
|
|
21300
21683
|
if (input.verification) {
|
|
21301
|
-
|
|
21684
|
+
completed.verification = await runInspection(
|
|
21302
21685
|
conversation,
|
|
21303
21686
|
input.verification,
|
|
21304
|
-
|
|
21687
|
+
completed,
|
|
21305
21688
|
turnDir
|
|
21306
21689
|
);
|
|
21307
21690
|
}
|
|
21308
21691
|
turnLog.completed = {
|
|
21309
|
-
responseText
|
|
21310
|
-
terminalKind:
|
|
21311
|
-
actionSummary:
|
|
21312
|
-
promptInteractions:
|
|
21313
|
-
result:
|
|
21692
|
+
responseText,
|
|
21693
|
+
terminalKind: completed.terminalKind,
|
|
21694
|
+
actionSummary: completed.actionSummary,
|
|
21695
|
+
promptInteractions: [],
|
|
21696
|
+
result: outcome.result
|
|
21314
21697
|
};
|
|
21315
|
-
|
|
21698
|
+
await writeJson(path__default.default.join(turnDir, "result.json"), completed);
|
|
21699
|
+
await writeTurnReport({ type: "completed", completed });
|
|
21700
|
+
await emitProgress(onProgress, {
|
|
21701
|
+
phase: "step",
|
|
21702
|
+
status: "passed",
|
|
21703
|
+
scenarioId: conversation.label,
|
|
21704
|
+
stepId: turnId,
|
|
21705
|
+
iteration: iteration + 1,
|
|
21706
|
+
jobId: job.id,
|
|
21707
|
+
title: "Step completed",
|
|
21708
|
+
message: responseText,
|
|
21709
|
+
data: completed
|
|
21710
|
+
});
|
|
21711
|
+
return completed;
|
|
21316
21712
|
}
|
|
21713
|
+
iteration += 1;
|
|
21317
21714
|
}
|
|
21318
|
-
|
|
21319
|
-
|
|
21320
|
-
"Unexpected non-completed outcome after prompt handling"
|
|
21321
|
-
);
|
|
21322
|
-
}
|
|
21323
|
-
await sleep2(350);
|
|
21324
|
-
const settledLiveDoc = cloneJson(
|
|
21325
|
-
conversation.environment.document
|
|
21326
|
-
);
|
|
21327
|
-
const sessionHeap = normalizeHeapSnapshot2(asRecord6(settledLiveDoc?.heap));
|
|
21328
|
-
const presentation = resolveJobPresentation({
|
|
21329
|
-
jobId: job.id,
|
|
21330
|
-
result: outcome.result,
|
|
21331
|
-
stdout: outcome.stdout,
|
|
21332
|
-
agentMessages: getJobAgentMessages(settledLiveDoc, job.id),
|
|
21333
|
-
sessionHeap
|
|
21334
|
-
});
|
|
21335
|
-
const responseText = presentation.responseText || generation.reply?.trim() || "Done.";
|
|
21336
|
-
const verifierSnapshot = createHarnessVerifierSnapshot({
|
|
21337
|
-
finalCode: generation.code,
|
|
21338
|
-
resultPreview: JSON.stringify(outcome.result, null, 2),
|
|
21339
|
-
liveDoc: settledLiveDoc,
|
|
21340
|
-
projectionOptions: { boundaryTimestamp }
|
|
21341
|
-
});
|
|
21342
|
-
const continuation = evaluateContinuation({
|
|
21343
|
-
iteration,
|
|
21344
|
-
budgets: controllerBudgets,
|
|
21345
|
-
baselineClosureId,
|
|
21346
|
-
currentClosureId: getCurrentClosureId(settledLiveDoc),
|
|
21347
|
-
liveDoc: settledLiveDoc,
|
|
21348
|
-
pendingPrompts: filterPromptsByBoundary(
|
|
21349
|
-
settledLiveDoc,
|
|
21350
|
-
getOpenPromptsFromDoc(settledLiveDoc),
|
|
21351
|
-
boundaryTimestamp
|
|
21352
|
-
),
|
|
21353
|
-
projectionOptions: { boundaryTimestamp },
|
|
21354
|
-
latestResponseText: responseText,
|
|
21355
|
-
previousSnapshot,
|
|
21356
|
-
currentSnapshot: verifierSnapshot,
|
|
21357
|
-
previousNoProgressCount: noProgressCount
|
|
21358
|
-
});
|
|
21359
|
-
latestCheckpoint = {
|
|
21360
|
-
iteration: iteration + 1,
|
|
21361
|
-
latestJobStatus: "succeeded",
|
|
21362
|
-
latestJobResult: JSON.stringify(outcome.result, null, 2),
|
|
21363
|
-
latestActionSummary: getActionSummary(settledLiveDoc, job.id),
|
|
21364
|
-
controllerOutcome: continuation.outcome,
|
|
21365
|
-
controllerReason: continuation.reason,
|
|
21366
|
-
noProgressCount: continuation.nextNoProgressCount
|
|
21367
|
-
};
|
|
21368
|
-
await emitProgress(onProgress, {
|
|
21369
|
-
phase: "continuation",
|
|
21370
|
-
status: continuation.shouldContinue ? "running" : "passed",
|
|
21371
|
-
scenarioId: conversation.label,
|
|
21372
|
-
stepId: turnId,
|
|
21373
|
-
iteration: iteration + 1,
|
|
21374
|
-
jobId: job.id,
|
|
21375
|
-
templateId: renderedPrompt.templateId,
|
|
21376
|
-
templateVersion: renderedPrompt.templateVersion,
|
|
21377
|
-
title: continuation.shouldContinue ? "Harness requested another loop" : "Harness accepted completion",
|
|
21378
|
-
message: `${continuation.reason}; ${continuation.outcome}`,
|
|
21379
|
-
data: {
|
|
21380
|
-
continuation,
|
|
21381
|
-
checkpoint: latestCheckpoint,
|
|
21382
|
-
verifierSnapshot
|
|
21383
|
-
}
|
|
21384
|
-
});
|
|
21385
|
-
previousSnapshot = verifierSnapshot;
|
|
21386
|
-
noProgressCount = continuation.nextNoProgressCount;
|
|
21387
|
-
conversation.history.push({
|
|
21388
|
-
role: "assistant",
|
|
21389
|
-
content: responseText,
|
|
21390
|
-
code: generation.code,
|
|
21391
|
-
jobStatus: "succeeded",
|
|
21392
|
-
jobResultPreview: JSON.stringify(outcome.result, null, 2)
|
|
21393
|
-
});
|
|
21394
|
-
await writeJson(
|
|
21395
|
-
path__default.default.join(turnDir, `iteration-${iteration + 1}-result.json`),
|
|
21396
|
-
{
|
|
21397
|
-
responseText,
|
|
21398
|
-
continuation,
|
|
21399
|
-
actionSummary: latestCheckpoint.latestActionSummary,
|
|
21400
|
-
result: outcome.result
|
|
21401
|
-
}
|
|
21715
|
+
throw new Error(
|
|
21716
|
+
`Turn exceeded iteration budget (${maxIterations}) for ${conversation.label}`
|
|
21402
21717
|
);
|
|
21403
|
-
|
|
21404
|
-
|
|
21405
|
-
|
|
21406
|
-
|
|
21407
|
-
|
|
21408
|
-
iterationLog.result = outcome.result;
|
|
21409
|
-
if (!continuation.shouldContinue) {
|
|
21410
|
-
const completed = {
|
|
21411
|
-
conversation,
|
|
21412
|
-
request: input.request,
|
|
21413
|
-
turnDir,
|
|
21414
|
-
responseText,
|
|
21415
|
-
terminalKind: getCurrentClosureId(settledLiveDoc) ? "closure" : "reply",
|
|
21416
|
-
finalCode: generation.code,
|
|
21417
|
-
actionSummary: latestCheckpoint.latestActionSummary || [],
|
|
21418
|
-
promptInteractions: [],
|
|
21419
|
-
verification: null,
|
|
21420
|
-
result: outcome.result
|
|
21421
|
-
};
|
|
21422
|
-
if (input.verification) {
|
|
21423
|
-
completed.verification = await runInspection(
|
|
21424
|
-
conversation,
|
|
21425
|
-
input.verification,
|
|
21426
|
-
completed,
|
|
21427
|
-
turnDir
|
|
21428
|
-
);
|
|
21429
|
-
}
|
|
21430
|
-
turnLog.completed = {
|
|
21431
|
-
responseText,
|
|
21432
|
-
terminalKind: completed.terminalKind,
|
|
21433
|
-
actionSummary: completed.actionSummary,
|
|
21434
|
-
promptInteractions: [],
|
|
21435
|
-
result: outcome.result
|
|
21436
|
-
};
|
|
21437
|
-
await writeJson(path__default.default.join(turnDir, "result.json"), completed);
|
|
21438
|
-
await emitProgress(onProgress, {
|
|
21439
|
-
phase: "step",
|
|
21440
|
-
status: "passed",
|
|
21441
|
-
scenarioId: conversation.label,
|
|
21442
|
-
stepId: turnId,
|
|
21443
|
-
iteration: iteration + 1,
|
|
21444
|
-
jobId: job.id,
|
|
21445
|
-
title: "Step completed",
|
|
21446
|
-
message: responseText,
|
|
21447
|
-
data: completed
|
|
21448
|
-
});
|
|
21449
|
-
return completed;
|
|
21718
|
+
} catch (error) {
|
|
21719
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
21720
|
+
const latestIteration = latestIterationLog(turnLog);
|
|
21721
|
+
if (latestIteration) {
|
|
21722
|
+
latestIteration.error = message;
|
|
21450
21723
|
}
|
|
21451
|
-
|
|
21724
|
+
turnLog.error = message;
|
|
21725
|
+
await writeTurnReport({ type: "failed", error: message });
|
|
21726
|
+
throw error;
|
|
21452
21727
|
}
|
|
21453
|
-
throw new Error(
|
|
21454
|
-
`Turn exceeded iteration budget (${maxIterations}) for ${conversation.label}`
|
|
21455
|
-
);
|
|
21456
21728
|
}
|
|
21457
21729
|
return {
|
|
21458
21730
|
artifactDir,
|
|
@@ -21487,6 +21759,7 @@ function createAgentTester(options) {
|
|
|
21487
21759
|
const harness = createAgentEvalHarness({
|
|
21488
21760
|
granular,
|
|
21489
21761
|
environmentId: resolvedEnvironmentId || void 0,
|
|
21762
|
+
local: options.local,
|
|
21490
21763
|
openEnvironment: async ({ clientId }) => {
|
|
21491
21764
|
if (resolvedEnvironmentId) {
|
|
21492
21765
|
return granular.createSession({
|