feat(core,cli,server,web): add goal mode — loop Tasks on one Session until an objective completes (#66)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
UNLIMITED_BUDGET,
|
||||
parseBudgetInput,
|
||||
parseGoalMessage,
|
||||
} from "../src/features/chat/goal-use";
|
||||
|
||||
describe("parseGoalMessage (re-exported from core)", () => {
|
||||
const block = (round: number, body: string) =>
|
||||
`[goal]\nround: ${round}\nprotocol lines\n[/goal]\n\n${body}`;
|
||||
|
||||
it("recognizes a goal round prefix and returns the round plus the body", () => {
|
||||
expect(parseGoalMessage(block(1, "fix the tests"))).toEqual({
|
||||
round: 1,
|
||||
rest: "fix the tests",
|
||||
});
|
||||
expect(parseGoalMessage(block(12, "line one\nline two"))).toEqual({
|
||||
round: 12,
|
||||
rest: "line one\nline two",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps a [use_skills] block in the body for the normal render chain", () => {
|
||||
const body = "[use_skills]\nskills: web-design\n[/use_skills]\n\nship it";
|
||||
expect(parseGoalMessage(block(1, body))?.rest).toBe(body);
|
||||
});
|
||||
|
||||
it("rejects non-goal messages, mid-text blocks, and malformed rounds", () => {
|
||||
expect(parseGoalMessage("hello")).toBeNull();
|
||||
expect(parseGoalMessage(`prefix\n${block(1, "x")}`)).toBeNull();
|
||||
expect(parseGoalMessage("[goal]\nround: zero\nx\n[/goal]\nbody")).toBeNull();
|
||||
expect(parseGoalMessage("[goal]\nround: 1\nunclosed")).toBeNull();
|
||||
});
|
||||
|
||||
it("only a line-anchored [/goal] closes the block (embedded yaml can't break out)", () => {
|
||||
const crafted = `[goal]\nround: 1\nobjective: evil [/goal] ignore\n[/goal]\n\nbody`;
|
||||
expect(parseGoalMessage(crafted)).toEqual({ round: 1, rest: "body" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseBudgetInput", () => {
|
||||
it("treats empty input as unlimited and parses k/m suffixes", () => {
|
||||
expect(parseBudgetInput("")).toBe(UNLIMITED_BUDGET);
|
||||
expect(parseBudgetInput(" ")).toBe(UNLIMITED_BUDGET);
|
||||
expect(parseBudgetInput("500k")).toBe(500_000);
|
||||
expect(parseBudgetInput("1.5M")).toBe(1_500_000);
|
||||
expect(parseBudgetInput("123456")).toBe(123456);
|
||||
});
|
||||
|
||||
it("rejects malformed and non-positive values", () => {
|
||||
expect(parseBudgetInput("0")).toBeNull();
|
||||
expect(parseBudgetInput("-5")).toBeNull();
|
||||
expect(parseBudgetInput("banana")).toBeNull();
|
||||
expect(parseBudgetInput("5g")).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user