|
|
@@ -29,6 +29,20 @@ test("shows pipeline stages and resolves remote confirmations", async () => {
|
|
|
],
|
|
|
["tool_call", { tool: "WriteFile", step: 1, content: '{"file_path":"/run/idea-analysis/work_plan.md"}' }],
|
|
|
["tool_result", { tool: "WriteFile", step: 1, content: "[OK] Created work_plan.md" }],
|
|
|
+ [
|
|
|
+ "tool_call",
|
|
|
+ { tool: "WriteFile", step: 1, content: '{"file_path":"/run/idea-analysis/artifacts/search_queries.json"}' },
|
|
|
+ ],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: 1, content: "[OK] Created search_queries.json" }],
|
|
|
+ [
|
|
|
+ "tool_call",
|
|
|
+ { tool: "WriteFile", step: 1, content: '{"file_path":"/run/idea-analysis/artifacts/similar_papers.json"}' },
|
|
|
+ ],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: 1, content: "[OK] Created similar_papers.json" }],
|
|
|
+ ["tool_call", { tool: "WriteFile", step: 1, content: '{"file_path":"/run/idea-analysis/report.json"}' }],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: 1, content: "[OK] Created report.json" }],
|
|
|
+ ["tool_call", { tool: "WriteFile", step: 1, content: '{"file_path":"/run/idea-analysis/report.md"}' }],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: 1, content: "[OK] Created report.md" }],
|
|
|
[
|
|
|
"stage_passed",
|
|
|
{
|
|
|
@@ -102,6 +116,20 @@ test("shows pipeline stages and resolves remote confirmations", async () => {
|
|
|
{ tool: "WriteFile", step: 5, content: '{"file_path":"/run/paper-writing/artifacts/sections/abstract.tex"}' },
|
|
|
],
|
|
|
["tool_result", { tool: "WriteFile", step: 5, content: "[OK] Created abstract.tex" }],
|
|
|
+ [
|
|
|
+ "tool_call",
|
|
|
+ {
|
|
|
+ tool: "BuildResearchPaper",
|
|
|
+ step: 6,
|
|
|
+ content:
|
|
|
+ '{"phase_dir":"/run/paper-writing","papers_selected_path":"/run/literature-review/artifacts/papers_selected.json"}',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ ["tool_result", { tool: "BuildResearchPaper", step: 6, content: '{"status":"completed","passed":true}' }],
|
|
|
+ ["tool_call", { tool: "WriteFile", step: 7, content: '{"file_path":"/run/paper-writing/report.json"}' }],
|
|
|
+ ["tool_call", { tool: "WriteFile", step: 7, content: '{"file_path":"/run/paper-writing/report.md"}' }],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: 7, content: "[OK] Created report.json" }],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: 7, content: "[OK] Created report.md" }],
|
|
|
[
|
|
|
"stage_passed",
|
|
|
{
|
|
|
@@ -182,10 +210,11 @@ test("shows pipeline stages and resolves remote confirmations", async () => {
|
|
|
expect.objectContaining({
|
|
|
metadata: expect.objectContaining({
|
|
|
latest_event: "heartbeat",
|
|
|
- research67_progress: expect.objectContaining({ footer: "连接正常" }),
|
|
|
+ research67_progress: expect.objectContaining({ activeSince: expect.any(Number) }),
|
|
|
}),
|
|
|
}),
|
|
|
)
|
|
|
+ expect(JSON.stringify(updates)).not.toContain("连接正常")
|
|
|
const snapshots = updates.flatMap((update) => {
|
|
|
const value = update.metadata?.research67_progress
|
|
|
return value && typeof value === "object" ? [Object.fromEntries(Object.entries(value))] : []
|
|
|
@@ -193,6 +222,21 @@ test("shows pipeline stages and resolves remote confirmations", async () => {
|
|
|
expect(snapshots.some((snapshot) => snapshot.title === "Research67 · idea-analyst · 创意分析 · 制定分析计划")).toBe(
|
|
|
true,
|
|
|
)
|
|
|
+ expect(snapshots).toContainEqual(
|
|
|
+ expect.objectContaining({
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "idea-analysis:plan", status: "completed" }),
|
|
|
+ expect.objectContaining({ id: "idea-analysis:directions", status: "running" }),
|
|
|
+ ]),
|
|
|
+ }),
|
|
|
+ )
|
|
|
+ expect(snapshots).toContainEqual(
|
|
|
+ expect.objectContaining({
|
|
|
+ footer: "正在进行 Guard / 阶段产物验收",
|
|
|
+ activeSince: expect.any(Number),
|
|
|
+ rows: expect.arrayContaining([expect.objectContaining({ id: "idea-analysis:report", status: "completed" })]),
|
|
|
+ }),
|
|
|
+ )
|
|
|
expect(snapshots).toContainEqual(
|
|
|
expect.objectContaining({
|
|
|
rows: expect.arrayContaining([
|
|
|
@@ -212,6 +256,14 @@ test("shows pipeline stages and resolves remote confirmations", async () => {
|
|
|
]),
|
|
|
}),
|
|
|
)
|
|
|
+ expect(snapshots).toContainEqual(
|
|
|
+ expect.objectContaining({
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "literature-review:select", status: "completed" }),
|
|
|
+ expect.objectContaining({ id: "literature-review:report", status: "running" }),
|
|
|
+ ]),
|
|
|
+ }),
|
|
|
+ )
|
|
|
expect(snapshots).toContainEqual(
|
|
|
expect.objectContaining({
|
|
|
rows: expect.arrayContaining([
|
|
|
@@ -219,6 +271,22 @@ test("shows pipeline stages and resolves remote confirmations", async () => {
|
|
|
]),
|
|
|
}),
|
|
|
)
|
|
|
+ expect(snapshots).toContainEqual(
|
|
|
+ expect.objectContaining({
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "paper-writing:compile", status: "completed" }),
|
|
|
+ expect.objectContaining({ id: "paper-writing:report", status: "running" }),
|
|
|
+ ]),
|
|
|
+ }),
|
|
|
+ )
|
|
|
+ expect(snapshots).toContainEqual(
|
|
|
+ expect.objectContaining({
|
|
|
+ footer: "正在进行 Guard / 阶段产物验收",
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "paper-writing:report", status: "completed", detail: undefined }),
|
|
|
+ ]),
|
|
|
+ }),
|
|
|
+ )
|
|
|
expect(updates.at(-1)?.metadata).toMatchObject({
|
|
|
pipeline_id: "research67-one-round",
|
|
|
stage_id: "paper-writing",
|
|
|
@@ -281,6 +349,37 @@ test("preserves completed artifacts and forbids automatic reruns after failure",
|
|
|
],
|
|
|
["tool_call", { tool: "WriteFile", content: '{"file_path":"/run/paper-writing/artifacts/outline.json"}' }],
|
|
|
["tool_result", { tool: "WriteFile", content: "[OK] Created outline.json" }],
|
|
|
+ [
|
|
|
+ "stage_started",
|
|
|
+ {
|
|
|
+ pipeline_id: "research67-one-round",
|
|
|
+ stage_id: "paper-writing",
|
|
|
+ stage_name: "实验前研究草稿撰写",
|
|
|
+ attempt: 1,
|
|
|
+ status: "running",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ ["tool_call", { tool: "CompileLatex", content: '{"tex_path":"/run/paper-writing/artifacts/paper.tex"}' }],
|
|
|
+ ["tool_result", { tool: "CompileLatex", content: "[TOOL_ERROR] UnicodeDecodeError" }],
|
|
|
+ [
|
|
|
+ "tool_call",
|
|
|
+ {
|
|
|
+ tool: "WriteFile",
|
|
|
+ step: "repair",
|
|
|
+ content: '{"file_path":"/run/paper-writing/artifacts/paper.tex"}',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ ["tool_result", { tool: "WriteFile", step: "repair", content: "[OK] Updated paper.tex" }],
|
|
|
+ [
|
|
|
+ "stage_started",
|
|
|
+ {
|
|
|
+ pipeline_id: "research67-one-round",
|
|
|
+ stage_id: "paper-writing",
|
|
|
+ stage_name: "实验前研究草稿撰写",
|
|
|
+ attempt: 2,
|
|
|
+ status: "running",
|
|
|
+ },
|
|
|
+ ],
|
|
|
["tool_call", { tool: "CompileLatex", content: '{"tex_path":"/run/paper-writing/artifacts/paper.tex"}' }],
|
|
|
["tool_result", { tool: "CompileLatex", content: "[TOOL_ERROR] UnicodeDecodeError" }],
|
|
|
[
|
|
|
@@ -289,7 +388,7 @@ test("preserves completed artifacts and forbids automatic reruns after failure",
|
|
|
pipeline_id: "research67-one-round",
|
|
|
stage_id: "paper-writing",
|
|
|
stage_name: "实验前研究草稿撰写",
|
|
|
- attempt: 1,
|
|
|
+ attempt: 2,
|
|
|
status: "failed",
|
|
|
error: "Native function-calling loop produced no final output",
|
|
|
},
|
|
|
@@ -348,6 +447,37 @@ test("preserves completed artifacts and forbids automatic reruns after failure",
|
|
|
expect(result.output).toContain("Native function-calling loop produced no final output")
|
|
|
expect(result.output).toContain(workspacePath)
|
|
|
expect(result.output).toContain("失败严禁自动重跑、拆分任务或调用其他 subagent")
|
|
|
+ expect(
|
|
|
+ updates.find((update) => update.metadata?.latest_event === "tool_result" && update.metadata.step === "repair")
|
|
|
+ ?.metadata?.research67_progress,
|
|
|
+ ).toMatchObject({
|
|
|
+ title: "Research67 · paper-writer · 论文撰写 · 编译双语 PDF",
|
|
|
+ footer: "当前操作失败,等待重试",
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "paper-writing:english", status: "completed" }),
|
|
|
+ expect.objectContaining({ id: "paper-writing:compile", status: "failed" }),
|
|
|
+ ]),
|
|
|
+ })
|
|
|
+ const attemptStarts = updates.filter((update) => update.metadata?.latest_event === "stage_started")
|
|
|
+ const firstAttemptProgress = attemptStarts[0]?.metadata?.research67_progress
|
|
|
+ const firstActiveSince =
|
|
|
+ firstAttemptProgress && typeof firstAttemptProgress === "object" && "activeSince" in firstAttemptProgress
|
|
|
+ ? firstAttemptProgress.activeSince
|
|
|
+ : undefined
|
|
|
+ expect(attemptStarts[1]?.metadata?.research67_progress).toMatchObject({
|
|
|
+ activeSince: firstActiveSince,
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "paper-writing:outline", status: "running", detail: "1/2" }),
|
|
|
+ ]),
|
|
|
+ })
|
|
|
+ expect(attemptStarts[2]?.metadata?.research67_progress).toMatchObject({
|
|
|
+ activeSince: expect.any(Number),
|
|
|
+ rows: expect.arrayContaining([
|
|
|
+ expect.objectContaining({ id: "paper-writing:outline", status: "running", detail: undefined }),
|
|
|
+ expect.objectContaining({ id: "paper-writing:english", status: "pending", detail: undefined }),
|
|
|
+ expect.objectContaining({ id: "paper-writing:compile", status: "pending", detail: undefined }),
|
|
|
+ ]),
|
|
|
+ })
|
|
|
expect(result.metadata).toMatchObject({
|
|
|
run_id: "run_failure",
|
|
|
status: "failed",
|