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:
rank-Yu
2026-07-27 23:43:24 +08:00
committed by GitHub
parent e1141ca010
commit 46463bee26
61 changed files with 3411 additions and 188 deletions
-36
View File
@@ -8,7 +8,6 @@ import {
emptyTokenCounts,
sanitizeTitle,
Session,
stripConversationMarkers,
thinkingMessage,
tokenUsage,
userText,
@@ -125,41 +124,6 @@ describe("session-title", () => {
);
});
it("stripConversationMarkers: removes machine marker blocks, keeps the human body", () => {
// The skill-invocation block that wraps a first user message must not reach the title.
expect(
stripConversationMarkers(
"[use_skills]\nskills: penguin-sdk, web-design\n[/use_skills]\n做一个 RAG 应用",
),
).toBe("做一个 RAG 应用");
// Handoff and scheduled-task markers are stripped too; ordinary bracketed text stays.
expect(stripConversationMarkers("[handoff_from]data_analyst[/handoff_from]继续分析")).toBe(
"继续分析",
);
// The /model switch origin block (the new session's first message) must not leak into the title either.
expect(
stripConversationMarkers(
"[model_switch_from]\nsession: session-01\ntrace: /t/x_001.jsonl\n[/model_switch_from]\n继续这个任务",
),
).toBe("继续这个任务");
expect(stripConversationMarkers("render a <div> element")).toBe("render a <div> element");
expect(stripConversationMarkers("check the [config] section")).toBe(
"check the [config] section",
);
});
it("stripConversationMarkers: the old angle-bracket marker form is still stripped (material from old Traces)", () => {
expect(
stripConversationMarkers("<use_skills>\nskills: web-design\n</use_skills>\n做一个落地页"),
).toBe("做一个落地页");
expect(stripConversationMarkers("<handoff_from>data_analyst</handoff_from>继续分析")).toBe(
"继续分析",
);
expect(
stripConversationMarkers("<model_switch_from>session: s1</model_switch_from>继续这个任务"),
).toBe("继续这个任务");
});
it("Session.generateTitle: sends via createBareLLM; returns null when no factory is provided", async () => {
const withFactory = new Session({
meta: META,