aitable-workflow-server 0.1.16 → 0.1.17-beta.1786087167343
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.
- package/dist/index.js +14 -14
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
var
|
|
2
|
-
`)}s(
|
|
3
|
-
`)}s(
|
|
4
|
-
`,r,{"content-type":"application/json; charset=utf-8"})}s(y,"jsonBody");function
|
|
5
|
-
`,401,{"content-type":"application/json; charset=utf-8"})}s(Ye,"unauthorized");function
|
|
1
|
+
var hr=Object.defineProperty;var s=(e,t)=>hr(e,"name",{value:t,configurable:!0});import xn from"http";import{Hono as Ko}from"hono";import{detectAgents as Vo}from"aitable-workflow-core";async function b(e){let t=[];for await(let o of e)t.push(Buffer.isBuffer(o)?o:Buffer.from(o));let r=Buffer.concat(t).toString("utf8").trim();return r?JSON.parse(r):{}}s(b,"readJson");function M(e,t,r=200){e.writeHead(r,{"content-type":"application/json; charset=utf-8"}),e.end(`${JSON.stringify(t)}
|
|
2
|
+
`)}s(M,"sendJson");function H(e,t,r,o,n){M(e,{error:{code:r,message:o,details:n}},t)}s(H,"sendError");function Cn(e){e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(`${JSON.stringify({error:"unauthorized"})}
|
|
3
|
+
`)}s(Cn,"sendUnauthorized");function ee(e){return{code:x(e),message:v(e),details:F(e)}}s(ee,"apiError");function te(e){return typeof e=="object"&&e!==null&&"status"in e&&typeof e.status=="number"?e.status:500}s(te,"errorStatus");function x(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:"INTERNAL_ERROR"}s(x,"errorCode");function v(e){return e instanceof Error?e.message:String(e)}s(v,"errorMessage");function F(e){if(typeof e=="object"&&e!==null&&"details"in e)return e.details}s(F,"errorDetails");import Tr from"crypto";function Je(e,t){vr(e,t),t.setHeader("access-control-allow-methods","GET,POST,PATCH,DELETE,OPTIONS"),t.setHeader("access-control-allow-headers","content-type, authorization")}s(Je,"setCors");function vr(e,t){let r=jr();if(!r){t.setHeader("access-control-allow-origin","*");return}let o=e.headers.origin,n=Array.isArray(o)?o[0]:o;n&&r.includes(n)&&(t.setHeader("access-control-allow-origin",n),t.setHeader("vary","Origin"))}s(vr,"applyCorsOrigin");function jr(){let e=process.env.AITABLE_WORKFLOW_ALLOWED_ORIGINS;if(typeof e!="string")return;let t=e.split(",").map(r=>r.trim()).filter(Boolean);return t.length?t:void 0}s(jr,"readAllowedOrigins");function Pr(){let e=process.env.AITABLE_WORKFLOW_API_TOKEN,t=typeof e=="string"?e.trim():"";return t||void 0}s(Pr,"readServerApiToken");function Ge(e){let t=Pr();if(!t)return!0;let r=e.headers.authorization,o=Array.isArray(r)?r[0]:r;if(!o)return!1;let i=/^Bearer\s+(.+)$/i.exec(o.trim())?.[1]?.trim();return i?Dr(i,t):!1}s(Ge,"isRequestAuthorized");function Dr(e,t){let r=Buffer.from(e),o=Buffer.from(t);return r.length!==o.length?!1:Tr.timingSafeEqual(r,o)}s(Dr,"timingSafeEqualString");function Ke(e){return Array.isArray(e)?e[0]:e}s(Ke,"headerValue");function Ve(e,t){let r=t.toUpperCase();return!!(r==="OPTIONS"||r==="GET"&&e==="/api/health"||r==="GET"&&e==="/check.node"||r==="POST"&&e.startsWith("/api/auth/"))}s(Ve,"isAuthExempt");function y(e,t,r=200){return e.newResponse(`${JSON.stringify(t)}
|
|
4
|
+
`,r,{"content-type":"application/json; charset=utf-8"})}s(y,"jsonBody");function E(e,t,r,o,n){return y(e,{error:{code:r,message:o,details:n}},t)}s(E,"errorBody");function Ye(e){return e.newResponse(`${JSON.stringify({error:"unauthorized"})}
|
|
5
|
+
`,401,{"content-type":"application/json; charset=utf-8"})}s(Ye,"unauthorized");function W(e){return async t=>(await e(t),t.env.rawHandled=!0,t.body(null))}s(W,"raw");function J(e){return e.env.services.execution}s(J,"backendOf");async function Ie(e,t){e.env.project||(e.env.project=await e.env.services.projectStore.projects.resolve(e.req.param("projectId"),e.env.scope)),await t()}s(Ie,"resolveProjectMw");import{Hono as zo}from"hono";import le from"path";import{validateDesignOutput as Jo,buildEnvSource as Go,loadWorkflowTemplate as Xt}from"aitable-workflow-core";import{logger as Sr}from"aitable-workflow-core";var re=new Set,ce=new Map;function Ae(e,t,r){e.write(`id: ${t}
|
|
6
6
|
`),e.write(`event: ${r.type}
|
|
7
7
|
`),e.write(`data: ${JSON.stringify(r)}
|
|
8
8
|
|
|
9
|
-
`)}s(
|
|
10
|
-
`,"utf8")}s(
|
|
11
|
-
`,"utf8")}s(
|
|
9
|
+
`)}s(Ae,"writeDesignSse");function Qe(e,t){let r=e.buffer.push(t);for(let o of e.subscribers){if(o.destroyed||o.writableEnded){e.subscribers.delete(o);continue}try{Ae(o,r.seq,t)}catch{e.subscribers.delete(o)}}}s(Qe,"publishDesignEvent");function Ze(e){re.delete(e);let t=ce.get(e);if(ce.delete(e),!!t){for(let r of t.subscribers)if(!r.writableEnded)try{r.end()}catch{}t.subscribers.clear()}}s(Ze,"closeDesignSession");function Xe(e,t){let r=e.searchParams.get("cursor")??Ke(t.headers["last-event-id"]);if(r==null||r==="")return;let o=Number(r);return Number.isFinite(o)?o:void 0}s(Xe,"parseReconnectCursor");function Or(e,t){return e.runtime.runSessions.has(t)||re.has(t)}s(Or,"isStageActiveFor");function j(e,t){return t.projectStore.prepareWorkdir(e,{isStageActive:s(()=>Or(t,e.id),"isStageActive")})}s(j,"prepareWorkdirGuarded");async function ue(e,t,r){try{let o=await e.projectStore.instances.getState(t),n=o.lastTasks[r];if(!n)return;let i=n.status;if(i!=="succeeded"&&i!=="failed"&&i!=="cancelled")return;await e.projectStore.commitWorkdir(t,{stage:o.stage})}catch(o){Sr.warn("stage-sync","stage \u6D41\u56DE\u5199\u6743\u5A01\u6E90\u5931\u8D25",{projectId:t.id,stage:r,error:v(o)})}}s(ue,"commitStageOnTerminal");async function et(e,t){await e.projectStore.cascadeDelete(t).catch(()=>{}),await e.execution.unbindProjectMachine(t).catch(()=>{})}s(et,"cascadeDeleteProject");import We from"path";import{readFile as Hr,writeFile as Ur,access as qr,readdir as zr}from"fs/promises";import St from"yaml";import{scaffold as Jr,writeRoleDefinitions as Gr,isRecord as Ot}from"aitable-workflow-core";import{logger as gt}from"aitable-workflow-core";import{createHash as br,randomUUID as Ir}from"crypto";import{mkdir as Re,readdir as tt,readFile as xe,rm as rt,stat as ot,writeFile as nt}from"fs/promises";import P from"path";var Ar=P.resolve(process.cwd(),".sandbox","aitable-workflow-server"),st=/^[a-zA-Z0-9_-]+$/,Rr=/\.(json|ya?ml|ts|js|md|txt)$/i,xr=["workflow.yml","views.yml","recipes","traces"];function it(e={}){let t=P.resolve(e.dataRoot??process.env.AITABLE_WORKFLOW_DATA_DIR??Ar);return{dataRoot:t,projectsRoot:P.join(t,"projects")}}s(it,"createWorkspace");async function at(e){await Re(e.projectsRoot,{recursive:!0});let t=new Date().toISOString(),r=(await Ee(e)).length+1,o={id:`wf_${Ir().slice(0,8)}`,title:`\u5DE5\u4F5C\u6D41 #${r}`,dir:"",createdAt:t,updatedAt:t};return o.dir=lt(e,o.id),await Re(o.dir,{recursive:!0}),await ge(o),o}s(at,"createProject");async function oe(e,t){let r=await I({dataRoot:P.dirname(P.dirname(e.dir)),projectsRoot:P.dirname(e.dir)},e.id),o={...r,...t,title:t.title?.trim()||r.title,updatedAt:new Date().toISOString()};return await ge(o),o}s(oe,"updateProjectMeta");async function Ee(e){let t=await tt(e.projectsRoot,{withFileTypes:!0}).catch(()=>[]);return(await Promise.all(t.filter(o=>o.isDirectory()&&st.test(o.name)).map(o=>I(e,o.name).catch(()=>null)))).filter(o=>o!==null).sort((o,n)=>n.updatedAt.localeCompare(o.updatedAt))}s(Ee,"listProjects");async function I(e,t){ft(t);let r=lt(e,t);if(!(await ot(r).catch(()=>null))?.isDirectory())throw Object.assign(new Error(`\u9879\u76EE\u4E0D\u5B58\u5728: ${t}`),{code:"PROJECT_NOT_FOUND",status:404});let n=P.join(r,"project.json"),i=await xe(n,"utf8").catch(()=>"");if(!i){let c=new Date().toISOString(),u={id:t,dir:r,createdAt:c,updatedAt:c};return await ge(u),u}return{...JSON.parse(i),dir:r}}s(I,"resolveProject");async function A(e){let t={...e,updatedAt:new Date().toISOString()};return await ge(t),t}s(A,"touchProject");async function ct(e){return await Promise.all(xr.map(t=>rt(P.join(e.dir,t),{recursive:!0,force:!0}))),await A(e)}s(ct,"resetProjectWorkflow");async function me(e){await rt(e.dir,{recursive:!0,force:!0})}s(me,"deleteProject");async function Er(e){let t=await xe(dt(e),"utf8").catch(()=>"");return t.trim()?JSON.parse(t):null}s(Er,"readDesignManifest");async function _e(e,t){await Re(pt(e),{recursive:!0}),await nt(dt(e),`${JSON.stringify(t,null,2)}
|
|
10
|
+
`,"utf8")}s(_e,"writeDesignManifest");async function ut(e){let t=await Er(e);if(!t)return{status:"missing_manifest",manifest:null,errors:["\u7F3A\u5C11 Design \u4EA7\u7269\u6E05\u5355"],missing:["runtime/artifacts/design-manifest.json"]};if(t.status!=="ready"||!t.validation.passed)return{status:"invalid",manifest:t,errors:t.validation.errors.length?t.validation.errors:["Design \u4EA7\u7269\u6E05\u5355\u672A\u5C31\u7EEA"],missing:[]};let r=t.generated.filter(n=>n.required).map(n=>n.path),o=[];for(let n of r)(await ot(P.join(e.dir,n)).catch(()=>null))?.isFile()||o.push(n);return o.length>0?{status:"artifact_missing",manifest:t,errors:[`\u7F3A\u5C11 Design \u4EA7\u7269\uFF1A${o.join(", ")}`],missing:o}:{status:"ready",manifest:t,errors:[],missing:[]}}s(ut,"validateDesignArtifacts");function pe(e){return br("sha256").update(e).digest("hex")}s(pe,"checksumContent");async function S(e){let t=[];return await mt(e.dir,e.dir,t),t.sort((r,o)=>r.path.localeCompare(o.path))}s(S,"listProjectFiles");function _(e){return P.join(e.dir,"aitable-workflow.config.yml")}s(_,"configPath");function Fe(e,t,r){let o=new URLSearchParams({entrance:"data",sheetId:t});return r?.trim()&&o.set("viewId",r.trim()),`https://alidocs.dingtalk.com/i/nodes/${e}?iframeQuery=${encodeURIComponent(o.toString())}`}s(Fe,"buildAITableUrl");function _r(e){return P.join(e.dir,"runtime")}s(_r,"runtimeDir");function pt(e){return P.join(_r(e),"artifacts")}s(pt,"artifactsDir");function dt(e){return P.join(pt(e),"design-manifest.json")}s(dt,"designManifestPath");function lt(e,t){return ft(t),P.join(e.projectsRoot,t)}s(lt,"projectDir");function ft(e){if(!st.test(e))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${e}`),{code:"INVALID_PROJECT_ID"})}s(ft,"assertProjectId");async function ge(e){await nt(P.join(e.dir,"project.json"),`${JSON.stringify(e,null,2)}
|
|
11
|
+
`,"utf8")}s(ge,"writeProjectMeta");async function mt(e,t,r){let o=await tt(t,{withFileTypes:!0}).catch(()=>[]);for(let n of o){if(n.name==="node_modules"||n.name==="traces"||n.name==="runtime")continue;let i=P.join(t,n.name);if(n.isDirectory()){await mt(e,i,r);continue}if(!n.isFile()||!Rr.test(n.name))continue;let a=P.relative(e,i).split(P.sep).join("/"),c=await xe(i,"utf8").catch(()=>"");r.push({path:a,content:c})}}s(mt,"walk");function yt(e){return{appFactory:e,runSessions:new Map}}s(yt,"createServerRuntime");async function kt(e,t,r,o,n,i){let a=await I(t,e),c=await r.getState(a),u=o.runSessions.get(e);if(u){wt(u,n,i);let g=await r.getState(a),d=g.activeTask?.stage==="run"?g.activeTask:g.lastTasks.run;d&&Tt(u,{type:"task.snapshot",task:d},i);return}if(c.activeTask?.stage==="run"&&c.activeTask.status==="running"){let d={type:"task.failed",task:await r.updateTask(a,c.activeTask.id,{status:"failed",checkpoint:"session_lost",currentAction:"\u8FD0\u884C\u670D\u52A1\u8FDE\u63A5\u5DF2\u65AD\u5F00",error:{code:"RUN_SESSION_LOST",message:"\u540E\u7AEF\u8FD0\u884C\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u53EF\u80FD\u662F\u670D\u52A1\u91CD\u542F\u3002\u8BF7\u91CD\u8BD5\u8FD0\u884C\u3002",retryable:!0}})};i(n,d.type,d),i(n,"error",{type:"error",error:{code:"RUN_SESSION_LOST",message:"\u540E\u7AEF\u8FD0\u884C\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u53EF\u80FD\u662F\u670D\u52A1\u91CD\u542F\u3002\u8BF7\u91CD\u8BD5\u8FD0\u884C\u3002"}}),n.end();return}let p=await r.createTask(a,"run"),l={taskId:p.id,subscribers:new Set,events:[],app:null,snapshotWrite:Promise.resolve()};o.runSessions.set(e,l),wt(l,n,i),Fr(a,p,l,o,r,i)}s(kt,"handleRunRuntime");function ht(e,t){if(!t)return e;let r=e.lastTasks.run;return r?.status==="running"?e:{...e,stage:"run",activeTask:r??e.activeTask,stageRuntime:{...e.stageRuntime,run:{status:"running",taskId:t.taskId,checkpoint:"listening",message:"\u771F\u5B9E\u8FD0\u884C\u670D\u52A1\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u76D1\u542C AI \u8868\u683C\u4E2D\u7684\u5F85\u5904\u7406\u8BB0\u5F55",retryable:!1}}}}s(ht,"overlayRunSessionState");async function Fr(e,t,r,o,n,i){let a=s(u=>{Tt(r,u,i),Cr(u)&&(gt.info("run-runtime","publish run execution event",Mr(u)),r.snapshotWrite=r.snapshotWrite.then(()=>n.appendRunSnapshotEvent(e,u)).catch(p=>{gt.error("run-runtime","\u5199\u5165\u8FD0\u884C\u5FEB\u7167\u5931\u8D25",{projectId:e.id,event:u.type,error:p instanceof Error?p.message:String(p)})}))},"send"),c=s(async(u,p)=>{let l=await n.updateTask(e,t.id,{currentAction:u,checkpoint:p});a({type:"task.progress",taskId:l.id,message:u,checkpoint:p}),a({type:"run.progress",message:u})},"progress");try{a({type:"task.started",task:t}),await c("\u52A0\u8F7D\u771F\u5B9E\u8FD0\u884C\u914D\u7F6E","loading");let u=await o.appFactory(_(e),l=>a(Wr(l)));r.app=u,await c("\u771F\u5B9E\u8FD0\u884C\u670D\u52A1\u5DF2\u8FDE\u63A5","started"),a({type:"run.started",projectId:e.id,workflowName:u.workflow.meta.name,stepCount:u.workflow.orderedStepIds.length,intervalMs:u.settings.polling.interval_ms}),await c("\u771F\u5B9E\u8FD0\u884C\u670D\u52A1\u5DF2\u542F\u52A8\uFF0C\u5F00\u59CB\u76D1\u542C AI \u8868\u683C\u4E2D\u7684\u5F85\u5904\u7406\u8BB0\u5F55","listening"),await u.start();let p=await n.updateTask(e,t.id,{status:"succeeded",checkpoint:"stopped",currentAction:"\u771F\u5B9E\u8FD0\u884C\u670D\u52A1\u5DF2\u505C\u6B62"});a({type:"task.succeeded",task:p}),a({type:"run.stopped",message:"\u771F\u5B9E\u8FD0\u884C\u670D\u52A1\u5DF2\u505C\u6B62"})}catch(u){let p=await n.updateTask(e,t.id,{status:"failed",checkpoint:"failed",currentAction:"\u771F\u5B9E\u8FD0\u884C\u542F\u52A8\u5931\u8D25",error:{code:vt(u),message:jt(u),retryable:!0,details:Pt(u)}});a({type:"task.failed",task:p}),a({type:"error",error:Lr(u)})}finally{o.runSessions.delete(e.id),Nr(r)}}s(Fr,"startRunSession");function Wr(e){switch(e.type){case"record.observed":return{type:"run.record.detected",record:e.record};case"step.started":return{type:"run.step.started",itemId:e.itemId,stepId:e.stepId,stepName:e.stepName};case"step.succeeded":return{type:"run.step.succeeded",itemId:e.itemId,stepId:e.stepId,stepName:e.stepName,logs:e.logs};case"step.failed":return{type:"run.step.failed",itemId:e.itemId,stepId:e.stepId,stepName:e.stepName,error:e.error,logs:e.logs};case"record.blocked":return{type:"run.record.blocked",itemId:e.itemId,stepId:e.stepId,stepName:e.stepName,reason:e.reason,logs:e.logs};case"record.completed":return{type:"run.record.completed",itemId:e.itemId}}}s(Wr,"toRunEventDTO");function Cr(e){return e.type.startsWith("run.record.")||e.type.startsWith("run.step.")}s(Cr,"isRunExecutionEvent");function Mr(e){return e.type==="run.record.detected"?{type:e.type,itemId:e.record.id,state:e.record.state,currentStep:e.record.currentStep}:e.type==="run.record.completed"?{type:e.type,itemId:e.itemId}:{type:e.type,itemId:e.itemId,stepId:e.stepId}}s(Mr,"summarizeRunExecutionEvent");function wt(e,t,r){e.subscribers.add(t);for(let o of e.events)r(t,o.type,o);t.on("close",()=>{e.subscribers.delete(t)})}s(wt,"attachRunSubscriber");function Tt(e,t,r){e.events.push(t),e.events.length>100&&e.events.shift();for(let o of e.subscribers){if(o.destroyed||o.writableEnded){e.subscribers.delete(o);continue}try{r(o,t.type,t)}catch{e.subscribers.delete(o)}}}s(Tt,"publishRunEvent");function Nr(e){for(let t of e.subscribers)t.end();e.subscribers.clear()}s(Nr,"closeRunSubscribers");function Lr(e){return{code:vt(e),message:jt(e),details:Pt(e)}}s(Lr,"apiError");function vt(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:"INTERNAL_ERROR"}s(vt,"errorCode");function jt(e){return e instanceof Error?e.message:String(e)}s(jt,"errorMessage");function Pt(e){if(typeof e=="object"&&e!==null&&"details"in e)return e.details}s(Pt,"errorDetails");function Dt(e,t=1){let r=e.replace(/\s+/g," ").trim();if(!r)return`\u5DE5\u4F5C\u6D41 #${t}`;let o=r.split(/[。.!!?\n]/u)[0]?.split(/[::,,;;]/u)[0]?.trim();return o?o.length>16?o.slice(0,16):o:`\u5DE5\u4F5C\u6D41 #${t}`}s(Dt,"deriveProjectTitleFromSop");function Br(){let e=process.env.AITABLE_WORKFLOW_SSE_HEARTBEAT_MS,t=typeof e=="string"?e.trim():"";if(!t)return 15e3;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>0?r:15e3}s(Br,"readSseHeartbeatMs");function N(e){e.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),$r(e)}s(N,"startSse");function $r(e){let t=Br(),r=setInterval(()=>{if(e.writableEnded||!e.writable){clearInterval(r);return}try{e.write(`:keepalive
|
|
12
12
|
|
|
13
|
-
`)}catch{clearInterval(r)}},t);r.unref?.();let o=s(()=>clearInterval(r),"stop");e.on("close",o),e.on("finish",o)}s(
|
|
13
|
+
`)}catch{clearInterval(r)}},t);r.unref?.();let o=s(()=>clearInterval(r),"stop");e.on("close",o),e.on("finish",o)}s($r,"startSseHeartbeat");function U(e,t,r){e.write(`event: ${t}
|
|
14
14
|
`),e.write(`data: ${JSON.stringify(r)}
|
|
15
15
|
|
|
16
|
-
`)}s(
|
|
16
|
+
`)}s(U,"writeSse");async function bt(e,t,r,o,n,i){let a=await I(t,e),c=await b(o),u=await r.createTask(a,"init");try{let p=Vr(c),l=await Jr({answers:p,cwd:a.dir,force:!0}),g=await Gr(We.join(a.dir,"roles"),c.roles??[]);c.machineId&&i&&await i(e,c.machineId).catch(()=>{});let d=await A(a),k=g.skippedKnowledgeBindings.map(K=>`\u89D2\u8272 ${K.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 role.yml\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${K.knowledge.join(", ")}`);await r.updateTask(a,u.id,{status:"succeeded",checkpoint:"done",currentAction:"\u914D\u7F6E\u5DF2\u5B8C\u6210",outputs:{warnings:k,roleFiles:g.files}});let w=Dt(c.sop,1),T=await oe(d,{title:w});M(n,{project:T,scaffold:l,roleFiles:g.files,files:await S(d),warnings:k})}catch(p){throw await r.updateTask(a,u.id,{status:"failed",checkpoint:"init_failed",currentAction:"\u914D\u7F6E\u751F\u6210\u5931\u8D25",error:{code:x(p),message:v(p),retryable:!0,details:F(p)}}),p}}s(bt,"handleInit");async function It(e,t,r,o,n){let i=await I(t,e),c=(await b(o)).tableId?.trim()??"";if(!c)throw Object.assign(new Error("Table Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"TABLE_ID_REQUIRED",status:422});let u=_(i),p=await Hr(u,"utf8"),l=St.parse(p);if(!Ot(l)||!Ot(l.tracker))throw Object.assign(new Error("\u914D\u7F6E\u6587\u4EF6\u7F3A\u5C11 tracker\uFF0C\u65E0\u6CD5\u5199\u56DE Table Id"),{code:"CONFIG_TRACKER_MISSING",status:500});l.tracker.table_id=c,await Ur(u,St.stringify(l),"utf8");let g=await A(i);M(n,{project:g,files:await S(g),state:await r.getRecoverableState(g)})}s(It,"handleUpdateProjectTableId");async function At(e,t,r,o,n,i,a){let c=await I(t,e),u=await b(i);if(u.action!=="confirm"&&u.action!=="terminate")throw Object.assign(new Error("\u4EBA\u5DE5\u64CD\u4F5C\u53EA\u652F\u6301 confirm \u6216 terminate"),{code:"INVALID_HUMAN_ACTION",status:422});let p=o.runSessions.get(e)?.app;if(!p)throw Object.assign(new Error("\u8FD0\u884C\u670D\u52A1\u672A\u542F\u52A8\uFF0C\u65E0\u6CD5\u5904\u7406\u4EBA\u5DE5\u786E\u8BA4\u64CD\u4F5C"),{code:"RUN_SESSION_REQUIRED",status:409});let l=u.action==="confirm"?p.settings.tracker.states.active[0]:p.settings.tracker.states.terminal.find(w=>w==="\u5DF2\u5173\u95ED")??p.settings.tracker.states.terminal.at(-1);if(!l)throw Object.assign(new Error("\u672A\u914D\u7F6E\u53EF\u7528\u4E8E\u4EBA\u5DE5\u64CD\u4F5C\u7684\u76EE\u6807\u72B6\u6001"),{code:"HUMAN_ACTION_STATE_MISSING",status:500});let g=u.action==="confirm"?"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EE7\u7EED\u6D41\u7A0B":"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EC8\u6B62\u6D41\u7A0B",d=null;u.action==="confirm"&&(d=await Kr(p,n)),await p.tracker.updateState(n,l),d&&await p.tracker.updateCurrentStep(n,d),await p.tracker.appendEvent(n,g);let k=await r.updateRunSnapshotRecord(c,n,u.action==="confirm"?{state:l,status:"running",currentStepId:d??void 0}:{state:l,status:"done",currentStepId:null},g);M(a,{action:u.action,recordId:n,state:k})}s(At,"handleRunHumanAction");async function Kr(e,t){let[r]=await e.tracker.fetchItemsByIds([t]).catch(()=>[]),o=r?.currentStep;if(!o)return null;let n=e.workflow.orderedStepIds.indexOf(o);return n<0?null:e.workflow.orderedStepIds[n+1]??null}s(Kr,"resolveNextStepId");async function Ce(e,t,r,o,n,i){N(i),await kt(e,t,r,o,i,U)}s(Ce,"handleRun");function Vr(e){let t=e.tableBaseId.trim();if(!t)throw Object.assign(new Error("Base Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"BASE_ID_REQUIRED",status:422});let r=e.llmProvider.trim();return{agentType:Qr(e.agentsSelected),scene:Yr(e),baseId:t,tableId:e.tableId?.trim()??"",llmProvider:r,llmModel:r?e.llmModel.trim()||Zr(r):"",llmApiKeyEnv:r?Xr(r):"",confirmed:!0}}s(Vr,"toInitAnswers");function Yr(e){let t=e.roles.map(r=>r.name).filter(Boolean).join("\u3001");return["aitable-workflow \u4E1A\u52A1\u81EA\u52A8\u5316\u573A\u666F\u3002",e.sop.trim()?`\u7528\u6237 SOP\uFF1A
|
|
17
17
|
${e.sop.trim()}`:"\u7528\u6237\u5728 AI \u8868\u683C\u4E2D\u63D0\u4EA4\u4E1A\u52A1\u8BB0\u5F55\uFF0C\u7CFB\u7EDF\u81EA\u52A8\u5B8C\u6210\u5206\u7C7B\u3001\u5904\u7406\u3001\u5BA1\u6838\u4E0E\u56DE\u5199\u3002",t?`\u53C2\u4E0E\u89D2\u8272\uFF1A${t}`:""].filter(Boolean).join(`
|
|
18
18
|
|
|
19
|
-
`)}s(
|
|
20
|
-
`)}}}catch{}if(a!==i.content){let c={path:i.path,content:a};r=r.map((p,l)=>l===n?c:p);let u=de(a);o=o.map((p,l)=>l===n?{path:p.path,sha256:u}:p),t.push(i.path)}}return{...e,files:r,checksums:o,redacted:t.length>0?t:e.redacted}}s(qt,"redactExportBundle");function zt(e){let t=s(r=>r.env.services.projectStore.workflows?null:_(r,501,"WORKFLOWS_NOT_CONFIGURED","\u5DE5\u4F5C\u6D41\u6301\u4E45\u5316\u672A\u914D\u7F6E\uFF08\u9700\u8981 AITABLE_DB_URL\uFF09"),"notConfigured");e.get("/:projectId/workflows",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i}=r.env;return y(r,{workflows:await n.projectStore.workflows.list(r.env.project.id,i)})}),e.post("/:projectId/workflows",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i,incoming:a}=r.env,c=r.env.project,u=await b(a);if(!u.name||!u.name.trim())return _(r,422,"INVALID_INPUT","\u5DE5\u4F5C\u6D41\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let p=await n.projectStore.workflows.create(c.id,{name:u.name,templatePath:u.templatePath,files:u.files},i);await j(c,n);let l={workflow:p.workflow};return p.files&&(l.files=p.files),p.warnings&&p.warnings.length>0&&(l.warnings=p.warnings),y(r,l)}),e.get("/:projectId/workflows/:workflowId",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i}=r.env,a=await n.projectStore.workflows.exportWorkflow(r.env.project.id,r.req.param("workflowId")??"",i);return y(r,{workflow:a.workflow,files:a.files})}),e.delete("/:projectId/workflows/:workflowId",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i}=r.env,a=r.env.project;if(n.runtime.runSessions.has(a.id))return _(r,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664\u5DE5\u4F5C\u6D41");let c=await n.projectStore.workflows.resolve(a.id,r.req.param("workflowId")??"",i);return await n.projectStore.workflows.delete(c,i),await j(a,n),y(r,{ok:!0,id:c.id})}),e.put("/:projectId/workflows/:workflowId/files",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i,incoming:a}=r.env,c=r.env.project,u=await n.projectStore.workflows.resolve(c.id,r.req.param("workflowId")??"",i),p=await b(a);if(!Array.isArray(p.files))return _(r,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");let l=await n.projectStore.workflows.replaceFiles(u,p.files,i);return await j(c,n),y(r,{workflow:u,files:l})}),e.patch("/:projectId/workflows/:workflowId/files",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i,incoming:a}=r.env,c=r.env.project,u=await n.projectStore.workflows.resolve(c.id,r.req.param("workflowId")??"",i),p=await b(a),l=await n.projectStore.workflows.updateFiles(u,{upsert:p.upsert,remove:p.remove},i);return await j(c,n),y(r,{workflow:u,files:l})})}s(zt,"registerWorkflowRoutes");import lo from"path";import{collectDesignContext as Le,runDesign as fo,syncFieldsFromWorkflow as mo,syncViewsFromDesign as go,runAutoDiscovery as wo,buildDesignBrief as yo,logger as ko}from"aitable-workflow-core";var ke=class{static{s(this,"DesignEventBuffer")}capacity;events=[];seq=0;constructor(t=100){this.capacity=t>0?t:100}push(t){this.seq+=1;let r={seq:this.seq,event:t};return this.events.push(r),this.events.length>this.capacity&&this.events.shift(),r}get cursor(){return this.seq}get size(){return this.events.length}replayAfter(t){return t===void 0||Number.isNaN(t)?[...this.events]:this.events.filter(r=>r.seq>t)}};async function Gt(e,t,r,o){let n=await A(t,e),i=await r.getState(n),a=i.lastTasks.design?.status==="failed"?i.lastTasks.design:null;if(a){await r.clearActiveTask(n,a.id),N(o,{task:a,error:{code:"DESIGN_RETRY_REQUIRED",message:a.error?.message??"\u4E0A\u4E00\u6B21 Design \u5DF2\u5931\u8D25\uFF0C\u8BF7\u70B9\u51FB\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u3002",retryable:!0}},409);return}let c=i.activeTask?.stage==="design"?i.activeTask:null,u=c&&(c.status==="running"||c.status==="blocked")?c:await r.createTask(n,"design");try{let p=F(n),l=await Le({configPath:p,yes:!0}),m=await wo({scene:l.scene,configPath:p,mode:"fast"}),d={form:m.form,answers:m.answers,summary:m.summary,confirmed:!1},k=await r.updateTask(n,u.id,{status:"blocked",checkpoint:"discovery_waiting_user",currentAction:"\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u9700\u6C42\u6F84\u6E05",block:{reason:"discovery_required",message:"\u8BF7\u5148\u786E\u8BA4 Design \u9636\u6BB5\u7684\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002",actionLabel:"\u786E\u8BA4\u540E\u5F00\u59CB\u751F\u6210"},outputs:{...u.outputs,discovery:d}});N(o,{task:k,discovery:d})}catch(p){let l=await r.updateTask(n,u.id,{status:"failed",checkpoint:"discovery_precheck",currentAction:"\u9700\u6C42\u6F84\u6E05\u51C6\u5907\u5931\u8D25",error:{code:"DESIGN_PRECHECK_FAILED",message:v(p),retryable:!0,details:W(p)}});N(o,{task:l,error:te(p)},500)}}s(Gt,"handleDesignDiscovery");async function Kt(e,t,r,o,n){let i=await A(t,e),a=await r.getState(i),c=a.activeTask?.stage==="design"?a.activeTask:a.lastTasks.design,u=c?.outputs?.discovery;if(!c||!u){U(n,409,"DISCOVERY_NOT_READY","\u8BF7\u5148\u751F\u6210\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u786E\u8BA4 Design \u8F93\u5165\u3002");return}let p=o.answers??u.answers,l=F(i),m=await Le({configPath:l,yes:!0}),d=await yo({scene:m.scene,filled:[{form:u.form,answers:p}]}),k={...u,answers:p,clarifications:d,summary:d.replace(/\s+/g," ").trim(),confirmed:!0},w=await r.updateTask(i,c.id,{status:"running",checkpoint:"discovery_confirmed",currentAction:"\u9700\u6C42\u6F84\u6E05\u5DF2\u786E\u8BA4\uFF0C\u51C6\u5907\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848",block:void 0,error:void 0,outputs:{...c.outputs,discovery:k,clarifications:d}});N(n,{task:w,discovery:k})}s(Kt,"handleDesignDiscoveryConfirm");async function Vt(e,t,r,o,n,i){let a=await A(t,e);try{n.ensureAvailable()}catch(f){U(o,re(f),E(f),v(f));return}let c=await r.getState(a),u=c.activeTask?.stage==="design"?c.activeTask:null;if(u&&u.status==="blocked"){L(o),q(o,"task.blocked",{type:"task.blocked",task:u}),o.end();return}if(u&&u.status==="running"&&u.checkpoint!=="discovery_confirmed"){L(o),q(o,"task.snapshot",{type:"task.snapshot",task:u}),o.end();return}if(oe.has(a.id)){L(o);let f=ue.get(a.id);if(f){for(let h of f.buffer.replayAfter(i))Re(o,h.seq,h.event);f.subscribers.add(o),o.on("close",()=>f.subscribers.delete(o));return}u&&q(o,"task.snapshot",{type:"task.snapshot",task:u}),o.end();return}let p=c.lastTasks.design,l=p?.outputs?.discovery,m=p?.status==="failed"&&l?.confirmed&&typeof p.outputs?.clarifications=="string",d=u?.checkpoint==="discovery_confirmed"?u:m?await r.updateTask(a,(await r.createTask(a,"design")).id,{checkpoint:"discovery_confirmed",currentAction:"\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1",outputs:{discovery:l,clarifications:p.outputs?.clarifications}}):await r.createTask(a,"design");oe.add(a.id),L(o);let k={buffer:new ke,subscribers:new Set([o])};ue.set(a.id,k),o.on("close",()=>k.subscribers.delete(o));let w=s(f=>Qe(k,f),"send"),T=Date.now(),V=T,ie=0,Y=[],$=[],M=s((f,h,D)=>{let x=Date.now(),X=x-T,ee=x-V;V=x,Y.push({phase:f,message:h,elapsedMs:X,deltaMs:ee,detail:D}),ko.info("design-runtime",h,{projectId:a.id,taskId:d.id,phase:f,elapsedMs:X,deltaMs:ee,...D?{detail:D}:{}}),w({type:"design.progress",phase:f,message:h,elapsedMs:X,deltaMs:ee,detail:D})},"emitProgress"),O=s(async(f,h,D)=>{M(f,h,D);let x=await r.updateTask(a,d.id,{currentAction:h,checkpoint:f});w({type:"task.progress",taskId:x.id,message:h,checkpoint:f})},"progress"),me="",ae=!1,ce=!1,z=s(async()=>{if(ae){ce=!0;return}ae=!0;try{do{ce=!1;let h=(await S(a)).filter(D=>D.path!=="project.json").map(D=>`${D.path}:${D.content}`).join("|");if(h&&h!==me){me=h;let D=await I(a),x=await S(D);M("file_snapshot",`\u540C\u6B65 ${x.length} \u4E2A\u751F\u6210\u6587\u4EF6`,{fileCount:x.length}),w({type:"design.files",files:x})}}while(ce)}finally{ae=!1}},"sendFileSnapshot");try{w({type:"task.started",task:d}),w({type:"design.started",projectId:e}),await z();let f,h;try{await O("precheck","\u8BFB\u53D6 Design \u914D\u7F6E"),h=F(a),f=await Le({configPath:h,yes:!0}),await O("precheck_done","Design \u914D\u7F6E\u8BFB\u53D6\u5B8C\u6210",{agent:f.agentType,timeoutMs:f.agentTimeoutMs})}catch(g){let J=await r.updateTask(a,d.id,{status:"failed",checkpoint:"precheck",currentAction:"Design \u9884\u68C0\u67E5\u5931\u8D25",error:{code:"DESIGN_PRECHECK_FAILED",message:v(g),retryable:!0,details:W(g)}});w({type:"task.failed",task:J}),w({type:"error",error:te(g)}),o.end();return}let D=d.outputs?.discovery,x=typeof d.outputs?.clarifications=="string"?d.outputs.clarifications:D?.clarifications;if(!D?.confirmed||!x){await O("waiting_input","\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u9700\u6C42\u6F84\u6E05");let g=await r.updateTask(a,d.id,{status:"blocked",checkpoint:"discovery_waiting_user",currentAction:"\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u9700\u6C42\u6F84\u6E05",block:{reason:"discovery_required",message:"\u8BF7\u5148\u786E\u8BA4 Design \u9636\u6BB5\u7684\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002",actionLabel:"\u786E\u8BA4\u540E\u5F00\u59CB\u751F\u6210"},outputs:d.outputs});w({type:"task.blocked",task:g}),o.end();return}f.clarifications=x,await O("brief_ready","\u9700\u6C42\u6458\u8981\u5DF2\u786E\u8BA4\uFF0C\u51C6\u5907\u542F\u52A8 Agent"),w({type:"design.discovery",summary:D.summary});let X=f.agentTimeoutMs;await O("agent_start","\u542F\u52A8 Coding Agent \u751F\u6210\u6D41\u7A0B\u65B9\u6848",{agent:f.agentType,timeoutMs:X,timeoutSource:"config",timeoutConfig:"agent.timeout_ms"});let ee=!1,qe=await n.buildDesignExecutor({projectId:a.id,agent:f.agentType,projectDir:a.dir}),H=await fo(f,{...qe?{executor:qe}:{},timeoutMs:X,onRoundStart:s((g,J)=>{M("agent_round",`\u7B2C ${g} \u8F6E ${J?"\u4FEE\u6B63":"\u751F\u6210"}\u5F00\u59CB`,{round:g,isFix:J}),w({type:"design.round_start",round:g,isFix:J})},"onRoundStart"),onEvent:s(g=>{$.push(ho(g)),$.length>30&&$.shift(),ee||(ee=!0,M("agent_first_event",`\u6536\u5230 Agent \u9996\u4E2A\u4E8B\u4EF6\uFF1A${g.type}`,{eventType:g.type})),g.type==="tool_use"&&M("agent_tool","Agent \u8C03\u7528\u5DE5\u5177",{toolName:g.toolName}),(g.type==="text"||g.type==="thinking")&&Date.now()-ie>5e3&&(ie=Date.now(),M("agent_output",g.type==="thinking"?"Agent \u6B63\u5728\u63A8\u7406":"Agent \u8F93\u51FA\u5185\u5BB9",{eventType:g.type,preview:g.content?.replace(/\s+/g," ").slice(0,120)})),w({type:"design.agent_event",event:g}),(g.type==="tool_use"||g.type==="tool_result")&&z()},"onEvent"),onAgentLifecycle:s(g=>{M(To(g.phase),vo(g),jo(g))},"onAgentLifecycle"),onValidation:s((g,J)=>{M("validating",g.valid?"\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u901A\u8FC7":`\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u53D1\u73B0 ${g.errors.length} \u4E2A\u95EE\u9898`,{round:J,valid:g.valid,errorCount:g.errors.length}),w({type:"design.validation",round:J,validation:g}),z()},"onValidation")});if(!H.success){await z();let g=await r.updateTask(a,d.id,{status:"failed",checkpoint:"validating",currentAction:"\u771F\u5B9E\u8BBE\u8BA1\u672A\u901A\u8FC7\u6821\u9A8C",error:{code:"DESIGN_VALIDATION_FAILED",message:H.response,retryable:!0},outputs:{...d.outputs,diagnostics:Ne(T,Y,$,H.validation)}});await Jt(a,g,H.response),w({type:"task.failed",task:g}),w({type:"design.done",success:!1,rounds:H.rounds,response:H.response}),o.end();return}await O("sync_fields","\u540C\u6B65\u5B57\u6BB5\u8BA1\u5212\u5230\u914D\u7F6E"),await mo({workflowPath:f.workflowPath,configPath:h,autoUpdate:!0}),await O("sync_views","\u540C\u6B65\u89C6\u56FE\u8BA1\u5212\u5230\u914D\u7F6E"),await go({viewsPath:lo.resolve(f.workDir,"views.yml"),configPath:h,autoUpdate:!0}).catch(()=>null),await z(),await O("manifest","\u5199\u5165 Design \u4EA7\u7269\u6E05\u5355");let wr=await S(a),ze=Po(a,d,wr);await Fe(a,ze);let yr=await r.updateTask(a,d.id,{status:"succeeded",currentAction:"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210",checkpoint:"done",outputs:{...d.outputs,manifest:ze,diagnostics:Ne(T,Y,$,H.validation)}});w({type:"task.succeeded",task:yr}),w({type:"design.done",success:!0,rounds:H.rounds,response:H.response}),o.end()}catch(f){await z().catch(()=>{});let h=await r.updateTask(a,d.id,{status:"failed",checkpoint:"generating",currentAction:"\u771F\u5B9E\u8BBE\u8BA1\u751F\u6210\u5931\u8D25",error:{code:E(f)==="INTERNAL_ERROR"?"DESIGN_GENERATION_FAILED":E(f),message:v(f),retryable:!0,details:W(f)},outputs:{...d.outputs,diagnostics:Ne(T,Y,$)}});await Jt(a,h,v(f)),w({type:"task.failed",task:h}),w({type:"error",error:te(f)}),w({type:"design.done",success:!1,rounds:0,response:v(f)}),o.end()}finally{Ze(a.id)}}s(Vt,"handleDesign");function ho(e){return e.type==="tool_use"?{type:e.type,toolName:e.toolName,toolInput:e.toolInput}:e.type==="tool_result"||e.type==="error"||e.type==="text"||e.type==="thinking"?{type:e.type,content:e.content?.replace(/\s+/g," ").slice(0,240)}:{type:e.type}}s(ho,"summarizeAgentEvent");function To(e){return`agent_${e}`}s(To,"agentLifecyclePhase");function vo(e){switch(e.phase){case"process_spawned":return"Coding Agent \u8FDB\u7A0B\u5DF2\u542F\u52A8";case"first_stdout":return"Coding Agent \u9996\u6B21\u8F93\u51FA stdout";case"first_stderr":return"Coding Agent \u9996\u6B21\u8F93\u51FA stderr";case"process_closed":return"Coding Agent \u8FDB\u7A0B\u5DF2\u9000\u51FA"}}s(vo,"agentLifecycleMessage");function jo(e){return{provider:e.provider,phase:e.phase,elapsedMs:e.elapsedMs,...e.pid?{pid:e.pid}:{},...e.cmd?{cmd:e.cmd}:{},...e.cwd?{cwd:e.cwd}:{},...e.exitCode!==void 0?{exitCode:e.exitCode}:{}}}s(jo,"sanitizeAgentLifecycle");function Ne(e,t,r,o){return{elapsedMs:Date.now()-e,timeline:t.slice(-40),recentAgentEvents:r,validation:o}}s(Ne,"buildDesignDiagnostics");function Po(e,t,r){let o=r.filter(a=>a.path==="workflow.yml"||a.path==="views.yml"||a.path.startsWith("recipes/")).map(a=>({path:a.path,kind:a.path==="workflow.yml"?"workflow":a.path==="views.yml"?"views":"recipe",checksum:de(a.content),required:a.path==="workflow.yml"||a.path.startsWith("recipes/")})),n=o.filter(a=>a.required).map(a=>a.path),i=new Date().toISOString();return{projectId:e.id,taskId:t.id,designVersion:t.attempt,status:"ready",expected:n,generated:o,validation:{passed:!0,errors:[],warnings:[]},createdAt:t.startedAt,updatedAt:i}}s(Po,"buildDesignManifest");async function Jt(e,t,r){let o=new Date().toISOString();await Fe(e,{projectId:e.id,taskId:t.id,designVersion:t.attempt,status:"invalid",expected:["workflow.yml"],generated:[],validation:{passed:!1,errors:[r],warnings:[]},createdAt:t.startedAt,updatedAt:o})}s(Jt,"writeInvalidDesignManifest");import xo from"path";import{loadSettings as Eo,resolveConfigPath as _o,loadWorkflowTemplate as Fo,initTable as Wo,ensureTableExists as Co,syncViewsFromDesign as Mo,runWithExecutor as No,runWithDwsRunner as Lo,DwsError as Bo,logger as $o}from"aitable-workflow-core";var Do={singleSelect:"single_select",multipleSelect:"multiple_select",date:"datetime"},So={Grid:"grid",FormDesigner:"form",Kanban:"kanban",Calendar:"calendar",Gantt:"gantt"};function Yt(e,t){let r=new Map,o=new Map((e.tracker.field_definitions??[]).map(c=>[c.name,c])),n=s((c,u,p="text",l)=>{if(!c?.trim()||r.has(c))return;let m=o.get(c);r.set(c,{id:Io(c),name:c,type:Ao(m?.type??p),...m?.options??l?{options:m?.options??l}:{},group:u})},"addField");for(let c of t.referencedFields.userInput)n(c,"business");for(let c of t.referencedFields.output)n(c,"business");for(let c of t.referencedFields.other)n(c,"business");for(let c of e.tracker.field_definitions??[])n(c.name,"business",c.type,c.options);n(e.tracker.fields.title,"business"),n(e.tracker.fields.description,"business"),n(e.tracker.fields.state,"process","singleSelect",bo(e)),n(e.tracker.fields.current_step,"process"),n(e.tracker.fields.owner,"process","user"),n(e.tracker.fields.deadline,"process","date"),n(e.tracker.fields.event_log,"process");let i=Oo(e.tracker.views??[],t).map(c=>({id:c.id,name:c.name,kind:So[c.type]??"grid",desc:c.description??Ro(c)})),a=[...r.values()];return{fieldCount:a.length,viewCount:i.length,fields:a,views:i}}s(Yt,"buildSetupSchemaSummary");function Oo(e,t){let r=[],o=2;for(let n of e){if(!n.for_each_step){r.push(n);continue}let i=t.steps.filter(a=>n.for_each_step==="needs_human"?!!a.needs_human:!0);for(let a of i){let c=String.fromCodePoint(9311+o);r.push({...n,id:`step_${a.id}`,name:`${c} ${a.name}`,visible_fields:[...Object.values(a.input_mapping??{}),...Object.values(a.output_mapping??{})],description:a.needs_human?.reason??n.description,for_each_step:void 0}),o++}}return r}s(Oo,"expandViews");function bo(e){return[e.tracker.states.initial,...e.tracker.states.active,...e.tracker.states.terminal,e.tracker.states.blocked,e.tracker.states.review].filter((t,r,o)=>!!t&&o.indexOf(t)===r)}s(bo,"stateOptions");function Ao(e){return Do[e]??e}s(Ao,"displayFieldType");function Io(e){return`fld_${e.replace(/[^\p{L}\p{N}]+/gu,"_").replace(/^_+|_+$/g,"")||"field"}`}s(Io,"fieldId");function Ro(e){return e.type==="FormDesigner"?"\u8868\u5355\u5F55\u5165\u89C6\u56FE":e.type==="Kanban"?e.group_by?`\u6309 ${e.group_by} \u5206\u7EC4`:"\u770B\u677F\u89C6\u56FE":e.type==="Calendar"?e.date_field?`\u6309 ${e.date_field} \u67E5\u770B`:"\u65E5\u5386\u89C6\u56FE":e.type==="Gantt"?"\u7518\u7279\u89C6\u56FE":"\u8868\u683C\u89C6\u56FE"}s(Ro,"viewDescription");async function Be(e,t,r,o,n){let i=await A(t,e);try{n.ensureAvailable()}catch(d){U(o,re(d),E(d),v(d));return}let a=await r.getState(i);if(a.activeTask?.stage==="setup"&&a.activeTask.status==="running"){L(o),q(o,"task.snapshot",{type:"task.snapshot",task:a.activeTask}),o.end();return}let c=a.activeTask?.stage==="setup"&&a.activeTask.status==="blocked"?await r.updateTask(i,a.activeTask.id,{status:"running",currentAction:"\u91CD\u65B0\u68C0\u67E5\u6388\u6743\u5E76\u7EE7\u7EED\u642D\u5EFA",block:void 0,error:void 0}):await r.createTask(i,"setup");L(o);let u=s(d=>q(o,d.type,d),"send"),p=s(async(d,k)=>{let w=await r.updateTask(i,c.id,{currentAction:d,checkpoint:k});u({type:"task.progress",taskId:w.id,message:d,checkpoint:k}),u({type:"setup.progress",message:d})},"progress"),l=n.buildSetupExecutor({projectId:i.id,projectDir:i.dir}),m=n.buildDwsRunner();try{await No(l,async()=>{await Lo(m,async()=>{u({type:"task.started",task:c}),u({type:"setup.started",projectId:e}),await p("\u52A0\u8F7D\u914D\u7F6E\u4E0E\u5DE5\u4F5C\u6D41\u6A21\u677F","preflight"),await Mo({viewsPath:xo.resolve(i.dir,"views.yml"),configPath:F(i),autoUpdate:!0}).catch(O=>($o.warn("setup","setup \u524D\u540C\u6B65 views.yml \u5931\u8D25\uFF0C\u7EE7\u7EED\u4F7F\u7528 config \u4E2D\u7684\u89C6\u56FE\u914D\u7F6E",{error:v(O)}),null));let d=await Eo(F(i),{lenientEnv:!0}),k=await Fo(d.workflowTemplatePath,{envSource:d.envSource}),w=d.tracker.base_id==="__placeholder__"?void 0:d.tracker,T=w??k.tracker,V=!!T&&!T.table_id.trim();if(T&&!T.table_id.trim()){let O=w?await _o(F(i)):d.workflowTemplatePath,me=w?d:{...d,tracker:T},ae=await Co({trackerFilePath:O,settings:me,workflow:k,onProgress:s((ce,z)=>p(ce,z),"onProgress")});d={...d,tracker:ae.tracker}}await p("\u5F00\u59CB\u521B\u5EFA\u5B57\u6BB5\u548C\u89C6\u56FE","sync_schema");let ie=await Wo({settings:d,workflow:k,cleanEmptyRows:!0,tableJustCreated:V});for(let O of ie.warnings)await p(`\u6CE8\u610F\uFF1A${O.message}`,"sync_schema");let Y=Yt(d,k),$=ie.warnings.map(O=>O.message);await I(i);let M=await r.updateTask(i,c.id,{status:"succeeded",currentAction:"AI \u8868\u683C\u642D\u5EFA\u5B8C\u6210",checkpoint:"done",outputs:{tableUrl:We(d.tracker.base_id,d.tracker.table_id),baseId:d.tracker.base_id,tableId:d.tracker.table_id,schema:Y,warnings:$}});u({type:"task.succeeded",task:M}),u({type:"setup.done",tableUrl:We(d.tracker.base_id,d.tracker.table_id),baseId:d.tracker.base_id,tableId:d.tracker.table_id,schema:Y,warnings:$}),o.end()})})}catch(d){if(Ho(d)){let w=v(d),T=await r.updateTask(i,c.id,{status:"blocked",checkpoint:"preflight",currentAction:"\u7B49\u5F85 AI \u8868\u683C\u6388\u6743",block:{reason:"auth_required",message:`\u6388\u6743\u6216\u6743\u9650\u4E0D\u8DB3\uFF1A${w}`,actionLabel:"\u6211\u5DF2\u5B8C\u6210\u6388\u6743\uFF0C\u7EE7\u7EED\u642D\u5EFA",help:"\u8BF7\u6267\u884C dws auth login\uFF0C\u5E76\u786E\u8BA4\u5F53\u524D\u8D26\u53F7\u53EF\u8BBF\u95EE\u76EE\u6807 Base/Table\u3002"}});u({type:"task.blocked",task:T}),o.end();return}let k=await r.updateTask(i,c.id,{status:"failed",currentAction:"AI \u8868\u683C\u642D\u5EFA\u5931\u8D25",error:{code:E(d),message:v(d),retryable:!0,details:W(d)}});u({type:"task.failed",task:k}),u({type:"error",error:te(d)}),o.end()}}s(Be,"handleSetup");function Ho(e){let t=v(e).toLowerCase(),r=e instanceof Bo?e.stderr.toLowerCase():"",o=`${t} ${r}`;return["auth","login","permission","unauthorized","forbidden","access denied"].some(n=>o.includes(n))}s(Ho,"isSetupAuthBlocker");function Qt(e){e.post("/:projectId/tasks/:stage/:taskAction",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project,a=t.req.param("stage")??"",c=t.req.param("taskAction")??"",u=c==="start"||c==="continue"||c==="retry";if(u&&a==="setup"){await j(i,r),await Be(i.id,r.workspace,r.projectStore.instances,n,G(t));return}if(u&&a==="run"){await j(i,r),await Me(i.id,r.workspace,r.projectStore.instances,r.runtime,o,n);return}U(n,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")})),e.post("/:projectId/design/discovery",C(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await j(n,r),await Gt(n.id,r.workspace,r.projectStore.instances,o)})),e.post("/:projectId/design/discovery/confirm",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r);let a=await b(o);await Kt(i.id,r.workspace,r.projectStore.instances,a,n)})),e.post("/:projectId/design",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r);let a=new URL(t.req.url),c=Xe(a,o);await Vt(i.id,r.workspace,r.projectStore.instances,n,G(t),c),await pe(r,i,"design")})),e.post("/:projectId/setup",C(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await j(n,r),await Be(n.id,r.workspace,r.projectStore.instances,o,G(t)),await pe(r,n,"setup")})),e.post("/:projectId/run/records/:recordId/human-action",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r),await It(i.id,r.workspace,r.projectStore.instances,r.runtime,t.req.param("recordId")??"",o,n)})),e.post("/:projectId/run",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r),await Me(i.id,r.workspace,r.projectStore.instances,r.runtime,o,n)}))}s(Qt,"registerStageRoutes");function Xt(){let e=new Uo;return e.get("/",async t=>y(t,{projects:await t.env.services.projectStore.projects.list(t.env.scope)})),e.post("/",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=await b(n),a=await r.projectStore.projects.create(o,{title:i.title,files:i.files});await j(a,r);let c={project:a};return a.files&&(c.files=a.files),a.warnings&&a.warnings.length>0&&(c.warnings=a.warnings),y(t,c)}),e.use("/:projectId",Ie),e.use("/:projectId/*",Ie),e.delete("/:projectId",async t=>{let{services:r,scope:o}=t.env,n=t.env.project;return r.runtime.runSessions.has(n.id)?_(t,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664"):(await r.projectStore.projects.delete(n,o),await ge(n),await et(r,n.id),y(t,{ok:!0,id:n.id}))}),e.patch("/:projectId",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=await b(n);return y(t,{project:await r.projectStore.projects.updateMeta(t.env.project,{title:i.title},o)})}),e.post("/:projectId/init",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r);let a=G(t);await bt(i.id,r.workspace,r.projectStore.instances,o,n,(c,u)=>a.bindProjectMachine(c,u)),await pe(r,i,"init")})),e.get("/:projectId/engine",async t=>{let r=t.env.project,o=G(t),n=await o.getProjectMachine(r.id);if(!n)return y(t,{machineId:null,machine:null,status:"unbound"});let i=o.isMachineOnline(n),c=(o.listMachines()??[]).find(u=>u.machineId===n);return y(t,{machineId:n,machine:c??null,status:i?"online":"offline"})}),e.put("/:projectId/engine",async t=>{let{incoming:r}=t.env,o=await b(r);return o.machineId?(await G(t).bindProjectMachine(t.env.project.id,o.machineId),y(t,{ok:!0,machineId:o.machineId})):_(t,422,"INVALID_INPUT","machineId \u4E0D\u80FD\u4E3A\u7A7A")}),e.get("/:projectId/files",async t=>{let r=t.env.project;return y(t,{project:r,files:await S(r)})}),e.put("/:projectId/files",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=t.env.project,a=await b(n);if(!Array.isArray(a.files))return _(t,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");let c=await r.projectStore.projects.replaceFiles(i,a.files,o),u=await j(i,r);return y(t,{project:u.project,files:c})}),e.patch("/:projectId/files",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=t.env.project,a=await b(n),c=await r.projectStore.projects.updateFiles(i,{upsert:a.upsert,remove:a.remove},o),u=await j(i,r);return y(t,{project:u.project,files:c})}),e.get("/:projectId/export",async t=>{let{services:r,scope:o}=t.env,n=t.env.project,i=await r.projectStore.projects.exportProject(n,o),a=qt(i),c=r.projectStore.workflows;if(c){let u=await Promise.all((await c.list(n.id,o)).map(async p=>{let l=await c.exportWorkflow(n.id,p.id,o);return{workflow:l.workflow,files:l.files}}));return y(t,{...a,workflows:u})}return y(t,a)}),e.post("/:projectId/validate",async t=>{let r=t.env.project,o=le.join(r.dir,"workflow.yml"),n=le.join(r.dir,"recipes"),i=le.join(r.dir,"views.yml"),a=await qo(o,n,i);return await Rt(r,a),y(t,a)}),e.get("/:projectId/workflow",async t=>{let r=t.env.project,o=await zo(r.dir),n=le.join(r.dir,"workflow.yml"),i=await Zt(n,{envSource:o}).catch(()=>Zt(n)),a=le.join(r.dir,"recipes"),c=i.steps.map(u=>({...u,requires_agent:u.recipe?_t(a,u.recipe):!!u.prompt}));return y(t,{workflow:{...i,steps:c}})}),e.post("/:projectId/reset-workflow",async t=>{let r=await ct(t.env.project);return y(t,{project:r,files:await S(r)})}),e.get("/:projectId/state",async t=>{let{services:r}=t.env,o=t.env.project,n=await r.projectStore.instances.getRecoverableState(o);return y(t,ht(n,r.runtime.runSessions.get(o.id)))}),e.patch("/:projectId/table-id",C(async t=>{let{services:r,incoming:o,outgoing:n}=t.env;await At(t.env.project.id,r.workspace,r.projectStore.instances,o,n)})),zt(e),Qt(e),e}s(Xt,"projectRoutes");function er(){let e=new Jo;return e.onError((t,r)=>_(r,re(t),E(t),v(t),W(t))),e.notFound(t=>_(t,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")),e.use("*",async(t,r)=>{t.env.scope=await t.env.services.identityService.resolveScope(t.env.incoming);let o=t.req.path,n=t.req.method;if(!(Ve(o,n)||n==="GET"&&o==="/api/public-config")&&!await t.env.services.identityService.authenticate(t.env.incoming))return Ye(t);await r()}),e.get("/api/health",t=>y(t,{ok:!0})),e.get("/check.node",t=>t.text("success")),e.get("/api/public-config",t=>{let r=process.env.RELAY_PUBLIC_GATEWAY_URL?.trim();return y(t,{authEnabled:t.env.services.identityService.authRequired,...r?{relayGatewayUrl:r}:{}})}),e.route("/api/projects",Xt()),e.get("/api/agents",t=>y(t,Go())),e}s(er,"createHonoApp");import{createApp as vn,logger as jn}from"aitable-workflow-core";function tr(e){return{create:s(async(t,r)=>{let o=await at(e),n=[];if(r?.files&&r.files.length>0){let i=await ye(o,r.files);n.push(...i.warnings);let a=await I(o);return r.title&&r.title.trim()&&(a=await ne(a,{title:r.title.trim()})),{...a,files:i.written,warnings:n}}if(r?.title&&r.title.trim()){let i=await ne(o,{title:r.title.trim()});return n.length?{...i,warnings:n}:{...i}}return n.length?{...o,warnings:n}:{...o}},"create"),list:s(async t=>_e(e),"list"),resolve:s(async(t,r)=>A(e,t),"resolve"),updateMeta:s(async(t,r,o)=>ne(t,r),"updateMeta"),delete:s(async(t,r)=>{await ge(t)},"delete"),updateFiles:s(async(t,r,o)=>(r.remove&&r.remove.length>0&&await $t(t,r.remove),r.upsert&&r.upsert.length>0&&await ye(t,r.upsert),await I(t),S(t)),"updateFiles"),replaceFiles:s(async(t,r,o)=>(await Ht(t,r),await I(t),S(t)),"replaceFiles"),exportProject:s(async(t,r)=>Ut(t),"exportProject"),syncHotFields:s(async()=>{},"syncHotFields")}}s(tr,"createLocalProjectRepository");import{randomUUID as rn}from"crypto";import{mkdir as or,readFile as nr,rm as on,writeFile as sr}from"fs/promises";import Q from"path";import{applyRunExecutionEvent as nn}from"aitable-workflow-core";var $e=["init","design","setup","run"];function Te(e,t){let r={...e.lastTasks,[t.stage]:t},o=rr(t.status)?t:e.activeTask?.id===t.id?null:e.activeTask;return B({id:t.projectId,dir:"",createdAt:"",updatedAt:t.updatedAt},{...e,projectId:t.projectId,stage:t.stage,activeTask:o,lastTasks:r,updatedAt:t.updatedAt})}s(Te,"mergeTaskIntoState");function B(e,t){let r=new Date().toISOString(),o=t.lastTasks??{},n=t.activeTask??Object.values(o).find(a=>a&&rr(a.status))??null,i=t.stage??n?.stage??en(o)?.stage??"init";return{projectId:t.projectId??e.id,stage:i,activeTask:n,lastTasks:o,stageRuntime:{init:he("init",o.init,n,o,i),design:he("design",o.design,n,o,i),setup:he("setup",o.setup,n,o,i),run:he("run",o.run,n,o,i)},runSnapshot:t.runSnapshot,updatedAt:t.updatedAt??e.updatedAt??r}}s(B,"normalizeProjectState");function rr(e){return e==="running"||e==="blocked"}s(rr,"isActiveStatus");function ve(e){return e==="failed"||e==="succeeded"||e==="cancelled"}s(ve,"isTerminalStatus");function he(e,t,r,o,n){let i=r?.stage===e?r:t;return i?{status:i.status,taskId:i.id,checkpoint:i.checkpoint,message:i.block?.message??i.error?.message??i.currentAction??tn(i.status),retryable:i.error?.retryable??(i.status==="blocked"||i.status==="failed"),block:i.block,error:i.error,recoveryAction:Yo(i)}:Ko(e,o,n)?{status:"succeeded",message:Vo(e),retryable:!1}:{status:"idle",message:"\u5C1A\u672A\u5F00\u59CB"}}s(he,"runtimeForStage");function Ko(e,t,r){let o=$e.indexOf(e);return $e.indexOf(r)>o?!0:$e.slice(o+1).some(i=>!!t[i])}s(Ko,"isPreviousStage");function Vo(e){return e==="init"?"\u914D\u7F6E\u5DF2\u5B8C\u6210":e==="design"?"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210":e==="setup"?"AI \u8868\u683C\u642D\u5EFA\u5B8C\u6210":"\u8FD0\u884C\u9636\u6BB5\u5DF2\u5B8C\u6210"}s(Vo,"inferredSuccessMessage");function Yo(e){if(e.status==="blocked"&&e.stage==="design"&&e.block?.reason==="discovery_required")return{type:"confirm_input",label:e.block.actionLabel,description:e.block.message,api:{method:"POST",path:`/api/projects/${e.projectId}/design/discovery/confirm`}};if(e.status==="blocked")return{type:"continue",label:e.block?.actionLabel??Qo(e.stage),description:e.block?.message??e.currentAction,api:{method:"POST",path:`/api/projects/${e.projectId}/tasks/${e.stage}/continue`}};if(e.status==="failed"&&e.error?.retryable)return{type:"retry",label:Zo(e.stage),description:e.error.message,api:{method:"POST",path:Xo(e)}}}s(Yo,"recoveryActionForTask");function Qo(e){return e==="setup"?"\u7EE7\u7EED\u642D\u5EFA":e==="design"?"\u7EE7\u7EED\u8BBE\u8BA1":e==="run"?"\u7EE7\u7EED\u8FD0\u884C":"\u7EE7\u7EED"}s(Qo,"continueLabel");function Zo(e){return e==="design"?"\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1":e==="setup"?"\u91CD\u8BD5\u642D\u5EFA":e==="run"?"\u91CD\u8BD5\u8FD0\u884C":"\u91CD\u8BD5"}s(Zo,"retryLabel");function Xo(e){return e.stage==="design"?`/api/projects/${e.projectId}/design`:`/api/projects/${e.projectId}/tasks/${e.stage}/retry`}s(Xo,"retryPath");function en(e){return Object.values(e).filter(t=>!!t).sort((t,r)=>r.updatedAt.localeCompare(t.updatedAt))[0]??null}s(en,"latestTask");function tn(e){return e==="running"?"\u4EFB\u52A1\u8FD0\u884C\u4E2D":e==="blocked"?"\u4EFB\u52A1\u7B49\u5F85\u5904\u7406":e==="failed"?"\u4EFB\u52A1\u5931\u8D25":e==="succeeded"?"\u4EFB\u52A1\u5B8C\u6210":e==="cancelled"?"\u4EFB\u52A1\u5DF2\u53D6\u6D88":"\u5C1A\u672A\u5F00\u59CB"}s(tn,"statusMessage");var je=new Map,sn=/^[a-zA-Z0-9_-]+$/;function ir(e){return{getState:Z,getRecoverableState:fn,createTask:un,updateTask:pn,clearActiveTask:mn,appendRunSnapshotEvent:dn,updateRunSnapshotRecord:ln,deleteProjectState:s(t=>an(e,t),"deleteProjectState")}}s(ir,"createLocalWorkflowInstanceStore");async function an(e,t){Ue(t);let r=cn(e,t);await on(Q.join(r,"runtime"),{recursive:!0,force:!0})}s(an,"deleteProjectState");function cn(e,t){return Ue(t),Q.join(e.projectsRoot,t)}s(cn,"projectDir");async function un(e,t){return se(e,async()=>{await De(e);let r=await Z(e),o=(r.lastTasks[t]?.attempt??0)+1,n=new Date().toISOString(),i={id:`task_${rn().slice(0,8)}`,projectId:e.id,stage:t,status:"running",attempt:o,startedAt:n,updatedAt:n,currentAction:"\u4EFB\u52A1\u5DF2\u542F\u52A8"};return await Pe(e,i),await K(e,Te(r,i)),i})}s(un,"createTask");async function pn(e,t,r){return se(e,async()=>{let o=await wn(e,t),n=new Date().toISOString(),i={...o,...r,id:o.id,projectId:o.projectId,stage:o.stage,attempt:o.attempt,startedAt:o.startedAt,updatedAt:n,completedAt:r.completedAt??(ve(r.status)?n:o.completedAt),block:Object.prototype.hasOwnProperty.call(r,"block")?r.block:ve(r.status)?void 0:o.block};await Pe(e,i);let a=await Z(e);return await K(e,Te(a,i)),i})}s(pn,"updateTask");async function Z(e){await De(e);let t=await nr(cr(e),"utf8").catch(()=>"");if(t.trim()){let r=yn(t),o=B(e,r);return r.repaired&&await K(e,o),o}return B(e,{projectId:e.id,stage:"init",activeTask:null,lastTasks:{},updatedAt:e.updatedAt})}s(Z,"getState");async function dn(e,t){return se(e,async()=>{let r=await Z(e),o=nn(r.runSnapshot??{records:[],logs:[]},t),n=B(e,{...r,runSnapshot:o,updatedAt:new Date().toISOString()});return await K(e,n),n})}s(dn,"appendRunSnapshotEvent");async function ln(e,t,r,o){return se(e,async()=>{let n=await Z(e);if(!n.runSnapshot)return n;let i=Date.now(),a={records:hn(n.runSnapshot.records,t,u=>({...u,...r,updatedAt:i})),logs:o?Tn(n.runSnapshot.logs,t,r.currentStepId??"run","info",o):n.runSnapshot.logs},c=B(e,{...n,runSnapshot:a,updatedAt:new Date().toISOString()});return await K(e,c),c})}s(ln,"updateRunSnapshotRecord");async function fn(e){return se(e,async()=>{let t=await Z(e),r=t.lastTasks.design,o=await ut(e);if(o.status==="ready"){if(!r||r.status==="succeeded")return t;let c=new Date().toISOString(),u={...r,status:"succeeded",updatedAt:c,completedAt:r.completedAt??c,currentAction:"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210",checkpoint:"done",block:void 0,error:void 0};await Pe(e,u);let p=B(e,{...t,stage:t.stage==="design"?"setup":t.stage,activeTask:t.activeTask?.stage==="design"?null:t.activeTask,lastTasks:{...t.lastTasks,design:u},updatedAt:c});return await K(e,p),p}if(r?.status!=="succeeded")return t;let n=new Date().toISOString(),i={...r,status:"failed",updatedAt:n,completedAt:n,currentAction:o.status==="artifact_missing"?"\u8BBE\u8BA1\u4EA7\u7269\u7F3A\u5931\uFF0C\u7B49\u5F85\u91CD\u65B0\u751F\u6210":"\u8BBE\u8BA1\u4EA7\u7269\u72B6\u6001\u5F02\u5E38\uFF0C\u7B49\u5F85\u91CD\u65B0\u751F\u6210",checkpoint:o.status,error:{code:o.status==="artifact_missing"?"ARTIFACT_MISSING":"DESIGN_ARTIFACT_INVALID",message:o.errors.join("\uFF1B")||"\u8BBE\u8BA1\u4EA7\u7269\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u3002",retryable:!0,details:{missing:o.missing}}},a=B(e,{...t,stage:"design",activeTask:null,lastTasks:{...t.lastTasks,design:i},updatedAt:n});return await Pe(e,i),await K(e,a),a})}s(fn,"getRecoverableState");async function mn(e,t){return se(e,async()=>{let r=await Z(e);if(r.activeTask?.id!==t)return r;let o=B(e,{...r,activeTask:null,updatedAt:new Date().toISOString()});return await K(e,o),o})}s(mn,"clearActiveTask");function He(e){return Q.join(e.dir,"runtime")}s(He,"runtimeDir");function gn(e){return Q.join(He(e),"artifacts")}s(gn,"artifactsDir");function ar(e){return Q.join(He(e),"tasks")}s(ar,"tasksDir");function cr(e){return Q.join(He(e),"state.json")}s(cr,"statePath");function ur(e,t){return Ue(t),Q.join(ar(e),`${t}.json`)}s(ur,"taskPath");async function De(e){await or(ar(e),{recursive:!0}),await or(gn(e),{recursive:!0})}s(De,"ensureRuntimeDirs");async function wn(e,t){let r=await nr(ur(e,t),"utf8");return JSON.parse(r)}s(wn,"readTask");async function Pe(e,t){await De(e),await sr(ur(e,t.id),`${JSON.stringify(t,null,2)}
|
|
21
|
-
`,"utf8")}s(
|
|
22
|
-
`,"utf8")}s(
|
|
19
|
+
`)}s(Yr,"buildScene");function Qr(e){return e.includes("qoder")?"qoder":e.includes("codex")?"codex":"claudecode"}s(Qr,"toAgentType");function Zr(e){return e==="openai"?"gpt-4o":e==="anthropic"?"claude-sonnet-4-20250514":e==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}s(Zr,"defaultModel");function Xr(e){return e==="openai"?"OPENAI_API_KEY":e==="anthropic"?"ANTHROPIC_API_KEY":e==="dashscope"?"DASHSCOPE_API_KEY":e==="idealab"?"IDEALAB_API_KEY":"LLM_API_KEY"}s(Xr,"defaultApiKeyEnv");async function Rt(e,t){let r=We.join(e.dir,"aitable-workflow.config.yml");try{await qr(r)}catch{t.warnings.push("aitable-workflow.config.yml \u4E0D\u5B58\u5728\uFF08\u9879\u76EE\u7EA7\u914D\u7F6E\u7F3A\u5931\uFF0C\u8FD0\u884C\u524D\u9700\u8981\u751F\u6210\uFF09")}let o=We.join(e.dir,"roles");try{(await zr(o).catch(()=>[])).some(a=>a.endsWith(".role.yml")||a.endsWith(".role.yaml"))||t.warnings.push("roles \u76EE\u5F55\u65E0 .role.yml \u89D2\u8272\u6587\u4EF6\uFF08design \u9636\u6BB5 recipe \u9700\u7ED1\u5B9A role\uFF09")}catch{t.warnings.push("roles \u76EE\u5F55\u4E0D\u5B58\u5728\uFF08design \u9636\u6BB5 recipe \u9700\u7ED1\u5B9A role\uFF09")}}s(Rt,"augmentProjectFileValidation");import xt from"fs";import eo from"path";var to=/requiresAgent\s*:\s*(true|false)/,Et=new Map;function _t(e,t){if(!t)return!1;for(let r of[".recipe.ts",".recipe.js"]){let o=eo.join(e,`${t}${r}`);try{let n=xt.statSync(o);if(!n.isFile())continue;let i=`${n.mtimeMs}:${n.size}`,a=Et.get(o);if(a?.signature===i)return a.requiresAgent;let u=xt.readFileSync(o,"utf8").match(to),p=u?u[1]==="true":!1;return Et.set(o,{signature:i,requiresAgent:p}),p}catch(n){if(n.code==="ENOENT")continue;return!1}}return!1}s(_t,"readRecipeRequiresAgent");import{rm as Wt,mkdir as ro,writeFile as oo}from"fs/promises";import de from"path";import no from"yaml";import{isRecord as so,resolveInsideRoot as io}from"aitable-workflow-core";var Ft=/\.(json|ya?ml|ts|js|md|txt)$/i,ao=new Set(["runtime","traces","node_modules"]),Ct="aitable-workflow.config.yml";function Mt(e,t){try{io(e,t,{allowRoot:!1})}catch{throw Object.assign(new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u76EE\u5F55: ${t}`),{code:"invalid_path",status:400})}}s(Mt,"assertSafeRelativePath");function Nt(e,t){Mt(e.dir,t)}s(Nt,"assertSafeProjectPath");function xs(e){Mt("/workflow-root",e)}s(xs,"assertSafeWorkflowPath");function Lt(e){let r=$t(e).split("/")[0]??"";return ao.has(r)}s(Lt,"isForbiddenWritable");function co(e){if(Lt(e))throw Object.assign(new Error(`\u7981\u6B62\u5199\u5165\u53D7\u4FDD\u62A4\u76EE\u5F55: ${e}`),{code:"invalid_path",status:400});if(!Ft.test(e))throw Object.assign(new Error(`\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8\u5199\u5165: ${e}\uFF08\u4EC5\u5141\u8BB8 ${Ft.source}\uFF09`),{code:"invalid_path",status:400})}s(co,"assertWritableKind");function Bt(e){let t=$t(e);return t===Ct||t.endsWith(".config.yml")?"config":t==="workflow.yml"?"workflow":t==="views.yml"?"views":t.startsWith("recipes/")?"recipe":t.startsWith("roles/")?"role":"other"}s(Bt,"kindOf");function $t(e){return de.posix.normalize(e.replace(/\\/g,"/")).replace(/^\.\//,"")}s($t,"normalizeLogicalPath");function uo(e){let t=[],r;try{r=no.parse(e)}catch(n){return t.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),t}if(!so(r))return t.push("aitable-workflow.config.yml \u9876\u5C42\u5E94\u4E3A\u5BF9\u8C61"),t;let o=r.scene;return(typeof o!="string"||o.trim()==="")&&t.push("aitable-workflow.config.yml \u7F3A\u5C11 scene \u5B57\u6BB5\uFF08\u5EFA\u8BAE\u586B\u5199\u4E1A\u52A1\u573A\u666F\u63CF\u8FF0\uFF09"),t}s(uo,"validateConfigScene");async function we(e,t){let r=[],o=[];for(let n of t){Nt(e,n.path),co(n.path);let i=de.join(e.dir,n.path);await ro(de.dirname(i),{recursive:!0}),await oo(i,n.content,"utf8"),r.push({path:n.path,content:n.content}),n.path===Ct&&o.push(...uo(n.content))}return{written:r,warnings:o}}s(we,"writeProjectFiles");async function Ht(e,t){for(let r of t){if(Nt(e,r),Lt(r))throw Object.assign(new Error(`\u7981\u6B62\u5220\u9664\u53D7\u4FDD\u62A4\u76EE\u5F55: ${r}`),{code:"invalid_path",status:400});await Wt(de.join(e.dir,r),{force:!0})}}s(Ht,"removeProjectFiles");async function Ut(e,t){let r=await po(e);for(let o of r)await Wt(de.join(e.dir,o),{force:!0}).catch(()=>{});return we(e,t)}s(Ut,"replaceProjectFiles");async function po(e){return(await S(e)).map(r=>r.path).filter(r=>Bt(r)!=="other")}s(po,"collectBusinessFiles");function lo(e){return pe(e.content)}s(lo,"checksumFile");async function qt(e){let t=await S(e),r=t.map(o=>({path:o.path,sha256:lo(o)}));return{project:e,files:t,checksums:r,exportedAt:new Date().toISOString()}}s(qt,"buildProjectExport");var fo="coding-agents.config.json";function zt(e){let t=[],r=e.files,o=e.checksums,n=r.findIndex(i=>i.path===fo);if(n>=0){let i=r[n],a=i.content;try{let c=JSON.parse(i.content);if(c&&typeof c=="object"&&!Array.isArray(c)){let u=c.agents;if(u&&typeof u=="object"&&!Array.isArray(u)){let p=!1;for(let l of Object.keys(u)){let g=u[l];if(!g||typeof g!="object"||Array.isArray(g))continue;let d=g.env;if(d&&typeof d=="object"&&!Array.isArray(d)){let k=d;if(Object.values(k).some(T=>typeof T=="string"&&T!=="")){for(let T of Object.keys(k))k[T]="";p=!0}}}p&&(a=JSON.stringify(c,null,2)+`
|
|
20
|
+
`)}}}catch{}if(a!==i.content){let c={path:i.path,content:a};r=r.map((p,l)=>l===n?c:p);let u=pe(a);o=o.map((p,l)=>l===n?{path:p.path,sha256:u}:p),t.push(i.path)}}return{...e,files:r,checksums:o,redacted:t.length>0?t:e.redacted}}s(zt,"redactExportBundle");function Jt(e){let t=s(r=>r.env.services.projectStore.workflows?null:E(r,501,"WORKFLOWS_NOT_CONFIGURED","\u5DE5\u4F5C\u6D41\u6301\u4E45\u5316\u672A\u914D\u7F6E\uFF08\u9700\u8981 AITABLE_DB_URL\uFF09"),"notConfigured");e.get("/:projectId/workflows",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i}=r.env;return y(r,{workflows:await n.projectStore.workflows.list(r.env.project.id,i)})}),e.post("/:projectId/workflows",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i,incoming:a}=r.env,c=r.env.project,u=await b(a);if(!u.name||!u.name.trim())return E(r,422,"INVALID_INPUT","\u5DE5\u4F5C\u6D41\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");let p=await n.projectStore.workflows.create(c.id,{name:u.name,templatePath:u.templatePath,files:u.files},i);await j(c,n);let l={workflow:p.workflow};return p.files&&(l.files=p.files),p.warnings&&p.warnings.length>0&&(l.warnings=p.warnings),y(r,l)}),e.get("/:projectId/workflows/:workflowId",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i}=r.env,a=await n.projectStore.workflows.exportWorkflow(r.env.project.id,r.req.param("workflowId")??"",i);return y(r,{workflow:a.workflow,files:a.files})}),e.delete("/:projectId/workflows/:workflowId",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i}=r.env,a=r.env.project;if(n.runtime.runSessions.has(a.id))return E(r,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664\u5DE5\u4F5C\u6D41");let c=await n.projectStore.workflows.resolve(a.id,r.req.param("workflowId")??"",i);return await n.projectStore.workflows.delete(c,i),await j(a,n),y(r,{ok:!0,id:c.id})}),e.put("/:projectId/workflows/:workflowId/files",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i,incoming:a}=r.env,c=r.env.project,u=await n.projectStore.workflows.resolve(c.id,r.req.param("workflowId")??"",i),p=await b(a);if(!Array.isArray(p.files))return E(r,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");let l=await n.projectStore.workflows.replaceFiles(u,p.files,i);return await j(c,n),y(r,{workflow:u,files:l})}),e.patch("/:projectId/workflows/:workflowId/files",async r=>{let o=t(r);if(o)return o;let{services:n,scope:i,incoming:a}=r.env,c=r.env.project,u=await n.projectStore.workflows.resolve(c.id,r.req.param("workflowId")??"",i),p=await b(a),l=await n.projectStore.workflows.updateFiles(u,{upsert:p.upsert,remove:p.remove},i);return await j(c,n),y(r,{workflow:u,files:l})})}s(Jt,"registerWorkflowRoutes");import mo from"path";import{collectDesignContext as Ne,runDesign as go,syncFieldsFromWorkflow as wo,syncViewsFromDesign as yo,runAutoDiscovery as ko,buildDesignBrief as ho,logger as To}from"aitable-workflow-core";var ye=class{static{s(this,"DesignEventBuffer")}capacity;events=[];seq=0;constructor(t=100){this.capacity=t>0?t:100}push(t){this.seq+=1;let r={seq:this.seq,event:t};return this.events.push(r),this.events.length>this.capacity&&this.events.shift(),r}get cursor(){return this.seq}get size(){return this.events.length}replayAfter(t){return t===void 0||Number.isNaN(t)?[...this.events]:this.events.filter(r=>r.seq>t)}};async function Kt(e,t,r,o){let n=await I(t,e),i=await r.getState(n),a=i.lastTasks.design?.status==="failed"?i.lastTasks.design:null;if(a){await r.clearActiveTask(n,a.id),M(o,{task:a,error:{code:"DESIGN_RETRY_REQUIRED",message:a.error?.message??"\u4E0A\u4E00\u6B21 Design \u5DF2\u5931\u8D25\uFF0C\u8BF7\u70B9\u51FB\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u3002",retryable:!0}},409);return}let c=i.activeTask?.stage==="design"?i.activeTask:null,u=c&&(c.status==="running"||c.status==="blocked")?c:await r.createTask(n,"design");try{let p=_(n),l=await Ne({configPath:p,yes:!0}),g=await ko({scene:l.scene,configPath:p,mode:"fast"}),d={form:g.form,answers:g.answers,summary:g.summary,confirmed:!1},k=await r.updateTask(n,u.id,{status:"blocked",checkpoint:"discovery_waiting_user",currentAction:"\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u9700\u6C42\u6F84\u6E05",block:{reason:"discovery_required",message:"\u8BF7\u5148\u786E\u8BA4 Design \u9636\u6BB5\u7684\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002",actionLabel:"\u786E\u8BA4\u540E\u5F00\u59CB\u751F\u6210"},outputs:{...u.outputs,discovery:d}});M(o,{task:k,discovery:d})}catch(p){let l=await r.updateTask(n,u.id,{status:"failed",checkpoint:"discovery_precheck",currentAction:"\u9700\u6C42\u6F84\u6E05\u51C6\u5907\u5931\u8D25",error:{code:"DESIGN_PRECHECK_FAILED",message:v(p),retryable:!0,details:F(p)}});M(o,{task:l,error:ee(p)},500)}}s(Kt,"handleDesignDiscovery");async function Vt(e,t,r,o,n){let i=await I(t,e),a=await r.getState(i),c=a.activeTask?.stage==="design"?a.activeTask:a.lastTasks.design,u=c?.outputs?.discovery;if(!c||!u){H(n,409,"DISCOVERY_NOT_READY","\u8BF7\u5148\u751F\u6210\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u786E\u8BA4 Design \u8F93\u5165\u3002");return}let p=o.answers??u.answers,l=_(i),g=await Ne({configPath:l,yes:!0}),d=await ho({scene:g.scene,filled:[{form:u.form,answers:p}]}),k={...u,answers:p,clarifications:d,summary:d.replace(/\s+/g," ").trim(),confirmed:!0},w=await r.updateTask(i,c.id,{status:"running",checkpoint:"discovery_confirmed",currentAction:"\u9700\u6C42\u6F84\u6E05\u5DF2\u786E\u8BA4\uFF0C\u51C6\u5907\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848",block:void 0,error:void 0,outputs:{...c.outputs,discovery:k,clarifications:d}});M(n,{task:w,discovery:k})}s(Vt,"handleDesignDiscoveryConfirm");async function Yt(e,t,r,o,n,i){let a=await I(t,e);try{n.ensureAvailable()}catch(f){H(o,te(f),x(f),v(f));return}let c=await r.getState(a),u=c.activeTask?.stage==="design"?c.activeTask:null;if(u&&u.status==="blocked"){N(o),U(o,"task.blocked",{type:"task.blocked",task:u}),o.end();return}if(u&&u.status==="running"&&u.checkpoint!=="discovery_confirmed"){N(o),U(o,"task.snapshot",{type:"task.snapshot",task:u}),o.end();return}if(re.has(a.id)){N(o);let f=ce.get(a.id);if(f){for(let h of f.buffer.replayAfter(i))Ae(o,h.seq,h.event);f.subscribers.add(o),o.on("close",()=>f.subscribers.delete(o));return}u&&U(o,"task.snapshot",{type:"task.snapshot",task:u}),o.end();return}let p=c.lastTasks.design,l=p?.outputs?.discovery,g=p?.status==="failed"&&l?.confirmed&&typeof p.outputs?.clarifications=="string",d=u?.checkpoint==="discovery_confirmed"?u:g?await r.updateTask(a,(await r.createTask(a,"design")).id,{checkpoint:"discovery_confirmed",currentAction:"\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1",outputs:{discovery:l,clarifications:p.outputs?.clarifications}}):await r.createTask(a,"design");re.add(a.id),N(o);let k={buffer:new ye,subscribers:new Set([o])};ce.set(a.id,k),o.on("close",()=>k.subscribers.delete(o));let w=s(f=>Qe(k,f),"send"),T=Date.now(),K=T,se=0,V=[],B=[],C=s((f,h,D)=>{let R=Date.now(),Z=R-T,X=R-K;K=R,V.push({phase:f,message:h,elapsedMs:Z,deltaMs:X,detail:D}),To.info("design-runtime",h,{projectId:a.id,taskId:d.id,phase:f,elapsedMs:Z,deltaMs:X,...D?{detail:D}:{}}),w({type:"design.progress",phase:f,message:h,elapsedMs:Z,deltaMs:X,detail:D})},"emitProgress"),O=s(async(f,h,D)=>{C(f,h,D);let R=await r.updateTask(a,d.id,{currentAction:h,checkpoint:f});w({type:"task.progress",taskId:R.id,message:h,checkpoint:f})},"progress"),fe="",ie=!1,ae=!1,q=s(async()=>{if(ie){ae=!0;return}ie=!0;try{do{ae=!1;let h=(await S(a)).filter(D=>D.path!=="project.json").map(D=>`${D.path}:${D.content}`).join("|");if(h&&h!==fe){fe=h;let D=await A(a),R=await S(D);C("file_snapshot",`\u540C\u6B65 ${R.length} \u4E2A\u751F\u6210\u6587\u4EF6`,{fileCount:R.length}),w({type:"design.files",files:R})}}while(ae)}finally{ie=!1}},"sendFileSnapshot");try{w({type:"task.started",task:d}),w({type:"design.started",projectId:e}),await q();let f,h;try{await O("precheck","\u8BFB\u53D6 Design \u914D\u7F6E"),h=_(a),f=await Ne({configPath:h,yes:!0}),await O("precheck_done","Design \u914D\u7F6E\u8BFB\u53D6\u5B8C\u6210",{agent:f.agentType,timeoutMs:f.agentTimeoutMs})}catch(m){let z=await r.updateTask(a,d.id,{status:"failed",checkpoint:"precheck",currentAction:"Design \u9884\u68C0\u67E5\u5931\u8D25",error:{code:"DESIGN_PRECHECK_FAILED",message:v(m),retryable:!0,details:F(m)}});w({type:"task.failed",task:z}),w({type:"error",error:ee(m)}),o.end();return}let D=d.outputs?.discovery,R=typeof d.outputs?.clarifications=="string"?d.outputs.clarifications:D?.clarifications;if(!D?.confirmed||!R){await O("waiting_input","\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u9700\u6C42\u6F84\u6E05");let m=await r.updateTask(a,d.id,{status:"blocked",checkpoint:"discovery_waiting_user",currentAction:"\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u9700\u6C42\u6F84\u6E05",block:{reason:"discovery_required",message:"\u8BF7\u5148\u786E\u8BA4 Design \u9636\u6BB5\u7684\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002",actionLabel:"\u786E\u8BA4\u540E\u5F00\u59CB\u751F\u6210"},outputs:d.outputs});w({type:"task.blocked",task:m}),o.end();return}f.clarifications=R,await O("brief_ready","\u9700\u6C42\u6458\u8981\u5DF2\u786E\u8BA4\uFF0C\u51C6\u5907\u542F\u52A8 Agent"),w({type:"design.discovery",summary:D.summary});let Z=f.agentTimeoutMs;await O("agent_start","\u542F\u52A8 Coding Agent \u751F\u6210\u6D41\u7A0B\u65B9\u6848",{agent:f.agentType,timeoutMs:Z,timeoutSource:"config",timeoutConfig:"agent.timeout_ms"});let X=!1,qe=await n.buildDesignExecutor({projectId:a.id,agent:f.agentType,projectDir:a.dir}),$=await go(f,{...qe?{executor:qe}:{},timeoutMs:Z,onRoundStart:s((m,z)=>{C("agent_round",`\u7B2C ${m} \u8F6E ${z?"\u4FEE\u6B63":"\u751F\u6210"}\u5F00\u59CB`,{round:m,isFix:z}),w({type:"design.round_start",round:m,isFix:z})},"onRoundStart"),onEvent:s(m=>{B.push(vo(m)),B.length>30&&B.shift(),X||(X=!0,C("agent_first_event",`\u6536\u5230 Agent \u9996\u4E2A\u4E8B\u4EF6\uFF1A${m.type}`,{eventType:m.type})),m.type==="tool_use"&&C("agent_tool","Agent \u8C03\u7528\u5DE5\u5177",{toolName:m.toolName}),(m.type==="text"||m.type==="thinking")&&Date.now()-se>5e3&&(se=Date.now(),C("agent_output",m.type==="thinking"?"Agent \u6B63\u5728\u63A8\u7406":"Agent \u8F93\u51FA\u5185\u5BB9",{eventType:m.type,preview:m.content?.replace(/\s+/g," ").slice(0,120)})),w({type:"design.agent_event",event:m}),(m.type==="tool_use"||m.type==="tool_result")&&q()},"onEvent"),onAgentLifecycle:s(m=>{C(jo(m.phase),Po(m),Do(m))},"onAgentLifecycle"),onValidation:s((m,z)=>{C("validating",m.valid?"\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u901A\u8FC7":`\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u53D1\u73B0 ${m.errors.length} \u4E2A\u95EE\u9898`,{round:z,valid:m.valid,errorCount:m.errors.length}),w({type:"design.validation",round:z,validation:m}),q()},"onValidation")});if(!$.success){await q();let m=await r.updateTask(a,d.id,{status:"failed",checkpoint:"validating",currentAction:"\u771F\u5B9E\u8BBE\u8BA1\u672A\u901A\u8FC7\u6821\u9A8C",error:{code:"DESIGN_VALIDATION_FAILED",message:$.response,retryable:!0},outputs:{...d.outputs,diagnostics:Me(T,V,B,$.validation)}});await Gt(a,m,$.response),w({type:"task.failed",task:m}),w({type:"design.done",success:!1,rounds:$.rounds,response:$.response}),o.end();return}await O("sync_fields","\u540C\u6B65\u5B57\u6BB5\u8BA1\u5212\u5230\u914D\u7F6E"),await wo({workflowPath:f.workflowPath,configPath:h,autoUpdate:!0}),await O("sync_views","\u540C\u6B65\u89C6\u56FE\u8BA1\u5212\u5230\u914D\u7F6E"),await yo({viewsPath:mo.resolve(f.workDir,"views.yml"),configPath:h,autoUpdate:!0}).catch(()=>null),await q(),await O("manifest","\u5199\u5165 Design \u4EA7\u7269\u6E05\u5355");let yr=await S(a),ze=So(a,d,yr);await _e(a,ze);let kr=await r.updateTask(a,d.id,{status:"succeeded",currentAction:"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210",checkpoint:"done",outputs:{...d.outputs,manifest:ze,diagnostics:Me(T,V,B,$.validation)}});w({type:"task.succeeded",task:kr}),w({type:"design.done",success:!0,rounds:$.rounds,response:$.response}),o.end()}catch(f){await q().catch(()=>{});let h=await r.updateTask(a,d.id,{status:"failed",checkpoint:"generating",currentAction:"\u771F\u5B9E\u8BBE\u8BA1\u751F\u6210\u5931\u8D25",error:{code:x(f)==="INTERNAL_ERROR"?"DESIGN_GENERATION_FAILED":x(f),message:v(f),retryable:!0,details:F(f)},outputs:{...d.outputs,diagnostics:Me(T,V,B)}});await Gt(a,h,v(f)),w({type:"task.failed",task:h}),w({type:"error",error:ee(f)}),w({type:"design.done",success:!1,rounds:0,response:v(f)}),o.end()}finally{Ze(a.id)}}s(Yt,"handleDesign");function vo(e){return e.type==="tool_use"?{type:e.type,toolName:e.toolName,toolInput:e.toolInput}:e.type==="tool_result"||e.type==="error"||e.type==="text"||e.type==="thinking"?{type:e.type,content:e.content?.replace(/\s+/g," ").slice(0,240)}:{type:e.type}}s(vo,"summarizeAgentEvent");function jo(e){return`agent_${e}`}s(jo,"agentLifecyclePhase");function Po(e){switch(e.phase){case"process_spawned":return"Coding Agent \u8FDB\u7A0B\u5DF2\u542F\u52A8";case"first_stdout":return"Coding Agent \u9996\u6B21\u8F93\u51FA stdout";case"first_stderr":return"Coding Agent \u9996\u6B21\u8F93\u51FA stderr";case"process_closed":return"Coding Agent \u8FDB\u7A0B\u5DF2\u9000\u51FA"}}s(Po,"agentLifecycleMessage");function Do(e){return{provider:e.provider,phase:e.phase,elapsedMs:e.elapsedMs,...e.pid?{pid:e.pid}:{},...e.cmd?{cmd:e.cmd}:{},...e.cwd?{cwd:e.cwd}:{},...e.exitCode!==void 0?{exitCode:e.exitCode}:{}}}s(Do,"sanitizeAgentLifecycle");function Me(e,t,r,o){return{elapsedMs:Date.now()-e,timeline:t.slice(-40),recentAgentEvents:r,validation:o}}s(Me,"buildDesignDiagnostics");function So(e,t,r){let o=r.filter(a=>a.path==="workflow.yml"||a.path==="views.yml"||a.path.startsWith("recipes/")).map(a=>({path:a.path,kind:a.path==="workflow.yml"?"workflow":a.path==="views.yml"?"views":"recipe",checksum:pe(a.content),required:a.path==="workflow.yml"||a.path.startsWith("recipes/")})),n=o.filter(a=>a.required).map(a=>a.path),i=new Date().toISOString();return{projectId:e.id,taskId:t.id,designVersion:t.attempt,status:"ready",expected:n,generated:o,validation:{passed:!0,errors:[],warnings:[]},createdAt:t.startedAt,updatedAt:i}}s(So,"buildDesignManifest");async function Gt(e,t,r){let o=new Date().toISOString();await _e(e,{projectId:e.id,taskId:t.id,designVersion:t.attempt,status:"invalid",expected:["workflow.yml"],generated:[],validation:{passed:!1,errors:[r],warnings:[]},createdAt:t.startedAt,updatedAt:o})}s(Gt,"writeInvalidDesignManifest");import _o from"path";import{loadSettings as Fo,resolveConfigPath as Wo,loadWorkflowTemplate as Co,initTable as Mo,ensureTableExists as No,syncViewsFromDesign as Lo,runWithExecutor as Bo,runWithDwsRunner as $o,DwsError as Ho,logger as Uo}from"aitable-workflow-core";var Oo={singleSelect:"single_select",multipleSelect:"multiple_select",date:"datetime"},bo={Grid:"grid",FormDesigner:"form",Kanban:"kanban",Calendar:"calendar",Gantt:"gantt"};function Qt(e,t){let r=new Map,o=new Map((e.tracker.field_definitions??[]).map(c=>[c.name,c])),n=s((c,u,p="text",l)=>{if(!c?.trim()||r.has(c))return;let g=o.get(c);r.set(c,{id:xo(c),name:c,type:Ro(g?.type??p),...g?.options??l?{options:g?.options??l}:{},group:u})},"addField");for(let c of t.referencedFields.userInput)n(c,"business");for(let c of t.referencedFields.output)n(c,"business");for(let c of t.referencedFields.other)n(c,"business");for(let c of e.tracker.field_definitions??[])n(c.name,"business",c.type,c.options);n(e.tracker.fields.title,"business"),n(e.tracker.fields.description,"business"),n(e.tracker.fields.state,"process","singleSelect",Ao(e)),n(e.tracker.fields.current_step,"process"),n(e.tracker.fields.owner,"process","user"),n(e.tracker.fields.deadline,"process","date"),n(e.tracker.fields.event_log,"process");let i=Io(e.tracker.views??[],t).map(c=>({id:c.id,name:c.name,kind:bo[c.type]??"grid",desc:c.description??Eo(c)})),a=[...r.values()];return{fieldCount:a.length,viewCount:i.length,fields:a,views:i}}s(Qt,"buildSetupSchemaSummary");function Io(e,t){let r=[],o=2;for(let n of e){if(!n.for_each_step){r.push(n);continue}let i=t.steps.filter(a=>n.for_each_step==="needs_human"?!!a.needs_human:!0);for(let a of i){let c=String.fromCodePoint(9311+o);r.push({...n,id:`step_${a.id}`,name:`${c} ${a.name}`,visible_fields:[...Object.values(a.input_mapping??{}),...Object.values(a.output_mapping??{})],description:a.needs_human?.reason??n.description,for_each_step:void 0}),o++}}return r}s(Io,"expandViews");function Ao(e){return[e.tracker.states.initial,...e.tracker.states.active,...e.tracker.states.terminal,e.tracker.states.blocked,e.tracker.states.review].filter((t,r,o)=>!!t&&o.indexOf(t)===r)}s(Ao,"stateOptions");function Ro(e){return Oo[e]??e}s(Ro,"displayFieldType");function xo(e){return`fld_${e.replace(/[^\p{L}\p{N}]+/gu,"_").replace(/^_+|_+$/g,"")||"field"}`}s(xo,"fieldId");function Eo(e){return e.type==="FormDesigner"?"\u8868\u5355\u5F55\u5165\u89C6\u56FE":e.type==="Kanban"?e.group_by?`\u6309 ${e.group_by} \u5206\u7EC4`:"\u770B\u677F\u89C6\u56FE":e.type==="Calendar"?e.date_field?`\u6309 ${e.date_field} \u67E5\u770B`:"\u65E5\u5386\u89C6\u56FE":e.type==="Gantt"?"\u7518\u7279\u89C6\u56FE":"\u8868\u683C\u89C6\u56FE"}s(Eo,"viewDescription");async function Le(e,t,r,o,n){let i=await I(t,e);try{n.ensureAvailable()}catch(d){H(o,te(d),x(d),v(d));return}let a=await r.getState(i);if(a.activeTask?.stage==="setup"&&a.activeTask.status==="running"){N(o),U(o,"task.snapshot",{type:"task.snapshot",task:a.activeTask}),o.end();return}let c=a.activeTask?.stage==="setup"&&a.activeTask.status==="blocked"?await r.updateTask(i,a.activeTask.id,{status:"running",currentAction:"\u91CD\u65B0\u68C0\u67E5\u6388\u6743\u5E76\u7EE7\u7EED\u642D\u5EFA",block:void 0,error:void 0}):await r.createTask(i,"setup");N(o);let u=s(d=>U(o,d.type,d),"send"),p=s(async(d,k)=>{let w=await r.updateTask(i,c.id,{currentAction:d,checkpoint:k});u({type:"task.progress",taskId:w.id,message:d,checkpoint:k}),u({type:"setup.progress",message:d})},"progress"),l=n.buildSetupExecutor({projectId:i.id,projectDir:i.dir}),g=n.buildDwsRunner();try{await Bo(l,async()=>{await $o(g,async()=>{u({type:"task.started",task:c}),u({type:"setup.started",projectId:e}),await p("\u52A0\u8F7D\u914D\u7F6E\u4E0E\u5DE5\u4F5C\u6D41\u6A21\u677F","preflight"),await Lo({viewsPath:_o.resolve(i.dir,"views.yml"),configPath:_(i),autoUpdate:!0}).catch(O=>(Uo.warn("setup","setup \u524D\u540C\u6B65 views.yml \u5931\u8D25\uFF0C\u7EE7\u7EED\u4F7F\u7528 config \u4E2D\u7684\u89C6\u56FE\u914D\u7F6E",{error:v(O)}),null));let d=await Fo(_(i),{lenientEnv:!0}),k=await Co(d.workflowTemplatePath,{envSource:d.envSource}),w=d.tracker.base_id==="__placeholder__"?void 0:d.tracker,T=w??k.tracker,K=!!T&&!T.table_id.trim();if(T&&!T.table_id.trim()){let O=w?await Wo(_(i)):d.workflowTemplatePath,fe=w?d:{...d,tracker:T},ie=await No({trackerFilePath:O,settings:fe,workflow:k,onProgress:s((ae,q)=>p(ae,q),"onProgress")});d={...d,tracker:ie.tracker}}await p("\u5F00\u59CB\u521B\u5EFA\u5B57\u6BB5\u548C\u89C6\u56FE","sync_schema");let se=await Mo({settings:d,workflow:k,cleanEmptyRows:!0,tableJustCreated:K});for(let O of se.warnings)await p(`\u6CE8\u610F\uFF1A${O.message}`,"sync_schema");let V=Qt(d,k),B=se.warnings.map(O=>O.message);await A(i);let C=await r.updateTask(i,c.id,{status:"succeeded",currentAction:"AI \u8868\u683C\u642D\u5EFA\u5B8C\u6210",checkpoint:"done",outputs:{tableUrl:Fe(d.tracker.base_id,d.tracker.table_id),baseId:d.tracker.base_id,tableId:d.tracker.table_id,schema:V,warnings:B}});u({type:"task.succeeded",task:C}),u({type:"setup.done",tableUrl:Fe(d.tracker.base_id,d.tracker.table_id),baseId:d.tracker.base_id,tableId:d.tracker.table_id,schema:V,warnings:B}),o.end()})})}catch(d){if(qo(d)){let w=v(d),T=await r.updateTask(i,c.id,{status:"blocked",checkpoint:"preflight",currentAction:"\u7B49\u5F85 AI \u8868\u683C\u6388\u6743",block:{reason:"auth_required",message:`\u6388\u6743\u6216\u6743\u9650\u4E0D\u8DB3\uFF1A${w}`,actionLabel:"\u6211\u5DF2\u5B8C\u6210\u6388\u6743\uFF0C\u7EE7\u7EED\u642D\u5EFA",help:"\u8BF7\u6267\u884C dws auth login\uFF0C\u5E76\u786E\u8BA4\u5F53\u524D\u8D26\u53F7\u53EF\u8BBF\u95EE\u76EE\u6807 Base/Table\u3002"}});u({type:"task.blocked",task:T}),o.end();return}let k=await r.updateTask(i,c.id,{status:"failed",currentAction:"AI \u8868\u683C\u642D\u5EFA\u5931\u8D25",error:{code:x(d),message:v(d),retryable:!0,details:F(d)}});u({type:"task.failed",task:k}),u({type:"error",error:ee(d)}),o.end()}}s(Le,"handleSetup");function qo(e){let t=v(e).toLowerCase(),r=e instanceof Ho?e.stderr.toLowerCase():"",o=`${t} ${r}`;return["auth","login","permission","unauthorized","forbidden","access denied"].some(n=>o.includes(n))}s(qo,"isSetupAuthBlocker");function Zt(e){e.post("/:projectId/tasks/:stage/:taskAction",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project,a=t.req.param("stage")??"",c=t.req.param("taskAction")??"",u=c==="start"||c==="continue"||c==="retry";if(u&&a==="setup"){await j(i,r),await Le(i.id,r.workspace,r.projectStore.instances,n,J(t));return}if(u&&a==="run"){await j(i,r),await Ce(i.id,r.workspace,r.projectStore.instances,r.runtime,o,n);return}H(n,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")})),e.post("/:projectId/design/discovery",W(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await j(n,r),await Kt(n.id,r.workspace,r.projectStore.instances,o)})),e.post("/:projectId/design/discovery/confirm",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r);let a=await b(o);await Vt(i.id,r.workspace,r.projectStore.instances,a,n)})),e.post("/:projectId/design",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r);let a=new URL(t.req.url),c=Xe(a,o);await Yt(i.id,r.workspace,r.projectStore.instances,n,J(t),c),await ue(r,i,"design")})),e.post("/:projectId/setup",W(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await j(n,r),await Le(n.id,r.workspace,r.projectStore.instances,o,J(t)),await ue(r,n,"setup")})),e.post("/:projectId/run/records/:recordId/human-action",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r),await At(i.id,r.workspace,r.projectStore.instances,r.runtime,t.req.param("recordId")??"",o,n)})),e.post("/:projectId/run",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r),await Ce(i.id,r.workspace,r.projectStore.instances,r.runtime,o,n)}))}s(Zt,"registerStageRoutes");function er(){let e=new zo;return e.get("/",async t=>y(t,{projects:await t.env.services.projectStore.projects.list(t.env.scope)})),e.post("/",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=await b(n),a=await r.projectStore.projects.create(o,{title:i.title,files:i.files});await j(a,r);let c={project:a};return a.files&&(c.files=a.files),a.warnings&&a.warnings.length>0&&(c.warnings=a.warnings),y(t,c)}),e.use("/:projectId",Ie),e.use("/:projectId/*",Ie),e.delete("/:projectId",async t=>{let{services:r,scope:o}=t.env,n=t.env.project;return r.runtime.runSessions.has(n.id)?E(t,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664"):(await r.projectStore.projects.delete(n,o),await me(n),await et(r,n.id),y(t,{ok:!0,id:n.id}))}),e.patch("/:projectId",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=await b(n);return y(t,{project:await r.projectStore.projects.updateMeta(t.env.project,{title:i.title},o)})}),e.post("/:projectId/init",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await j(i,r);let a=J(t);await bt(i.id,r.workspace,r.projectStore.instances,o,n,(c,u)=>a.bindProjectMachine(c,u)),await ue(r,i,"init")})),e.get("/:projectId/engine",async t=>{let r=t.env.project,o=J(t),n=await o.getProjectMachine(r.id);if(!n)return y(t,{machineId:null,machine:null,status:"unbound"});let i=o.isMachineOnline(n),c=(o.listMachines()??[]).find(u=>u.machineId===n);return y(t,{machineId:n,machine:c??null,status:i?"online":"offline"})}),e.put("/:projectId/engine",async t=>{let{incoming:r}=t.env,o=await b(r);return o.machineId?(await J(t).bindProjectMachine(t.env.project.id,o.machineId),y(t,{ok:!0,machineId:o.machineId})):E(t,422,"INVALID_INPUT","machineId \u4E0D\u80FD\u4E3A\u7A7A")}),e.get("/:projectId/files",async t=>{let r=t.env.project;return y(t,{project:r,files:await S(r)})}),e.put("/:projectId/files",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=t.env.project,a=await b(n);if(!Array.isArray(a.files))return E(t,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");let c=await r.projectStore.projects.replaceFiles(i,a.files,o),u=await j(i,r);return y(t,{project:u.project,files:c})}),e.patch("/:projectId/files",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=t.env.project,a=await b(n),c=await r.projectStore.projects.updateFiles(i,{upsert:a.upsert,remove:a.remove},o),u=await j(i,r);return y(t,{project:u.project,files:c})}),e.get("/:projectId/export",async t=>{let{services:r,scope:o}=t.env,n=t.env.project,i=await r.projectStore.projects.exportProject(n,o),a=zt(i),c=r.projectStore.workflows;if(c){let u=await Promise.all((await c.list(n.id,o)).map(async p=>{let l=await c.exportWorkflow(n.id,p.id,o);return{workflow:l.workflow,files:l.files}}));return y(t,{...a,workflows:u})}return y(t,a)}),e.post("/:projectId/validate",async t=>{let r=t.env.project,o=le.join(r.dir,"workflow.yml"),n=le.join(r.dir,"recipes"),i=le.join(r.dir,"views.yml"),a=await Jo(o,n,i);return await Rt(r,a),y(t,a)}),e.get("/:projectId/workflow",async t=>{let r=t.env.project,o=await Go(r.dir),n=le.join(r.dir,"workflow.yml"),i=await Xt(n,{envSource:o}).catch(()=>Xt(n)),a=le.join(r.dir,"recipes"),c=i.steps.map(u=>({...u,requires_agent:u.recipe?_t(a,u.recipe):!!u.prompt}));return y(t,{workflow:{...i,steps:c}})}),e.post("/:projectId/reset-workflow",async t=>{let r=await ct(t.env.project);return y(t,{project:r,files:await S(r)})}),e.get("/:projectId/state",async t=>{let{services:r}=t.env,o=t.env.project,n=await r.projectStore.instances.getRecoverableState(o);return y(t,ht(n,r.runtime.runSessions.get(o.id)))}),e.patch("/:projectId/table-id",W(async t=>{let{services:r,incoming:o,outgoing:n}=t.env;await It(t.env.project.id,r.workspace,r.projectStore.instances,o,n)})),Jt(e),Zt(e),e}s(er,"projectRoutes");function tr(){let e=new Ko;return e.onError((t,r)=>E(r,te(t),x(t),v(t),F(t))),e.notFound(t=>E(t,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")),e.use("*",async(t,r)=>{t.env.scope=await t.env.services.identityService.resolveScope(t.env.incoming);let o=t.req.path,n=t.req.method;if(!(Ve(o,n)||n==="GET"&&o==="/api/public-config")&&!await t.env.services.identityService.authenticate(t.env.incoming))return Ye(t);await r()}),e.get("/api/health",t=>y(t,{ok:!0})),e.get("/check.node",t=>t.text("success")),e.get("/api/public-config",t=>{let r=process.env.RELAY_PUBLIC_GATEWAY_URL?.trim();return y(t,{authEnabled:t.env.services.identityService.authRequired,...r?{relayGatewayUrl:r}:{}})}),e.route("/api/projects",er()),e.get("/api/agents",t=>y(t,Vo())),e}s(tr,"createHonoApp");import{createApp as Pn,logger as Dn}from"aitable-workflow-core";function rr(e){return{create:s(async(t,r)=>{let o=await at(e),n=[];if(r?.files&&r.files.length>0){let i=await we(o,r.files);n.push(...i.warnings);let a=await A(o);return r.title&&r.title.trim()&&(a=await oe(a,{title:r.title.trim()})),{...a,files:i.written,warnings:n}}if(r?.title&&r.title.trim()){let i=await oe(o,{title:r.title.trim()});return n.length?{...i,warnings:n}:{...i}}return n.length?{...o,warnings:n}:{...o}},"create"),list:s(async t=>Ee(e),"list"),resolve:s(async(t,r)=>I(e,t),"resolve"),updateMeta:s(async(t,r,o)=>oe(t,r),"updateMeta"),delete:s(async(t,r)=>{await me(t)},"delete"),updateFiles:s(async(t,r,o)=>(r.remove&&r.remove.length>0&&await Ht(t,r.remove),r.upsert&&r.upsert.length>0&&await we(t,r.upsert),await A(t),S(t)),"updateFiles"),replaceFiles:s(async(t,r,o)=>(await Ut(t,r),await A(t),S(t)),"replaceFiles"),exportProject:s(async(t,r)=>qt(t),"exportProject"),syncHotFields:s(async()=>{},"syncHotFields")}}s(rr,"createLocalProjectRepository");import{randomUUID as nn}from"crypto";import{mkdir as nr,readFile as sr,rm as sn,writeFile as ir}from"fs/promises";import Y from"path";import{applyRunExecutionEvent as an}from"aitable-workflow-core";var Be=["init","design","setup","run"];function he(e,t){let r={...e.lastTasks,[t.stage]:t},o=or(t.status)?t:e.activeTask?.id===t.id?null:e.activeTask;return L({id:t.projectId,dir:"",createdAt:"",updatedAt:t.updatedAt},{...e,projectId:t.projectId,stage:t.stage,activeTask:o,lastTasks:r,updatedAt:t.updatedAt})}s(he,"mergeTaskIntoState");function L(e,t){let r=new Date().toISOString(),o=t.lastTasks??{},n=t.activeTask??Object.values(o).find(a=>a&&or(a.status))??null,i=t.stage??n?.stage??rn(o)?.stage??"init";return{projectId:t.projectId??e.id,stage:i,activeTask:n,lastTasks:o,stageRuntime:{init:ke("init",o.init,n,o,i),design:ke("design",o.design,n,o,i),setup:ke("setup",o.setup,n,o,i),run:ke("run",o.run,n,o,i)},runSnapshot:t.runSnapshot,updatedAt:t.updatedAt??e.updatedAt??r}}s(L,"normalizeProjectState");function or(e){return e==="running"||e==="blocked"}s(or,"isActiveStatus");function Te(e){return e==="failed"||e==="succeeded"||e==="cancelled"}s(Te,"isTerminalStatus");function ke(e,t,r,o,n){let i=r?.stage===e?r:t;return i?{status:i.status,taskId:i.id,checkpoint:i.checkpoint,message:i.block?.message??i.error?.message??i.currentAction??on(i.status),retryable:i.error?.retryable??(i.status==="blocked"||i.status==="failed"),block:i.block,error:i.error,recoveryAction:Zo(i)}:Yo(e,o,n)?{status:"succeeded",message:Qo(e),retryable:!1}:{status:"idle",message:"\u5C1A\u672A\u5F00\u59CB"}}s(ke,"runtimeForStage");function Yo(e,t,r){let o=Be.indexOf(e);return Be.indexOf(r)>o?!0:Be.slice(o+1).some(i=>!!t[i])}s(Yo,"isPreviousStage");function Qo(e){return e==="init"?"\u914D\u7F6E\u5DF2\u5B8C\u6210":e==="design"?"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210":e==="setup"?"AI \u8868\u683C\u642D\u5EFA\u5B8C\u6210":"\u8FD0\u884C\u9636\u6BB5\u5DF2\u5B8C\u6210"}s(Qo,"inferredSuccessMessage");function Zo(e){if(e.status==="blocked"&&e.stage==="design"&&e.block?.reason==="discovery_required")return{type:"confirm_input",label:e.block.actionLabel,description:e.block.message,api:{method:"POST",path:`/api/projects/${e.projectId}/design/discovery/confirm`}};if(e.status==="blocked")return{type:"continue",label:e.block?.actionLabel??Xo(e.stage),description:e.block?.message??e.currentAction,api:{method:"POST",path:`/api/projects/${e.projectId}/tasks/${e.stage}/continue`}};if(e.status==="failed"&&e.error?.retryable)return{type:"retry",label:en(e.stage),description:e.error.message,api:{method:"POST",path:tn(e)}}}s(Zo,"recoveryActionForTask");function Xo(e){return e==="setup"?"\u7EE7\u7EED\u642D\u5EFA":e==="design"?"\u7EE7\u7EED\u8BBE\u8BA1":e==="run"?"\u7EE7\u7EED\u8FD0\u884C":"\u7EE7\u7EED"}s(Xo,"continueLabel");function en(e){return e==="design"?"\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1":e==="setup"?"\u91CD\u8BD5\u642D\u5EFA":e==="run"?"\u91CD\u8BD5\u8FD0\u884C":"\u91CD\u8BD5"}s(en,"retryLabel");function tn(e){return e.stage==="design"?`/api/projects/${e.projectId}/design`:`/api/projects/${e.projectId}/tasks/${e.stage}/retry`}s(tn,"retryPath");function rn(e){return Object.values(e).filter(t=>!!t).sort((t,r)=>r.updatedAt.localeCompare(t.updatedAt))[0]??null}s(rn,"latestTask");function on(e){return e==="running"?"\u4EFB\u52A1\u8FD0\u884C\u4E2D":e==="blocked"?"\u4EFB\u52A1\u7B49\u5F85\u5904\u7406":e==="failed"?"\u4EFB\u52A1\u5931\u8D25":e==="succeeded"?"\u4EFB\u52A1\u5B8C\u6210":e==="cancelled"?"\u4EFB\u52A1\u5DF2\u53D6\u6D88":"\u5C1A\u672A\u5F00\u59CB"}s(on,"statusMessage");var ve=new Map,cn=/^[a-zA-Z0-9_-]+$/;function ar(e){return{getState:Q,getRecoverableState:gn,createTask:dn,updateTask:ln,clearActiveTask:wn,appendRunSnapshotEvent:fn,updateRunSnapshotRecord:mn,deleteProjectState:s(t=>un(e,t),"deleteProjectState")}}s(ar,"createLocalWorkflowInstanceStore");async function un(e,t){He(t);let r=pn(e,t);await sn(Y.join(r,"runtime"),{recursive:!0,force:!0})}s(un,"deleteProjectState");function pn(e,t){return He(t),Y.join(e.projectsRoot,t)}s(pn,"projectDir");async function dn(e,t){return ne(e,async()=>{await Pe(e);let r=await Q(e),o=(r.lastTasks[t]?.attempt??0)+1,n=new Date().toISOString(),i={id:`task_${nn().slice(0,8)}`,projectId:e.id,stage:t,status:"running",attempt:o,startedAt:n,updatedAt:n,currentAction:"\u4EFB\u52A1\u5DF2\u542F\u52A8"};return await je(e,i),await G(e,he(r,i)),i})}s(dn,"createTask");async function ln(e,t,r){return ne(e,async()=>{let o=await kn(e,t),n=new Date().toISOString(),i={...o,...r,id:o.id,projectId:o.projectId,stage:o.stage,attempt:o.attempt,startedAt:o.startedAt,updatedAt:n,completedAt:r.completedAt??(Te(r.status)?n:o.completedAt),block:Object.prototype.hasOwnProperty.call(r,"block")?r.block:Te(r.status)?void 0:o.block};await je(e,i);let a=await Q(e);return await G(e,he(a,i)),i})}s(ln,"updateTask");async function Q(e){await Pe(e);let t=await sr(ur(e),"utf8").catch(()=>"");if(t.trim()){let r=hn(t),o=L(e,r);return r.repaired&&await G(e,o),o}return L(e,{projectId:e.id,stage:"init",activeTask:null,lastTasks:{},updatedAt:e.updatedAt})}s(Q,"getState");async function fn(e,t){return ne(e,async()=>{let r=await Q(e),o=an(r.runSnapshot??{records:[],logs:[]},t),n=L(e,{...r,runSnapshot:o,updatedAt:new Date().toISOString()});return await G(e,n),n})}s(fn,"appendRunSnapshotEvent");async function mn(e,t,r,o){return ne(e,async()=>{let n=await Q(e);if(!n.runSnapshot)return n;let i=Date.now(),a={records:vn(n.runSnapshot.records,t,u=>({...u,...r,updatedAt:i})),logs:o?jn(n.runSnapshot.logs,t,r.currentStepId??"run","info",o):n.runSnapshot.logs},c=L(e,{...n,runSnapshot:a,updatedAt:new Date().toISOString()});return await G(e,c),c})}s(mn,"updateRunSnapshotRecord");async function gn(e){return ne(e,async()=>{let t=await Q(e),r=t.lastTasks.design,o=await ut(e);if(o.status==="ready"){if(!r||r.status==="succeeded")return t;let c=new Date().toISOString(),u={...r,status:"succeeded",updatedAt:c,completedAt:r.completedAt??c,currentAction:"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210",checkpoint:"done",block:void 0,error:void 0};await je(e,u);let p=L(e,{...t,stage:t.stage==="design"?"setup":t.stage,activeTask:t.activeTask?.stage==="design"?null:t.activeTask,lastTasks:{...t.lastTasks,design:u},updatedAt:c});return await G(e,p),p}if(r?.status!=="succeeded")return t;let n=new Date().toISOString(),i={...r,status:"failed",updatedAt:n,completedAt:n,currentAction:o.status==="artifact_missing"?"\u8BBE\u8BA1\u4EA7\u7269\u7F3A\u5931\uFF0C\u7B49\u5F85\u91CD\u65B0\u751F\u6210":"\u8BBE\u8BA1\u4EA7\u7269\u72B6\u6001\u5F02\u5E38\uFF0C\u7B49\u5F85\u91CD\u65B0\u751F\u6210",checkpoint:o.status,error:{code:o.status==="artifact_missing"?"ARTIFACT_MISSING":"DESIGN_ARTIFACT_INVALID",message:o.errors.join("\uFF1B")||"\u8BBE\u8BA1\u4EA7\u7269\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u3002",retryable:!0,details:{missing:o.missing}}},a=L(e,{...t,stage:"design",activeTask:null,lastTasks:{...t.lastTasks,design:i},updatedAt:n});return await je(e,i),await G(e,a),a})}s(gn,"getRecoverableState");async function wn(e,t){return ne(e,async()=>{let r=await Q(e);if(r.activeTask?.id!==t)return r;let o=L(e,{...r,activeTask:null,updatedAt:new Date().toISOString()});return await G(e,o),o})}s(wn,"clearActiveTask");function $e(e){return Y.join(e.dir,"runtime")}s($e,"runtimeDir");function yn(e){return Y.join($e(e),"artifacts")}s(yn,"artifactsDir");function cr(e){return Y.join($e(e),"tasks")}s(cr,"tasksDir");function ur(e){return Y.join($e(e),"state.json")}s(ur,"statePath");function pr(e,t){return He(t),Y.join(cr(e),`${t}.json`)}s(pr,"taskPath");async function Pe(e){await nr(cr(e),{recursive:!0}),await nr(yn(e),{recursive:!0})}s(Pe,"ensureRuntimeDirs");async function kn(e,t){let r=await sr(pr(e,t),"utf8");return JSON.parse(r)}s(kn,"readTask");async function je(e,t){await Pe(e),await ir(pr(e,t.id),`${JSON.stringify(t,null,2)}
|
|
21
|
+
`,"utf8")}s(je,"writeTask");async function G(e,t){await Pe(e),await ir(ur(e),`${JSON.stringify(t,null,2)}
|
|
22
|
+
`,"utf8")}s(G,"writeProjectState");async function ne(e,t){let r=e.dir||e.id,n=(ve.get(r)??Promise.resolve()).catch(()=>{}).then(t),i=n.then(()=>{},()=>{});ve.set(r,i);try{return await n}finally{ve.get(r)===i&&ve.delete(r)}}s(ne,"withProjectStateWrite");function hn(e){try{return JSON.parse(e)}catch(t){let r=Tn(e);if(!r)throw t;return{...JSON.parse(r),repaired:!0}}}s(hn,"parseProjectStateJson");function Tn(e){let t=e.indexOf("{");if(t<0)return null;let r=0,o=!1,n=!1;for(let i=t;i<e.length;i+=1){let a=e[i];if(o){n?n=!1:a==="\\"?n=!0:a==='"'&&(o=!1);continue}if(a==='"')o=!0;else if(a==="{")r+=1;else if(a==="}"&&(r-=1,r===0))return e.slice(t,i+1)}return null}s(Tn,"extractFirstJsonObject");function vn(e,t,r){return e.map(o=>o.id===t?r(o):o)}s(vn,"updateRunRecord");function jn(e,t,r,o,n){return[...e,{id:`run_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,7)}`,ts:Date.now(),itemId:t,stepId:r,level:o,text:n}].slice(-300)}s(jn,"appendRunLog");function He(e){if(!cn.test(e))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${e}`),{code:"INVALID_PROJECT_ID"})}s(He,"assertProjectId");var De=class{static{s(this,"LocalProjectStore")}projects;instances;workflows;constructor(t){this.projects=rr(t),this.instances=ar(t)}async prepareWorkdir(t,r){return{project:await A(t),materialized:0,warnings:[]}}async commitWorkdir(t,r){}async cascadeDelete(t){}};var Se=class{static{s(this,"LocalExecutionBackend")}kind="local";ensureAvailable(){}async buildDesignExecutor(){}buildSetupExecutor(){}buildDwsRunner(){}listMachines(){}isMachineOnline(){return!1}async getProjectMachine(){return null}async bindProjectMachine(){throw Object.assign(new Error("\u5F15\u64CE\u7BA1\u7406\u6682\u4E0D\u53EF\u7528"),{code:"NOT_AVAILABLE",status:503})}async unbindProjectMachine(){}};var Oe=class{static{s(this,"LocalIdentityService")}authRequired=!1;authenticate(t){return Ge(t)}async resolveScope(t){let r=t.headers["x-actor-id"],o=Array.isArray(r)?r[0]:r;return o?.trim()?{actorId:o.trim()}:{}}};function dr(e={}){let t=e.workspace??it({dataRoot:e.dataRoot});return{workspace:t,runtime:yt(e.appFactory??((r,o)=>Pn(r,{onRunEvent:o}))),projectStore:e.projectStore??new De(t),execution:e.execution??new Se,identityService:e.identityService??new Oe,extendApp:e.extendApp,webRoot:e.webRoot}}s(dr,"createServerServices");function lr(e=process.env){let t=e.AITABLE_RELAY_BOOTSTRAP_KEY;return typeof t=="string"&&t.trim()!==""?(Dn.warn("server","AITABLE_RELAY_BOOTSTRAP_KEY \u5DF2\u5E9F\u5F03\u5E76\u88AB\u5FFD\u7565\uFF1Abootstrap \u8BA4\u8BC1\u5DF2\u79FB\u9664\uFF0C\u8BF7\u6539\u7528 owner-token\uFF08sk_owner_*\uFF09\u6216 per-machine key\uFF08sk_machine_*\uFF09"),!0):!1}s(lr,"warnDeprecatedBootstrapKey");var Sn="127.0.0.1",ja=8787;function be(e){if(typeof e!="string")return;let t=e.trim();return t||void 0}s(be,"readEnvString");function On(e){let t=be(e);if(t===void 0)return;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>0?r:void 0}s(On,"readEnvPort");function fr(e={},t=process.env){let r=e.host??be(t.AITABLE_WORKFLOW_HOST)??Sn,o=e.port??On(t.AITABLE_WORKFLOW_PORT)??8787,n=e.dataRoot??be(t.AITABLE_WORKFLOW_DATA_DIR)??void 0,i=e.webRoot??be(t.AITABLE_WORKFLOW_WEB_ROOT)??void 0;return{host:r,port:o,dataRoot:n,webRoot:i}}s(fr,"resolveServeConfig");import Ue from"path";import{readFile as bn,access as In}from"fs/promises";import{resolveInsideRoot as An}from"aitable-workflow-core";var Rn={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".ico":"image/x-icon",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json; charset=utf-8",".txt":"text/plain; charset=utf-8"};async function mr(e,t,r,o){let n=Ue.resolve(e),i=Ue.join(n,"index.html"),a=decodeURIComponent(t).replace(/^\/+/,""),c;try{c=a===""?i:An(n,a,{allowRoot:!1})}catch{c=i}try{await In(c)}catch{c=i}try{let u=await bn(c),p=Ue.extname(c).toLowerCase(),l=Rn[p]??"application/octet-stream";if(o.writeHead(200,{"Content-Type":l,"Content-Length":u.byteLength}),r.method==="HEAD"){o.end();return}o.end(u)}catch{H(o,404,"WEB_NOT_BUILT","\u672C\u5730 web \u8D44\u6E90\u4E0D\u5B58\u5728\uFF08\u8BF7\u5148\u6784\u5EFA\u524D\u7AEF\u6216\u68C0\u67E5 --web-root\uFF09")}}s(mr,"serveStaticWeb");async function Ma(e={}){lr();let t=fr({port:e.port,host:e.host,dataRoot:e.dataRoot,webRoot:e.webRoot}),r=e.services??dr({dataRoot:t.dataRoot,appFactory:e.appFactory,webRoot:t.webRoot}),o=xn.createServer((n,i)=>{_n(r,n,i)});return await new Promise(n=>o.listen(t.port,t.host,n)),console.log(`aitable-workflow server listening on http://${t.host}:${t.port}`),console.log(`data root: ${r.workspace.dataRoot}`),o}s(Ma,"startServer");var gr=new WeakMap;function En(e){let t=gr.get(e);return t||(t=tr(),e.extendApp?.(t),gr.set(e,t)),t}s(En,"appFor");async function _n(e,t,r){if(Je(t,r),t.method==="OPTIONS"){r.writeHead(204).end();return}let o=new URL(t.url??"/","http://localhost");if(e.webRoot&&(t.method==="GET"||t.method==="HEAD")&&!o.pathname.startsWith("/api/")&&o.pathname!=="/check.node"){await mr(e.webRoot,o.pathname,t,r);return}let n={incoming:t,outgoing:r,services:e,scope:{}},i=new Request(o,{method:t.method??"GET",headers:Fn(t.headers)}),a=await En(e).fetch(i,n);if(n.rawHandled)return;let c={};a.headers.forEach((p,l)=>{c[l]=p});let u=a.body?Buffer.from(await a.arrayBuffer()):void 0;r.writeHead(a.status,c),r.end(u)}s(_n,"handleRequest");function Fn(e){let t=new Headers;for(let[r,o]of Object.entries(e))if(o!==void 0)if(Array.isArray(o))for(let n of o)t.append(r,n);else t.set(r,o);return t}s(Fn,"toFetchHeaders");import wr from"path";function $a(e){let t=wr.normalize(e).split(wr.sep).join("/");return t==="workflow.yml"?"workflow":t==="views.yml"?"views":t.startsWith("recipes/")?"recipe":"other"}s($a,"workflowFileKind");function qa(){let e=new Map;return{withProjectLock(t,r){let n=(e.get(t)??Promise.resolve()).then(r,r);return e.set(t,n),n.then(()=>{e.get(t)===n&&e.delete(t)},()=>{e.get(t)===n&&e.delete(t)}).catch(()=>{}),n}}}s(qa,"createProjectMutexStore");export{Sn as DEFAULT_SERVE_HOST,ja as DEFAULT_SERVE_PORT,Se as LocalExecutionBackend,Oe as LocalIdentityService,De as LocalProjectStore,ee as apiError,Nt as assertSafeProjectPath,Mt as assertSafeRelativePath,xs as assertSafeWorkflowPath,co as assertWritableKind,J as backendOf,Fe as buildAITableUrl,et as cascadeDeleteProject,pe as checksumContent,ue as commitStageOnTerminal,_ as configPath,tr as createHonoApp,rr as createLocalProjectRepository,ar as createLocalWorkflowInstanceStore,at as createProject,qa as createProjectMutexStore,yt as createServerRuntime,dr as createServerServices,it as createWorkspace,me as deleteProject,E as errorBody,x as errorCode,F as errorDetails,v as errorMessage,te as errorStatus,_n as handleRequest,kt as handleRunRuntime,Lt as isForbiddenWritable,Or as isStageActiveFor,Te as isTerminalStatus,y as jsonBody,Bt as kindOf,S as listProjectFiles,Ee as listProjects,he as mergeTaskIntoState,L as normalizeProjectState,ht as overlayRunSessionState,j as prepareWorkdirGuarded,W as raw,Er as readDesignManifest,b as readJson,Ht as removeProjectFiles,Ut as replaceProjectFiles,ct as resetProjectWorkflow,I as resolveProject,Ie as resolveProjectMw,fr as resolveServeConfig,H as sendError,M as sendJson,Cn as sendUnauthorized,Ma as startServer,A as touchProject,Ye as unauthorized,oe as updateProjectMeta,uo as validateConfigScene,ut as validateDesignArtifacts,lr as warnDeprecatedBootstrapKey,$a as workflowFileKind,_e as writeDesignManifest,we as writeProjectFiles};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aitable-workflow-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17-beta.1786087167343",
|
|
4
4
|
"description": "aitable-workflow 服务端(server):纯 local 的 HTTP design/setup/run API(Hono)。relay gateway/PG/OSS 装配在 apps/gateway。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"aitable-workflow-core": "0.1.
|
|
25
|
+
"aitable-workflow-core": "0.1.17-beta.1786087167343",
|
|
26
26
|
"@hono/node-server": "^2.0.12",
|
|
27
27
|
"hono": "^4.12.32",
|
|
28
28
|
"yaml": "^2.8.1"
|