feat: publish Agent Studio integrations and setup guide

This commit is contained in:
Wenxin Duan
2026-09-16 16:32:16 +08:00
parent 2ad089d68a
commit 05e6060490
106 changed files with 4942 additions and 198 deletions
@@ -0,0 +1,56 @@
import {it,expect} from "vitest";
import {mkdtemp,rm,writeFile,readFile} from "node:fs/promises";
import {tmpdir,homedir} from "node:os";
import {join} from "node:path";
import {createHash} from "node:crypto";
import {EditorWorkflow} from "../src/media/editor-workflow.js";
import {SkillRunner} from "../src/media/skill-runner.js";
import {analysisFixture} from "./fixtures/editor-analysis.js";
import {planFixture} from "./fixtures/editor-plan.js";
import {mediaRuntime,runMedia} from "../src/media/media-worker.js";
it("requires source review before accepting a plan and never treats model PASS as human review",async()=>{
const root=await mkdtemp(join(tmpdir(),"workflow-"));
try{
await writeFile(join(root,"target-drama-analysis.json"),JSON.stringify({withheld_information:["The answer"]}));
const workflow=new EditorWorkflow({root,sessionId:"ses_test",jobId:"job_test",analysisId:"analysis_test",dramaId:"drama_test",sources:[{episodeId:"ep_test",episodeNo:1,source:join(root,"source.mp4"),duration:20,sha256:"abc",subtitle:"WEBVTT"}],runner:new SkillRunner({skillRoot:"/unused",pythonExecutable:"/unused"})});
await expect(workflow.submitPlan({},new AbortController().signal)).rejects.toMatchObject({code:"SELECTION_REVIEW_REQUIRED"});
const selected=await workflow.proposeSelection({segments:[{id:"one",episodeId:"ep_test",start:0,end:10,reason:"A complete question and reaction"}]});
expect(selected.selection?.reviewed).toBe(false);
expect(JSON.stringify(selected)).not.toContain(root);
await expect(workflow.review("selection",{planHash:selected.selection?.hash,pass:true})).rejects.toThrow();
await expect(workflow.render(new AbortController().signal)).rejects.toMatchObject({code:"PLAN_REVIEW_REQUIRED"});
await expect(workflow.proposeSelection({segments:[{id:"one",episodeId:"foreign",start:0,end:10,reason:"Invalid source"}]})).rejects.toMatchObject({code:"SELECTION_INVALID"});
}finally{await rm(root,{recursive:true,force:true});}
});
it("binds human-reviewed selection to original validators and renders only a REVIEW artifact",async()=>{
const root=await mkdtemp(join(tmpdir(),"workflow-render-"));const signal=new AbortController().signal;
try{
const runtime=await mediaRuntime();const source=join(root,"source.mp4");
await runMedia(runtime.ffmpeg,["-v","error","-f","lavfi","-i","testsrc2=size=180x320:rate=24","-f","lavfi","-i","sine=frequency=440:sample_rate=48000","-t","11","-c:v","libx264","-c:a","aac",source],root,signal);
await writeFile(join(root,"target-drama-analysis.json"),JSON.stringify(analysisFixture()));
const original=await readFile(source);
const workflow=new EditorWorkflow({root,sessionId:"ses_test",jobId:"job_test",analysisId:"analysis_fixture",dramaId:"drama_fixture",sources:[{episodeId:"ep_test",episodeNo:1,source,duration:11,sha256:createHash("sha256").update(original).digest("hex"),subtitle:"WEBVTT\n\n00:00:01.000 --> 00:00:04.000\nSynthetic test caption.\n"}],runner:new SkillRunner({skillRoot:join(homedir(),".codex/skills/swads-short-drama-editor"),pythonExecutable:join(homedir(),".cache/codex-runtimes/codex-primary-runtime/dependencies/python/bin/python3")})});
const selected=await workflow.proposeSelection({segments:[{id:"one",episodeId:"ep_test",start:0,end:10,reason:"Synthetic complete test sequence"}]});
const evidence="Synthetic engineering review; not a licensed drama clearance.";
await workflow.review("selection",{planHash:selected.selection!.hash,reviewer:"Test fixture",policyCheckedAt:new Date().toISOString(),policyPageUpdated:"Test fixture policy",pictureAudioReviewed:true,noUnresolvedFindings:true,segmentEvidence:[{segmentId:"one",pictureEvidence:evidence,audioEvidence:evidence,subtitleEvidence:evidence}]});
const unverified=planFixture();unverified.referenceCandidates.candidates[0]!.evidence.metrics={views:0,likes:0};
const pendingReference=await workflow.submitPlan(unverified,signal);
expect(pendingReference.pass).toBe(true);
await expect(workflow.review("plan",{planHash:workflow.view().plan!.hash,reviewer:"Test fixture",policyCheckedAt:new Date().toISOString(),pictureAudioReviewed:true,referenceReviewed:true,storyReviewed:true,packagingReviewed:true,noUnresolvedFindings:true,segmentEvidence:[{segmentId:"one",observation:evidence}]})).rejects.toMatchObject({code:"VERIFIED_REFERENCE_REQUIRED"});
const result=await workflow.submitPlan(planFixture(),signal);
expect(result.pass).toBe(true);
const plan=workflow.view().plan!;
await expect(workflow.render(signal)).rejects.toMatchObject({code:"PLAN_REVIEW_REQUIRED"});
await workflow.review("plan",{planHash:plan.hash,reviewer:"Test fixture",policyCheckedAt:new Date().toISOString(),pictureAudioReviewed:true,referenceReviewed:true,storyReviewed:true,packagingReviewed:true,noUnresolvedFindings:true,segmentEvidence:[{segmentId:"one",observation:evidence}]});
await writeFile(source,"changed after review");
await expect(workflow.render(signal)).rejects.toMatchObject({code:"REVIEWED_SOURCE_CHANGED"});
await writeFile(source,original);
const rendered=await workflow.render(signal);
expect(rendered.preview?.duration).toBeCloseTo(10,1);expect(rendered.preview?.reviewStatus).toBe("REVIEW");
expect(JSON.stringify(rendered)).not.toContain(root);
const bytes=await readFile(workflow.previewPath(plan.id));expect(bytes.byteLength).toBeGreaterThan(1000);
expect(rendered.humanReviewPassed).toBe(false);
}finally{await rm(root,{recursive:true,force:true});}
},60_000);