Files
openclaw/src/plugin-sdk/agent-harness-runtime.test.ts
EVA 2c35a6e599 [codex] Consolidate RuntimePlan and Harness V2 package (#71722)
* refactor: centralize runtime plan policy surface

* refactor: route embedded attempts through runtime plan

* feat: add agent harness v2 lifecycle adapter

* docs: document agent harness runtime plan

---------

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 16:07:04 -07:00

129 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
classifyAgentHarnessTerminalOutcome,
type AgentHarnessTerminalOutcomeClassification,
} from "./agent-harness-runtime.js";
describe("classifyAgentHarnessTerminalOutcome", () => {
it("does not classify an in-flight turn", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "",
planText: "",
promptError: null,
turnCompleted: false,
}),
).toBeUndefined();
});
it("does not classify prompt errors as terminal empty-output outcomes", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "",
planText: "",
promptError: new Error("turn failed"),
turnCompleted: true,
}),
).toBeUndefined();
});
it("does not classify deliberate silent replies such as NO_REPLY", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: ["NO_REPLY"],
reasoningText: "",
planText: "",
promptError: null,
turnCompleted: true,
}),
).toBeUndefined();
});
it("treats empty-string prompt errors as terminal errors", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "",
planText: "",
promptError: "",
turnCompleted: true,
}),
).toBeUndefined();
});
it("treats whitespace-only assistant text as not visible", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [" ", "\n\t"],
reasoningText: "",
planText: "",
promptError: null,
turnCompleted: true,
}),
).toBe("empty");
});
it("classifies a completed turn with plan text only as planning-only", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "",
planText: "1. inspect\n2. patch\n3. test",
promptError: null,
turnCompleted: true,
}),
).toBe("planning-only");
});
it("prefers planning-only when both plan and reasoning text are present", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "I need to inspect the files.",
planText: "I will inspect, patch, and test.",
promptError: null,
turnCompleted: true,
}),
).toBe("planning-only");
});
it("classifies a completed turn with reasoning text only as reasoning-only", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "The answer depends on the current repository state.",
planText: "",
promptError: null,
turnCompleted: true,
}),
).toBe("reasoning-only");
});
it("classifies a completed turn with no visible output as empty", () => {
expect(
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: " ",
planText: "\n",
promptError: null,
turnCompleted: true,
}),
).toBe("empty");
});
it("returns only terminal fallback classifications, not ok", () => {
const classification: AgentHarnessTerminalOutcomeClassification =
classifyAgentHarnessTerminalOutcome({
assistantTexts: [],
reasoningText: "",
planText: "",
promptError: null,
turnCompleted: true,
}) ?? "empty";
expect(classification).toBe("empty");
});
});