@lingjingai/scriptctl 0.66.15 → 0.66.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ # 0.66.16
2
+
3
+ - 统一 review usage 的输入/输出为包含缓存/推理的总量;缓存和推理字段为子项。修正 Gemini JSON 请求漏计推理输出的问题。
4
+ - Redraw 消费端按互斥 token 分类计价,避免重复计费。
@@ -61,7 +61,7 @@ ${n}`),t}function Uw(e){let t=ww.flatMap(o=>{let n=e[o];return n==null||n===!1?[
61
61
  ${o.join(`
62
62
  `)}`);this.usage=n}usage};function GE(e){return e instanceof Error&&(e.name==="TimeoutError"||e instanceof TypeError&&e.message==="fetch failed"||e.cause instanceof Error&&"code"in e.cause&&["ECONNRESET","ECONNREFUSED","ETIMEDOUT","EAI_AGAIN","UND_ERR_SOCKET","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT"].includes(String(e.cause.code)))}function SE(e){let t=e.trim(),o=/^```(?:json)?[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```$/i.exec(t);return o?o[1]:t}async function ki(e){let t=[],o=[],n=we.toJSONSchema(e.schema),s=[e.system,`\u53EA\u8FD4\u56DE\u7B26\u5408\u4EE5\u4E0B schema \u7684\u5355\u4E2A JSON \u5BF9\u8C61\u6B63\u6587\uFF1A
63
63
  ${JSON.stringify(n)}`].filter(Boolean).join(`
64
- `);for(let i of Ru(e.config)){let r=i.protocol.startsWith("google");if(!r&&i.provider!=="doubao"){t.push(`${i.provider}/${i.model}: JSON review requests need a Gemini or Doubao route`);continue}if(!i.vertex&&!i.apiKey){t.push(`${i.provider}/${i.model}: ${r?"API key":"ARK_API_KEY"} is not set`);continue}let l=r?{contents:[{role:"user",parts:[...e.video?[{inline_data:{mime_type:"video/mp4",data:e.video.data},video_metadata:{fps:e.video.fps}}]:[],{text:e.prompt}]}],systemInstruction:{parts:[{text:s}]},generationConfig:{temperature:0,responseMimeType:"application/json",...i.responseSchemaField==="responseSchema"?{responseSchema:we.toJSONSchema(e.schema,{target:"openapi-3.0"})}:{responseJsonSchema:n}}}:{model:i.model,input:[{role:"user",content:[...e.video?[{type:"input_video",video_url:`data:video/mp4;base64,${e.video.data}`,fps:e.video.fps}]:[],{type:"input_text",text:e.prompt}]}],instructions:s,text:{format:{type:"json_schema",name:"review",schema:n}}};for(let a=1;a<=i.maxAttempts;a++){let c,d;try{c=await Ri(r?`${i.baseUrl}/models/${i.model}:generateContent`:`${i.baseUrl}/responses`,l,e.timeoutMs,i.vertex?{Authorization:`Bearer ${await OE.getAccessToken()}`}:r?{"x-goog-api-key":i.apiKey}:{Authorization:`Bearer ${i.apiKey}`}),d=await c.text()}catch(f){if(!GE(f))throw f;let p=f instanceof Error&&f.cause instanceof Error?`; ${f.cause.name}: ${f.cause.message}`:"";t.push(`${i.provider}/${i.model} attempt ${a}: ${String(f)}${p}`),a<i.maxAttempts&&await new Promise(u=>setTimeout(u,a*1e3));continue}await e.onResponse?.(i,a,d);try{if(!c.ok)throw new vn(`HTTP ${c.status}: ${d.slice(0,400)}`,[408,429].includes(c.status)||c.status>=500);let f=JSON.parse(d),p,u={call_key:`${e.callKey}:${i.provider}:${i.model}:${a}`,provider:i.provider,model:i.model,input_tokens:0,output_tokens:0,cached_input_tokens:0,reasoning_tokens:0};if(r){let g=JE.parse(f),h=g.usageMetadata;Object.assign(u,{input_tokens:h?.promptTokenCount??0,output_tokens:h?.candidatesTokenCount??0,cached_input_tokens:h?.cachedContentTokenCount??0,reasoning_tokens:h?.thoughtsTokenCount??0}),o.push(u);let w=g.candidates?.[0],A=g.promptFeedback?.blockReason??w?.finishReason;if(A&&A!=="STOP")throw new vn(`finishReason=${A}`,!1);p=w?.content?.parts.filter(U=>!U.thought).map(U=>U.text??"").join("")??""}else{let g=kE.parse(f),h=g.usage;if(Object.assign(u,{input_tokens:h?.input_tokens??0,output_tokens:h?.output_tokens??0,cached_input_tokens:h?.input_tokens_details?.cached_tokens??0,reasoning_tokens:h?.output_tokens_details?.reasoning_tokens??0}),o.push(u),g.status&&g.status!=="completed")throw new vn(`status=${g.status}; ${g.incomplete_details?.reason??""}`,!1);p=g.output?.filter(w=>w.type==="message").flatMap(w=>w.content??[]).filter(w=>w.type==="output_text").map(w=>w.text??"").join("")??""}return{value:e.schema.parse(JSON.parse(SE(p))),usage:o,route:i}}catch(f){if(!(f instanceof vn||f instanceof SyntaxError||f instanceof we.ZodError))throw f;if(t.push(`${i.provider}/${i.model} attempt ${a}: ${f.message}`),!(f instanceof vn)||!f.retryable)break;a<i.maxAttempts&&await new Promise(p=>setTimeout(p,a*1e3))}}}throw new Nn(t,o)}import{Agent as VE}from"@mastra/core/agent";import{createScorer as TE}from"@mastra/core/evals";import{randomUUID as $E}from"node:crypto";import*as Gi from"node:fs";import*as xu from"node:path";function QE(e,t){return{id:`episode-${e}-timeout`,category:"other",title:"\u5BA1\u6838\u8D85\u65F6",issue:`\u7B2C ${e} \u96C6\u5BA1\u6838\u8D85\u8FC7 ${t} \u5206\u949F`,impact:"\u672C\u96C6\u53EF\u80FD\u4ECD\u6709\u672A\u6536\u53E3\u7684\u5019\u9009",resolution:"\u5DF2\u4E2D\u65AD\u5E76\u4FDD\u7559\u6B64\u524D\u7ED3\u8BBA",outcome:"unresolved",confidence:"low",anchor:{episode_number:e,episode_id:null,scene_number:null,scene_id:null,action_id:null,timestamp:null,end_timestamp:null},subject:null,before:null,after:null,unresolved_reason:`\u5355\u96C6\u5BA1\u6838\u8D85\u8FC7 ${t} \u5206\u949F\u786C\u8D85\u65F6`,evidence:[]}}async function rn(e,t,o,n,s,i=Date.now()){let r=e.episode,l=e.asset?`ep${r}:${e.asset}`:`ep${r}`,a=[],c=[],d=new VE({id:`review-${l}`,name:`Script review \xB7 episode ${r}`,instructions:o,model:Ji(t,(U,O,E)=>{c.push(`${U.provider}/${U.model}: ${O instanceof Error?O.message:String(O)}`),t.failureDirectory&&(Gi.mkdirSync(t.failureDirectory,{recursive:!0,mode:448}),Gi.writeFileSync(xu.join(t.failureDirectory,`${Date.now()}-${$E()}.json`),JSON.stringify({episode_number:r,asset:e.asset,provider:U.provider,model:U.model,error:O instanceof Error?O.message:String(O),...E}),{mode:384}))},U=>a.push({...U,call_key:`review:${l}:agent:${U.call_key}`})),tools:s}),f="completed",p="",u=null,g=0,h=!1,w=TE({id:"review-validated",name:"Review validation",type:"agent",description:"Require a successful validate tool call before convergence completes"}).generateScore(()=>h?1:0).generateReason(()=>h?"\u5DF2\u6267\u884C validate \u6536\u53E3\u3002":"\u5BA1\u6838\u5C1A\u672A\u5B8C\u6210\uFF1A\u8BF7\u63A5\u7740\u5DF2\u6709\u8FDB\u5EA6\u5B8C\u6210\u6838\u5BF9\u4E0E\u5FC5\u8981\u4FEE\u6539\uFF0C\u8C03\u7528 validate \u68C0\u67E5\u7ED3\u679C\u540E\u518D\u7ED3\u675F\u3002\u4E0D\u8981\u91CD\u590D\u5DF2\u5B8C\u6210\u7684\u5DE5\u5177\u64CD\u4F5C\uFF1B\u65E0\u6CD5\u4FEE\u590D\u7684\u95EE\u9898\u8BB0\u5F55\u4E3A unresolved\u3002"),A=Math.round(t.timeoutMs/6e4);try{let U=jt(e.doc).warnings.filter(y=>["scene_time_missing","scene_space_missing","scene_location_missing"].includes(y.code)&&(e.phase==="converge"?!e.asset:y.path.startsWith(`$.episodes[${r-1}].`))),O=U.length?`${n}
64
+ `);for(let i of Ru(e.config)){let r=i.protocol.startsWith("google");if(!r&&i.provider!=="doubao"){t.push(`${i.provider}/${i.model}: JSON review requests need a Gemini or Doubao route`);continue}if(!i.vertex&&!i.apiKey){t.push(`${i.provider}/${i.model}: ${r?"API key":"ARK_API_KEY"} is not set`);continue}let l=r?{contents:[{role:"user",parts:[...e.video?[{inline_data:{mime_type:"video/mp4",data:e.video.data},video_metadata:{fps:e.video.fps}}]:[],{text:e.prompt}]}],systemInstruction:{parts:[{text:s}]},generationConfig:{temperature:0,responseMimeType:"application/json",...i.responseSchemaField==="responseSchema"?{responseSchema:we.toJSONSchema(e.schema,{target:"openapi-3.0"})}:{responseJsonSchema:n}}}:{model:i.model,input:[{role:"user",content:[...e.video?[{type:"input_video",video_url:`data:video/mp4;base64,${e.video.data}`,fps:e.video.fps}]:[],{type:"input_text",text:e.prompt}]}],instructions:s,text:{format:{type:"json_schema",name:"review",schema:n}}};for(let a=1;a<=i.maxAttempts;a++){let c,d;try{c=await Ri(r?`${i.baseUrl}/models/${i.model}:generateContent`:`${i.baseUrl}/responses`,l,e.timeoutMs,i.vertex?{Authorization:`Bearer ${await OE.getAccessToken()}`}:r?{"x-goog-api-key":i.apiKey}:{Authorization:`Bearer ${i.apiKey}`}),d=await c.text()}catch(f){if(!GE(f))throw f;let p=f instanceof Error&&f.cause instanceof Error?`; ${f.cause.name}: ${f.cause.message}`:"";t.push(`${i.provider}/${i.model} attempt ${a}: ${String(f)}${p}`),a<i.maxAttempts&&await new Promise(u=>setTimeout(u,a*1e3));continue}await e.onResponse?.(i,a,d);try{if(!c.ok)throw new vn(`HTTP ${c.status}: ${d.slice(0,400)}`,[408,429].includes(c.status)||c.status>=500);let f=JSON.parse(d),p,u={call_key:`${e.callKey}:${i.provider}:${i.model}:${a}`,provider:i.provider,model:i.model,input_tokens:0,output_tokens:0,cached_input_tokens:0,reasoning_tokens:0};if(r){let g=JE.parse(f),h=g.usageMetadata;Object.assign(u,{input_tokens:h?.promptTokenCount??0,output_tokens:(h?.candidatesTokenCount??0)+(h?.thoughtsTokenCount??0),cached_input_tokens:h?.cachedContentTokenCount??0,reasoning_tokens:h?.thoughtsTokenCount??0}),o.push(u);let w=g.candidates?.[0],A=g.promptFeedback?.blockReason??w?.finishReason;if(A&&A!=="STOP")throw new vn(`finishReason=${A}`,!1);p=w?.content?.parts.filter(U=>!U.thought).map(U=>U.text??"").join("")??""}else{let g=kE.parse(f),h=g.usage;if(Object.assign(u,{input_tokens:h?.input_tokens??0,output_tokens:h?.output_tokens??0,cached_input_tokens:h?.input_tokens_details?.cached_tokens??0,reasoning_tokens:h?.output_tokens_details?.reasoning_tokens??0}),o.push(u),g.status&&g.status!=="completed")throw new vn(`status=${g.status}; ${g.incomplete_details?.reason??""}`,!1);p=g.output?.filter(w=>w.type==="message").flatMap(w=>w.content??[]).filter(w=>w.type==="output_text").map(w=>w.text??"").join("")??""}return{value:e.schema.parse(JSON.parse(SE(p))),usage:o,route:i}}catch(f){if(!(f instanceof vn||f instanceof SyntaxError||f instanceof we.ZodError))throw f;if(t.push(`${i.provider}/${i.model} attempt ${a}: ${f.message}`),!(f instanceof vn)||!f.retryable)break;a<i.maxAttempts&&await new Promise(p=>setTimeout(p,a*1e3))}}}throw new Nn(t,o)}import{Agent as VE}from"@mastra/core/agent";import{createScorer as TE}from"@mastra/core/evals";import{randomUUID as $E}from"node:crypto";import*as Gi from"node:fs";import*as xu from"node:path";function QE(e,t){return{id:`episode-${e}-timeout`,category:"other",title:"\u5BA1\u6838\u8D85\u65F6",issue:`\u7B2C ${e} \u96C6\u5BA1\u6838\u8D85\u8FC7 ${t} \u5206\u949F`,impact:"\u672C\u96C6\u53EF\u80FD\u4ECD\u6709\u672A\u6536\u53E3\u7684\u5019\u9009",resolution:"\u5DF2\u4E2D\u65AD\u5E76\u4FDD\u7559\u6B64\u524D\u7ED3\u8BBA",outcome:"unresolved",confidence:"low",anchor:{episode_number:e,episode_id:null,scene_number:null,scene_id:null,action_id:null,timestamp:null,end_timestamp:null},subject:null,before:null,after:null,unresolved_reason:`\u5355\u96C6\u5BA1\u6838\u8D85\u8FC7 ${t} \u5206\u949F\u786C\u8D85\u65F6`,evidence:[]}}async function rn(e,t,o,n,s,i=Date.now()){let r=e.episode,l=e.asset?`ep${r}:${e.asset}`:`ep${r}`,a=[],c=[],d=new VE({id:`review-${l}`,name:`Script review \xB7 episode ${r}`,instructions:o,model:Ji(t,(U,O,E)=>{c.push(`${U.provider}/${U.model}: ${O instanceof Error?O.message:String(O)}`),t.failureDirectory&&(Gi.mkdirSync(t.failureDirectory,{recursive:!0,mode:448}),Gi.writeFileSync(xu.join(t.failureDirectory,`${Date.now()}-${$E()}.json`),JSON.stringify({episode_number:r,asset:e.asset,provider:U.provider,model:U.model,error:O instanceof Error?O.message:String(O),...E}),{mode:384}))},U=>a.push({...U,call_key:`review:${l}:agent:${U.call_key}`})),tools:s}),f="completed",p="",u=null,g=0,h=!1,w=TE({id:"review-validated",name:"Review validation",type:"agent",description:"Require a successful validate tool call before convergence completes"}).generateScore(()=>h?1:0).generateReason(()=>h?"\u5DF2\u6267\u884C validate \u6536\u53E3\u3002":"\u5BA1\u6838\u5C1A\u672A\u5B8C\u6210\uFF1A\u8BF7\u63A5\u7740\u5DF2\u6709\u8FDB\u5EA6\u5B8C\u6210\u6838\u5BF9\u4E0E\u5FC5\u8981\u4FEE\u6539\uFF0C\u8C03\u7528 validate \u68C0\u67E5\u7ED3\u679C\u540E\u518D\u7ED3\u675F\u3002\u4E0D\u8981\u91CD\u590D\u5DF2\u5B8C\u6210\u7684\u5DE5\u5177\u64CD\u4F5C\uFF1B\u65E0\u6CD5\u4FEE\u590D\u7684\u95EE\u9898\u8BB0\u5F55\u4E3A unresolved\u3002"),A=Math.round(t.timeoutMs/6e4);try{let U=jt(e.doc).warnings.filter(y=>["scene_time_missing","scene_space_missing","scene_location_missing"].includes(y.code)&&(e.phase==="converge"?!e.asset:y.path.startsWith(`$.episodes[${r-1}].`))),O=U.length?`${n}
65
65
 
66
66
  ## \u7A0B\u5E8F\u626B\u63CF\u7684\u5236\u4F5C\u5B57\u6BB5\u7F3A\u9879
67
67
  ${U.map(y=>`${y.path}: ${y.message}`).join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingjingai/scriptctl",
3
- "version": "0.66.15",
3
+ "version": "0.66.16",
4
4
  "description": "剧本阶段统一 CLI:素材转 Script v4,并兼容 Script v3 的本地写作、精修、校验和发布。",
5
5
  "type": "module",
6
6
  "bin": {