@kodelyth/codex 2026.5.42 → 2026.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +16 -1
- package/doctor-contract-api.test.ts +0 -44
- package/doctor-contract-api.ts +0 -68
- package/harness.ts +0 -72
- package/index.test.ts +0 -230
- package/index.ts +0 -66
- package/media-understanding-provider.test.ts +0 -486
- package/media-understanding-provider.ts +0 -521
- package/prompt-overlay-runtime-contract.test.ts +0 -48
- package/prompt-overlay.ts +0 -21
- package/provider-catalog.ts +0 -83
- package/provider-discovery.ts +0 -45
- package/provider.test.ts +0 -384
- package/provider.ts +0 -243
- package/src/app-server/app-inventory-cache.test.ts +0 -176
- package/src/app-server/app-inventory-cache.ts +0 -324
- package/src/app-server/approval-bridge.test.ts +0 -1471
- package/src/app-server/approval-bridge.ts +0 -1211
- package/src/app-server/auth-bridge.test.ts +0 -1449
- package/src/app-server/auth-bridge.ts +0 -614
- package/src/app-server/auth-profile-runtime-contract.test.ts +0 -239
- package/src/app-server/capabilities.ts +0 -27
- package/src/app-server/client-factory.ts +0 -24
- package/src/app-server/client.test.ts +0 -563
- package/src/app-server/client.ts +0 -715
- package/src/app-server/compact.test.ts +0 -710
- package/src/app-server/compact.ts +0 -500
- package/src/app-server/computer-use.test.ts +0 -788
- package/src/app-server/computer-use.ts +0 -683
- package/src/app-server/config.test.ts +0 -879
- package/src/app-server/config.ts +0 -1038
- package/src/app-server/context-engine-projection.test.ts +0 -252
- package/src/app-server/context-engine-projection.ts +0 -403
- package/src/app-server/delivery-no-reply-runtime-contract.test.ts +0 -80
- package/src/app-server/dynamic-tool-diagnostics.ts +0 -73
- package/src/app-server/dynamic-tool-profile.ts +0 -69
- package/src/app-server/dynamic-tools.test.ts +0 -1302
- package/src/app-server/dynamic-tools.ts +0 -623
- package/src/app-server/elicitation-bridge.test.ts +0 -1056
- package/src/app-server/elicitation-bridge.ts +0 -783
- package/src/app-server/event-projector.test.ts +0 -2668
- package/src/app-server/event-projector.ts +0 -2057
- package/src/app-server/image-payload-sanitizer.test.ts +0 -49
- package/src/app-server/image-payload-sanitizer.ts +0 -167
- package/src/app-server/klaw-owned-tool-runtime-contract.test.ts +0 -456
- package/src/app-server/local-runtime-attribution.ts +0 -39
- package/src/app-server/managed-binary.test.ts +0 -139
- package/src/app-server/managed-binary.ts +0 -193
- package/src/app-server/models.test.ts +0 -246
- package/src/app-server/models.ts +0 -172
- package/src/app-server/native-hook-relay.test.ts +0 -271
- package/src/app-server/native-hook-relay.ts +0 -150
- package/src/app-server/native-subagent-task-mirror.test.ts +0 -573
- package/src/app-server/native-subagent-task-mirror.ts +0 -497
- package/src/app-server/outcome-fallback-runtime-contract.test.ts +0 -404
- package/src/app-server/plugin-activation.test.ts +0 -336
- package/src/app-server/plugin-activation.ts +0 -283
- package/src/app-server/plugin-app-cache-key.ts +0 -74
- package/src/app-server/plugin-approval-roundtrip.ts +0 -122
- package/src/app-server/plugin-inventory.test.ts +0 -355
- package/src/app-server/plugin-inventory.ts +0 -357
- package/src/app-server/plugin-thread-config.test.ts +0 -865
- package/src/app-server/plugin-thread-config.ts +0 -455
- package/src/app-server/protocol-generated/json/DynamicToolCallParams.json +0 -33
- package/src/app-server/protocol-generated/json/v2/ErrorNotification.json +0 -199
- package/src/app-server/protocol-generated/json/v2/GetAccountResponse.json +0 -102
- package/src/app-server/protocol-generated/json/v2/ModelListResponse.json +0 -227
- package/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json +0 -2630
- package/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json +0 -2630
- package/src/app-server/protocol-generated/json/v2/TurnCompletedNotification.json +0 -1659
- package/src/app-server/protocol-generated/json/v2/TurnStartResponse.json +0 -1655
- package/src/app-server/protocol-validators.test.ts +0 -75
- package/src/app-server/protocol-validators.ts +0 -203
- package/src/app-server/protocol.ts +0 -520
- package/src/app-server/rate-limit-cache.ts +0 -48
- package/src/app-server/rate-limits.test.ts +0 -202
- package/src/app-server/rate-limits.ts +0 -583
- package/src/app-server/request.ts +0 -73
- package/src/app-server/run-attempt.context-engine.test.ts +0 -1004
- package/src/app-server/run-attempt.test.ts +0 -9477
- package/src/app-server/run-attempt.ts +0 -4683
- package/src/app-server/run-attempt.vision-tools.test.ts +0 -35
- package/src/app-server/schema-normalization-runtime-contract.test.ts +0 -206
- package/src/app-server/session-binding.test.ts +0 -303
- package/src/app-server/session-binding.ts +0 -398
- package/src/app-server/session-history.ts +0 -44
- package/src/app-server/shared-client.test.ts +0 -589
- package/src/app-server/shared-client.ts +0 -289
- package/src/app-server/side-question.test.ts +0 -1175
- package/src/app-server/side-question.ts +0 -1007
- package/src/app-server/test-support.ts +0 -48
- package/src/app-server/thread-lifecycle.test.ts +0 -447
- package/src/app-server/thread-lifecycle.ts +0 -939
- package/src/app-server/thread-lifecycle.user-mcp-servers.test.ts +0 -442
- package/src/app-server/timeout.ts +0 -9
- package/src/app-server/tool-progress-normalization.ts +0 -77
- package/src/app-server/trajectory.test.ts +0 -205
- package/src/app-server/trajectory.ts +0 -365
- package/src/app-server/transcript-mirror.test.ts +0 -524
- package/src/app-server/transcript-mirror.ts +0 -208
- package/src/app-server/transcript-repair-runtime-contract.test.ts +0 -44
- package/src/app-server/transport-stdio.test.ts +0 -171
- package/src/app-server/transport-stdio.ts +0 -107
- package/src/app-server/transport-websocket.test.ts +0 -69
- package/src/app-server/transport-websocket.ts +0 -90
- package/src/app-server/transport.ts +0 -117
- package/src/app-server/user-input-bridge.test.ts +0 -249
- package/src/app-server/user-input-bridge.ts +0 -316
- package/src/app-server/version.ts +0 -4
- package/src/app-server/vision-tools.ts +0 -12
- package/src/command-account.ts +0 -544
- package/src/command-formatters.ts +0 -425
- package/src/command-handlers.ts +0 -2004
- package/src/command-rpc.test.ts +0 -16
- package/src/command-rpc.ts +0 -142
- package/src/commands.test.ts +0 -3312
- package/src/commands.ts +0 -65
- package/src/conversation-binding-data.ts +0 -124
- package/src/conversation-binding.test.ts +0 -599
- package/src/conversation-binding.ts +0 -561
- package/src/conversation-control.test.ts +0 -126
- package/src/conversation-control.ts +0 -303
- package/src/conversation-turn-collector.test.ts +0 -191
- package/src/conversation-turn-collector.ts +0 -186
- package/src/conversation-turn-input.test.ts +0 -141
- package/src/conversation-turn-input.ts +0 -106
- package/src/manifest.test.ts +0 -20
- package/src/migration/apply.ts +0 -501
- package/src/migration/helpers.ts +0 -55
- package/src/migration/plan.ts +0 -461
- package/src/migration/provider.test.ts +0 -1741
- package/src/migration/provider.ts +0 -41
- package/src/migration/source.ts +0 -643
- package/src/migration/targets.ts +0 -25
- package/src/node-cli-sessions.test.ts +0 -180
- package/src/node-cli-sessions.ts +0 -711
- package/test-api.ts +0 -82
- package/tsconfig.json +0 -16
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
5
|
-
import type { EmbeddedRunAttemptParams } from "klaw/plugin-sdk/agent-harness";
|
|
6
|
-
import { classifyEmbeddedPiRunResultForModelFallback } from "klaw/plugin-sdk/agent-harness-runtime";
|
|
7
|
-
import {
|
|
8
|
-
createContractRunResult,
|
|
9
|
-
OUTCOME_FALLBACK_RUNTIME_CONTRACT,
|
|
10
|
-
} from "klaw/plugin-sdk/agent-runtime-test-contracts";
|
|
11
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
12
|
-
import {
|
|
13
|
-
CodexAppServerEventProjector,
|
|
14
|
-
type CodexAppServerToolTelemetry,
|
|
15
|
-
} from "./event-projector.js";
|
|
16
|
-
import { createCodexTestModel } from "./test-support.js";
|
|
17
|
-
|
|
18
|
-
const THREAD_ID = "thread-outcome-contract";
|
|
19
|
-
const TURN_ID = "turn-outcome-contract";
|
|
20
|
-
const tempDirs = new Set<string>();
|
|
21
|
-
|
|
22
|
-
type ProjectorNotification = Parameters<CodexAppServerEventProjector["handleNotification"]>[0];
|
|
23
|
-
type ProjectedAttemptResult = ReturnType<CodexAppServerEventProjector["buildResult"]>;
|
|
24
|
-
type MirrorTaggedMessage = { __klaw?: { mirrorIdentity?: string } };
|
|
25
|
-
|
|
26
|
-
async function createParams(): Promise<EmbeddedRunAttemptParams> {
|
|
27
|
-
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "klaw-codex-outcome-contract-"));
|
|
28
|
-
tempDirs.add(tempDir);
|
|
29
|
-
const sessionFile = path.join(tempDir, "session.jsonl");
|
|
30
|
-
SessionManager.open(sessionFile);
|
|
31
|
-
return {
|
|
32
|
-
prompt: OUTCOME_FALLBACK_RUNTIME_CONTRACT.prompt,
|
|
33
|
-
sessionId: OUTCOME_FALLBACK_RUNTIME_CONTRACT.sessionId,
|
|
34
|
-
sessionKey: OUTCOME_FALLBACK_RUNTIME_CONTRACT.sessionKey,
|
|
35
|
-
sessionFile,
|
|
36
|
-
workspaceDir: tempDir,
|
|
37
|
-
runId: OUTCOME_FALLBACK_RUNTIME_CONTRACT.runId,
|
|
38
|
-
provider: "codex",
|
|
39
|
-
modelId: OUTCOME_FALLBACK_RUNTIME_CONTRACT.primaryModel,
|
|
40
|
-
model: createCodexTestModel("codex"),
|
|
41
|
-
thinkLevel: "medium",
|
|
42
|
-
} as EmbeddedRunAttemptParams;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function createProjector(): Promise<CodexAppServerEventProjector> {
|
|
46
|
-
return new CodexAppServerEventProjector(await createParams(), THREAD_ID, TURN_ID);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function buildToolTelemetry(
|
|
50
|
-
overrides: Partial<CodexAppServerToolTelemetry> = {},
|
|
51
|
-
): CodexAppServerToolTelemetry {
|
|
52
|
-
return {
|
|
53
|
-
didSendViaMessagingTool: false,
|
|
54
|
-
messagingToolSentTexts: [],
|
|
55
|
-
messagingToolSentMediaUrls: [],
|
|
56
|
-
messagingToolSentTargets: [],
|
|
57
|
-
toolMediaUrls: [],
|
|
58
|
-
toolAudioAsVoice: false,
|
|
59
|
-
...overrides,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function forCurrentTurn(
|
|
64
|
-
method: ProjectorNotification["method"],
|
|
65
|
-
params: Record<string, unknown>,
|
|
66
|
-
): ProjectorNotification {
|
|
67
|
-
return {
|
|
68
|
-
method,
|
|
69
|
-
params: { threadId: THREAD_ID, turnId: TURN_ID, ...params },
|
|
70
|
-
} as ProjectorNotification;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function classifyProjectedAttemptResult(result: ProjectedAttemptResult) {
|
|
74
|
-
const finalAssistantText = result.assistantTexts.join("\n\n").trim();
|
|
75
|
-
return classifyEmbeddedPiRunResultForModelFallback({
|
|
76
|
-
provider: "codex",
|
|
77
|
-
model: OUTCOME_FALLBACK_RUNTIME_CONTRACT.primaryModel,
|
|
78
|
-
result: createContractRunResult({
|
|
79
|
-
...result,
|
|
80
|
-
meta: {
|
|
81
|
-
durationMs: 1,
|
|
82
|
-
aborted: result.aborted,
|
|
83
|
-
agentHarnessResultClassification: result.agentHarnessResultClassification,
|
|
84
|
-
finalAssistantRawText: finalAssistantText || undefined,
|
|
85
|
-
finalAssistantVisibleText: finalAssistantText || undefined,
|
|
86
|
-
},
|
|
87
|
-
}),
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function readMirrorIdentity(message: unknown): string | undefined {
|
|
92
|
-
const meta = (message as MirrorTaggedMessage | undefined)?.["__klaw"];
|
|
93
|
-
return meta?.mirrorIdentity;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
afterEach(async () => {
|
|
97
|
-
for (const tempDir of tempDirs) {
|
|
98
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
99
|
-
}
|
|
100
|
-
tempDirs.clear();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
describe("Outcome/fallback runtime contract - Codex app-server adapter", () => {
|
|
104
|
-
it("preserves an empty terminal turn for Klaw-owned fallback classification", async () => {
|
|
105
|
-
const projector = await createProjector();
|
|
106
|
-
await projector.handleNotification(
|
|
107
|
-
forCurrentTurn("turn/completed", {
|
|
108
|
-
turn: { id: TURN_ID, status: "completed", items: [] },
|
|
109
|
-
}),
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
const result = projector.buildResult(buildToolTelemetry());
|
|
113
|
-
|
|
114
|
-
expect(result.assistantTexts).toStrictEqual([]);
|
|
115
|
-
expect(result.lastAssistant).toBeUndefined();
|
|
116
|
-
expect(result.promptError).toBeNull();
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it("preserves exact NO_REPLY as assistant text instead of classifying in the adapter", async () => {
|
|
120
|
-
const projector = await createProjector();
|
|
121
|
-
await projector.handleNotification(
|
|
122
|
-
forCurrentTurn("item/agentMessage/delta", {
|
|
123
|
-
itemId: "msg-1",
|
|
124
|
-
delta: "NO_REPLY",
|
|
125
|
-
}),
|
|
126
|
-
);
|
|
127
|
-
await projector.handleNotification(
|
|
128
|
-
forCurrentTurn("turn/completed", {
|
|
129
|
-
turn: {
|
|
130
|
-
id: TURN_ID,
|
|
131
|
-
status: "completed",
|
|
132
|
-
items: [{ type: "agentMessage", id: "msg-1", text: "NO_REPLY" }],
|
|
133
|
-
},
|
|
134
|
-
}),
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const result = projector.buildResult(buildToolTelemetry());
|
|
138
|
-
|
|
139
|
-
expect(result.assistantTexts).toEqual(["NO_REPLY"]);
|
|
140
|
-
expect(result.lastAssistant?.content).toEqual([{ type: "text", text: "NO_REPLY" }]);
|
|
141
|
-
expect(result.promptError).toBeNull();
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("preserves reasoning-only terminal turns for Klaw-owned fallback classification", async () => {
|
|
145
|
-
const projector = await createProjector();
|
|
146
|
-
await projector.handleNotification(
|
|
147
|
-
forCurrentTurn("item/reasoning/textDelta", {
|
|
148
|
-
itemId: "reasoning-1",
|
|
149
|
-
delta: OUTCOME_FALLBACK_RUNTIME_CONTRACT.reasoningOnlyText,
|
|
150
|
-
}),
|
|
151
|
-
);
|
|
152
|
-
await projector.handleNotification(
|
|
153
|
-
forCurrentTurn("turn/completed", {
|
|
154
|
-
turn: {
|
|
155
|
-
id: TURN_ID,
|
|
156
|
-
status: "completed",
|
|
157
|
-
items: [{ type: "reasoning", id: "reasoning-1" }],
|
|
158
|
-
},
|
|
159
|
-
}),
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
const result = projector.buildResult(buildToolTelemetry());
|
|
163
|
-
|
|
164
|
-
expect(result.assistantTexts).toStrictEqual([]);
|
|
165
|
-
expect(result.lastAssistant).toBeUndefined();
|
|
166
|
-
expect(result.promptError).toBeNull();
|
|
167
|
-
expect(result.messagesSnapshot.map((message) => message.role)).toStrictEqual([
|
|
168
|
-
"user",
|
|
169
|
-
"assistant",
|
|
170
|
-
]);
|
|
171
|
-
const reasoningMessage = result.messagesSnapshot[1];
|
|
172
|
-
if (reasoningMessage?.role !== "assistant") {
|
|
173
|
-
throw new Error("expected Codex reasoning mirror assistant message");
|
|
174
|
-
}
|
|
175
|
-
expect(readMirrorIdentity(reasoningMessage)).toBe(`${TURN_ID}:reasoning`);
|
|
176
|
-
expect(reasoningMessage.content).toStrictEqual([
|
|
177
|
-
{
|
|
178
|
-
type: "text",
|
|
179
|
-
text: `Codex reasoning:\n${OUTCOME_FALLBACK_RUNTIME_CONTRACT.reasoningOnlyText}`,
|
|
180
|
-
},
|
|
181
|
-
]);
|
|
182
|
-
expect(reasoningMessage.api).toBe("openai-codex-responses");
|
|
183
|
-
expect(reasoningMessage.provider).toBe("codex");
|
|
184
|
-
expect(reasoningMessage.model).toBe(OUTCOME_FALLBACK_RUNTIME_CONTRACT.primaryModel);
|
|
185
|
-
expect(reasoningMessage.usage).toStrictEqual({
|
|
186
|
-
input: 0,
|
|
187
|
-
output: 0,
|
|
188
|
-
cacheRead: 0,
|
|
189
|
-
cacheWrite: 0,
|
|
190
|
-
totalTokens: 0,
|
|
191
|
-
cost: {
|
|
192
|
-
input: 0,
|
|
193
|
-
output: 0,
|
|
194
|
-
cacheRead: 0,
|
|
195
|
-
cacheWrite: 0,
|
|
196
|
-
total: 0,
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
expect(reasoningMessage.stopReason).toBe("stop");
|
|
200
|
-
expect(typeof reasoningMessage.timestamp).toBe("number");
|
|
201
|
-
expect(reasoningMessage.timestamp).toBeGreaterThan(0);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("preserves planning-only terminal turns for Klaw-owned fallback classification", async () => {
|
|
205
|
-
const projector = await createProjector();
|
|
206
|
-
await projector.handleNotification(
|
|
207
|
-
forCurrentTurn("item/plan/delta", {
|
|
208
|
-
itemId: "plan-1",
|
|
209
|
-
delta: OUTCOME_FALLBACK_RUNTIME_CONTRACT.planningOnlyText,
|
|
210
|
-
}),
|
|
211
|
-
);
|
|
212
|
-
await projector.handleNotification(
|
|
213
|
-
forCurrentTurn("turn/completed", {
|
|
214
|
-
turn: {
|
|
215
|
-
id: TURN_ID,
|
|
216
|
-
status: "completed",
|
|
217
|
-
items: [
|
|
218
|
-
{
|
|
219
|
-
type: "plan",
|
|
220
|
-
id: "plan-1",
|
|
221
|
-
text: OUTCOME_FALLBACK_RUNTIME_CONTRACT.planningOnlyText,
|
|
222
|
-
},
|
|
223
|
-
],
|
|
224
|
-
},
|
|
225
|
-
}),
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
const result = projector.buildResult(buildToolTelemetry());
|
|
229
|
-
|
|
230
|
-
expect(result.assistantTexts).toStrictEqual([]);
|
|
231
|
-
expect(result.lastAssistant).toBeUndefined();
|
|
232
|
-
expect(result.promptError).toBeNull();
|
|
233
|
-
expect(result.messagesSnapshot.map((message) => message.role)).toStrictEqual([
|
|
234
|
-
"user",
|
|
235
|
-
"assistant",
|
|
236
|
-
]);
|
|
237
|
-
const planMessage = result.messagesSnapshot[1];
|
|
238
|
-
if (planMessage?.role !== "assistant") {
|
|
239
|
-
throw new Error("expected Codex plan mirror assistant message");
|
|
240
|
-
}
|
|
241
|
-
expect(readMirrorIdentity(planMessage)).toBe(`${TURN_ID}:plan`);
|
|
242
|
-
expect(planMessage.content).toStrictEqual([
|
|
243
|
-
{
|
|
244
|
-
type: "text",
|
|
245
|
-
text: `Codex plan:\n${OUTCOME_FALLBACK_RUNTIME_CONTRACT.planningOnlyText}`,
|
|
246
|
-
},
|
|
247
|
-
]);
|
|
248
|
-
expect(planMessage.api).toBe("openai-codex-responses");
|
|
249
|
-
expect(planMessage.provider).toBe("codex");
|
|
250
|
-
expect(planMessage.model).toBe(OUTCOME_FALLBACK_RUNTIME_CONTRACT.primaryModel);
|
|
251
|
-
expect(planMessage.usage).toStrictEqual({
|
|
252
|
-
input: 0,
|
|
253
|
-
output: 0,
|
|
254
|
-
cacheRead: 0,
|
|
255
|
-
cacheWrite: 0,
|
|
256
|
-
totalTokens: 0,
|
|
257
|
-
cost: {
|
|
258
|
-
input: 0,
|
|
259
|
-
output: 0,
|
|
260
|
-
cacheRead: 0,
|
|
261
|
-
cacheWrite: 0,
|
|
262
|
-
total: 0,
|
|
263
|
-
},
|
|
264
|
-
});
|
|
265
|
-
expect(planMessage.stopReason).toBe("stop");
|
|
266
|
-
expect(typeof planMessage.timestamp).toBe("number");
|
|
267
|
-
expect(planMessage.timestamp).toBeGreaterThan(0);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it("preserves tool side-effect telemetry so fallback can stay disabled", async () => {
|
|
271
|
-
const projector = await createProjector();
|
|
272
|
-
|
|
273
|
-
const result = projector.buildResult(
|
|
274
|
-
buildToolTelemetry({
|
|
275
|
-
didSendViaMessagingTool: true,
|
|
276
|
-
messagingToolSentTexts: ["sent out of band"],
|
|
277
|
-
}),
|
|
278
|
-
);
|
|
279
|
-
|
|
280
|
-
expect(result.assistantTexts).toStrictEqual([]);
|
|
281
|
-
expect(result.didSendViaMessagingTool).toBe(true);
|
|
282
|
-
expect(result.messagingToolSentTexts).toEqual(["sent out of band"]);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it.each([
|
|
286
|
-
{
|
|
287
|
-
name: "empty",
|
|
288
|
-
classification: "empty",
|
|
289
|
-
expectedCode: "empty_result",
|
|
290
|
-
build: async () => {
|
|
291
|
-
const projector = await createProjector();
|
|
292
|
-
await projector.handleNotification(
|
|
293
|
-
forCurrentTurn("turn/completed", {
|
|
294
|
-
turn: { id: TURN_ID, status: "completed", items: [] },
|
|
295
|
-
}),
|
|
296
|
-
);
|
|
297
|
-
return projector.buildResult(buildToolTelemetry());
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: "reasoning-only",
|
|
302
|
-
classification: "reasoning-only",
|
|
303
|
-
expectedCode: "reasoning_only_result",
|
|
304
|
-
build: async () => {
|
|
305
|
-
const projector = await createProjector();
|
|
306
|
-
await projector.handleNotification(
|
|
307
|
-
forCurrentTurn("item/reasoning/textDelta", {
|
|
308
|
-
itemId: "reasoning-1",
|
|
309
|
-
delta: OUTCOME_FALLBACK_RUNTIME_CONTRACT.reasoningOnlyText,
|
|
310
|
-
}),
|
|
311
|
-
);
|
|
312
|
-
await projector.handleNotification(
|
|
313
|
-
forCurrentTurn("turn/completed", {
|
|
314
|
-
turn: {
|
|
315
|
-
id: TURN_ID,
|
|
316
|
-
status: "completed",
|
|
317
|
-
items: [{ type: "reasoning", id: "reasoning-1" }],
|
|
318
|
-
},
|
|
319
|
-
}),
|
|
320
|
-
);
|
|
321
|
-
return projector.buildResult(buildToolTelemetry());
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
name: "planning-only",
|
|
326
|
-
classification: "planning-only",
|
|
327
|
-
expectedCode: "planning_only_result",
|
|
328
|
-
build: async () => {
|
|
329
|
-
const projector = await createProjector();
|
|
330
|
-
await projector.handleNotification(
|
|
331
|
-
forCurrentTurn("item/plan/delta", {
|
|
332
|
-
itemId: "plan-1",
|
|
333
|
-
delta: OUTCOME_FALLBACK_RUNTIME_CONTRACT.planningOnlyText,
|
|
334
|
-
}),
|
|
335
|
-
);
|
|
336
|
-
await projector.handleNotification(
|
|
337
|
-
forCurrentTurn("turn/completed", {
|
|
338
|
-
turn: {
|
|
339
|
-
id: TURN_ID,
|
|
340
|
-
status: "completed",
|
|
341
|
-
items: [
|
|
342
|
-
{
|
|
343
|
-
type: "plan",
|
|
344
|
-
id: "plan-1",
|
|
345
|
-
text: OUTCOME_FALLBACK_RUNTIME_CONTRACT.planningOnlyText,
|
|
346
|
-
},
|
|
347
|
-
],
|
|
348
|
-
},
|
|
349
|
-
}),
|
|
350
|
-
);
|
|
351
|
-
return projector.buildResult(buildToolTelemetry());
|
|
352
|
-
},
|
|
353
|
-
},
|
|
354
|
-
] as const)(
|
|
355
|
-
"keeps $name terminal turns fallback-ready with adapter-produced classification",
|
|
356
|
-
async ({ build, classification, expectedCode }) => {
|
|
357
|
-
const result = await build();
|
|
358
|
-
|
|
359
|
-
expect(result.agentHarnessResultClassification).toBe(classification);
|
|
360
|
-
const projected = classifyProjectedAttemptResult(result);
|
|
361
|
-
if (!projected || !("reason" in projected)) {
|
|
362
|
-
throw new Error("expected format fallback projection");
|
|
363
|
-
}
|
|
364
|
-
expect(projected.reason).toBe("format");
|
|
365
|
-
expect(projected.code).toBe(expectedCode);
|
|
366
|
-
},
|
|
367
|
-
);
|
|
368
|
-
|
|
369
|
-
it("keeps exact NO_REPLY classified as an intentional silent terminal reply", async () => {
|
|
370
|
-
const projector = await createProjector();
|
|
371
|
-
await projector.handleNotification(
|
|
372
|
-
forCurrentTurn("item/agentMessage/delta", {
|
|
373
|
-
itemId: "msg-1",
|
|
374
|
-
delta: "NO_REPLY",
|
|
375
|
-
}),
|
|
376
|
-
);
|
|
377
|
-
await projector.handleNotification(
|
|
378
|
-
forCurrentTurn("turn/completed", {
|
|
379
|
-
turn: {
|
|
380
|
-
id: TURN_ID,
|
|
381
|
-
status: "completed",
|
|
382
|
-
items: [{ type: "agentMessage", id: "msg-1", text: "NO_REPLY" }],
|
|
383
|
-
},
|
|
384
|
-
}),
|
|
385
|
-
);
|
|
386
|
-
|
|
387
|
-
const result = projector.buildResult(buildToolTelemetry());
|
|
388
|
-
|
|
389
|
-
expect(classifyProjectedAttemptResult(result)).toBeNull();
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
it("keeps tool side effects classified as non-fallback terminal outcomes", async () => {
|
|
393
|
-
const projector = await createProjector();
|
|
394
|
-
const result = projector.buildResult(
|
|
395
|
-
buildToolTelemetry({
|
|
396
|
-
didSendViaMessagingTool: true,
|
|
397
|
-
messagingToolSentTexts: ["sent out of band"],
|
|
398
|
-
}),
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
expect(result.agentHarnessResultClassification).toBeUndefined();
|
|
402
|
-
expect(classifyProjectedAttemptResult(result)).toBeNull();
|
|
403
|
-
});
|
|
404
|
-
});
|