aitable-workflow-server 0.1.16 → 0.1.17-beta.1786415522134

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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import http, { ServerResponse, IncomingMessage } from 'node:http';
2
- import { ProjectDTO, ProjectFileDTO, DesignArtifactManifestDTO, DesignArtifactValidationDTO, ProjectStateDTO, StageIdDTO, ProjectTaskDTO, RunExecutionEventDTO, RunSnapshotDTO, RunEventSink, App, RunEventDTO, ProjectExportDTO, ProjectWorkflowDTO, CreateWorkflowResponseDTO, AgentType, AgentExecutor, DwsRunner, ApiError } from 'aitable-workflow-core';
2
+ import { ProjectDTO, ProjectFileDTO, DesignArtifactManifestDTO, DesignArtifactValidationDTO, ProjectStateDTO, StageIdDTO, ProjectTaskDTO, RunExecutionEventDTO, RunSnapshotDTO, RunEventSink, App, RunEventDTO, ProjectExportDTO, ProjectWorkflowDTO, CreateWorkflowResponseDTO, AgentType, AgentExecutor, DwsRunner, RunScheduleDTO, RunRecordsPageDTO, ApiError, RunControlResultDTO } from 'aitable-workflow-core';
3
3
  import { Context, Hono } from 'hono';
4
4
 
5
5
  type WorkspaceOptions = {
@@ -46,7 +46,18 @@ interface WorkflowInstanceStore {
46
46
  */
47
47
  deleteProjectState(projectId: string): Promise<void>;
48
48
  }
49
- declare function createLocalWorkflowInstanceStore(workspace: Workspace): WorkflowInstanceStore;
49
+ declare class LocalWorkflowInstanceStore implements WorkflowInstanceStore {
50
+ private readonly workspace;
51
+ constructor(workspace: Workspace);
52
+ getState(project: ProjectDTO): Promise<ProjectStateDTO>;
53
+ getRecoverableState(project: ProjectDTO): Promise<ProjectStateDTO>;
54
+ createTask(project: ProjectDTO, stage: StageIdDTO): Promise<ProjectTaskDTO>;
55
+ updateTask(project: ProjectDTO, taskId: string, patch: Partial<ProjectTaskDTO>): Promise<ProjectTaskDTO>;
56
+ clearActiveTask(project: ProjectDTO, taskId: string): Promise<ProjectStateDTO>;
57
+ appendRunSnapshotEvent(project: ProjectDTO, event: RunExecutionEventDTO): Promise<ProjectStateDTO>;
58
+ updateRunSnapshotRecord(project: ProjectDTO, itemId: string, patch: Partial<Pick<RunSnapshotDTO["records"][number], "state" | "status" | "currentStepId">>, logText?: string): Promise<ProjectStateDTO>;
59
+ deleteProjectState(projectId: string): Promise<void>;
60
+ }
50
61
 
51
62
  type RunExecutionEvent = Parameters<RunEventSink>[0];
52
63
 
@@ -117,7 +128,19 @@ interface ProjectRepository {
117
128
  tableBaseId: string | null;
118
129
  }, actor?: ActorContext): Promise<void>;
119
130
  }
120
- declare function createLocalProjectRepository(workspace: Workspace): ProjectRepository;
131
+ declare class LocalProjectRepository implements ProjectRepository {
132
+ private readonly workspace;
133
+ constructor(workspace: Workspace);
134
+ create(_actor?: ActorContext, init?: CreateProjectInit): Promise<CreateProjectResult>;
135
+ list(_actor?: ActorContext): Promise<ProjectDTO[]>;
136
+ resolve(projectId: string, _actor?: ActorContext): Promise<ProjectDTO>;
137
+ updateMeta(project: ProjectDTO, patch: Partial<Pick<ProjectDTO, "title">>, _actor?: ActorContext): Promise<ProjectDTO>;
138
+ delete(project: ProjectDTO, _actor?: ActorContext): Promise<void>;
139
+ updateFiles(project: ProjectDTO, patch: FilesPatch, _actor?: ActorContext): Promise<ProjectFileDTO[]>;
140
+ replaceFiles(project: ProjectDTO, files: ProjectFileDTO[], _actor?: ActorContext): Promise<ProjectFileDTO[]>;
141
+ exportProject(project: ProjectDTO, _actor?: ActorContext): Promise<ProjectExportDTO>;
142
+ syncHotFields(): Promise<void>;
143
+ }
121
144
 
122
145
  /** 带内容创建工作流的初始载荷。 */
123
146
  type CreateWorkflowInit = {
@@ -225,6 +248,36 @@ interface RelayMachineInfo {
225
248
  ownerUserId?: string;
226
249
  lastSeen: number;
227
250
  }
251
+ /** run 阶段调度状态快照(lease 模式,workflow-pull-claim §3.2)。契约在 core(前端共享)。 */
252
+ type RunScheduleStatus = RunScheduleDTO;
253
+ /**
254
+ * run 阶段调度器(P1):把「运行工作流」从"在本进程 createApp"改为"翻转 DB 期望态,
255
+ * 由用户机器 daemon 认领执行"。**归属执行域**(不新增 ServerServices 顶层字段)。
256
+ *
257
+ * local 不提供(`runScheduler` 为 undefined)→ 路由走现状进程内 run-runtime,
258
+ * 本机调试行为零变化。
259
+ */
260
+ interface RunScheduler {
261
+ /** 用户点「启动」:desired_state='running'(幂等)+ 唤醒候选机器。 */
262
+ start(projectId: string): Promise<RunScheduleStatus>;
263
+ /** 用户点「停止」:desired_state='stopped'(daemon 下次心跳收 stop 并优雅退出)。 */
264
+ stop(projectId: string): Promise<RunScheduleStatus>;
265
+ getStatus(projectId: string): Promise<RunScheduleStatus>;
266
+ }
267
+ /**
268
+ * 工单记录读模型契约在 core(前端与服务端共享):`RunRecordDTO` /
269
+ * `RunRecordsPageDTO`。此处只声明执行域端口,不重复定义数据形状。
270
+ */
271
+ type RunRecordsPage = RunRecordsPageDTO;
272
+ /**
273
+ * lease 模式的工单投影读端口(gateway 用 PG `work_items` 适配注入)。
274
+ * local 不需要——`LocalRunController` 直接读 runSnapshot。
275
+ */
276
+ interface RunRecordsReader {
277
+ listRecords(projectId: string, opts?: {
278
+ limit?: number;
279
+ }): Promise<RunRecordsPageDTO>;
280
+ }
228
281
  interface ExecutionBackend {
229
282
  readonly kind: "local" | "relay";
230
283
  /**
@@ -260,6 +313,16 @@ interface ExecutionBackend {
260
313
  bindProjectMachine(projectId: string, machineId: string): Promise<void>;
261
314
  /** 解绑项目的执行机器(项目删除级联);local no-op。 */
262
315
  unbindProjectMachine(projectId: string): Promise<void>;
316
+ /**
317
+ * run 阶段调度器(P1,lease 模式)。undefined = 未启用 → 路由走进程内 run-runtime
318
+ * (local 与未配 DB 的 gateway 装配均如此,行为与现状一致)。
319
+ */
320
+ readonly runScheduler?: RunScheduler;
321
+ /**
322
+ * 工单投影读源(P1.5,lease 模式)。undefined = 未启用(local 与未配 DB 的
323
+ * gateway)→ `GET /run/records` 由 LocalRunController 读 runSnapshot。
324
+ */
325
+ readonly runRecords?: RunRecordsReader;
263
326
  }
264
327
  declare class LocalExecutionBackend implements ExecutionBackend {
265
328
  readonly kind: "local";
@@ -516,6 +579,13 @@ declare function replaceProjectFiles(project: ProjectDTO, files: ProjectFileDTO[
516
579
 
517
580
  declare function mergeTaskIntoState(state: ProjectStateDTO, task: ProjectTaskDTO): ProjectStateDTO;
518
581
  declare function normalizeProjectState(project: ProjectDTO, value: Partial<ProjectStateDTO>): ProjectStateDTO;
582
+ /** 把一条任务包成阶段状态:事实用 task 原样承载,服务端只额外给恢复动作。 */
583
+ declare function stageStateOf(task: ProjectTaskDTO): ProjectStateDTO["stages"][StageIdDTO];
584
+ /**
585
+ * 当前活跃任务。`activeStage` 与 `stages` 理论上同步更新,这里再按状态校验一次——
586
+ * 指针指向一条已终态的任务时按「无活跃任务」处理,避免调用方误判成还在跑。
587
+ */
588
+ declare function activeTaskOf(state: ProjectStateDTO): ProjectTaskDTO | null;
519
589
  declare function isTerminalStatus(status: ProjectTaskDTO["status"] | undefined): boolean;
520
590
 
521
591
  /**
@@ -543,10 +613,13 @@ type ProjectMutexStore = {
543
613
  withProjectLock<T>(projectId: string, fn: () => Promise<T>): Promise<T>;
544
614
  };
545
615
  /**
546
- * 创建 per-project 互斥锁存储。每个 projectId 维护一条 promise 链;
616
+ * per-project 互斥锁存储。每个 projectId 维护一条 promise 链;
547
617
  * 任务完成后清理链条尾节点,避免长生命周期下 Map 无限增长。
548
618
  */
549
- declare function createProjectMutexStore(): ProjectMutexStore;
619
+ declare class LocalProjectMutexStore implements ProjectMutexStore {
620
+ private readonly queues;
621
+ withProjectLock<T>(projectId: string, fn: () => Promise<T>): Promise<T>;
622
+ }
550
623
 
551
624
  /**
552
625
  * WP-10-011 #1 + #7:stage 活跃判定。
@@ -571,4 +644,52 @@ declare function commitStageOnTerminal(services: ServerServices, project: Projec
571
644
  */
572
645
  declare function cascadeDeleteProject(services: ServerServices, projectId: string): Promise<void>;
573
646
 
574
- export { type ActorContext, type AppEnv, type CreateProjectInit, type CreateProjectResult, type CreateWorkflowInit, type CreateWorkflowResult, type Ctx, DEFAULT_SERVE_HOST, DEFAULT_SERVE_PORT, type ExecutionBackend, type FilesPatch, type HttpEnv, type IdentityService, LocalExecutionBackend, LocalIdentityService, LocalProjectStore, type MaterializeOptions, type MaterializeResult, type ProjectFileKind, type ProjectMutexStore, type ProjectRepository, type ProjectStore, type RelayMachineInfo, type RunAppFactory, type RunSession, type RunSseWriter, type ServeConfig, type ServeConfigOverrides, type ServerRuntime, type ServerServices, type ServerServicesOptions, type StartServerOptions, type WorkflowExportDTO, type WorkflowInstanceStore, type WorkflowRepository, type Workspace, type WorkspaceOptions, type WriteProjectFilesResult, apiError, assertSafeProjectPath, assertSafeRelativePath, assertSafeWorkflowPath, assertWritableKind, backendOf, buildAITableUrl, cascadeDeleteProject, checksumContent, commitStageOnTerminal, configPath, createHonoApp, createLocalProjectRepository, createLocalWorkflowInstanceStore, createProject, createProjectMutexStore, createServerRuntime, createServerServices, createWorkspace, deleteProject, errorBody, errorCode, errorDetails, errorMessage, errorStatus, handleRequest, handleRunRuntime, isForbiddenWritable, isStageActiveFor, isTerminalStatus, jsonBody, kindOf, listProjectFiles, listProjects, mergeTaskIntoState, normalizeProjectState, overlayRunSessionState, prepareWorkdirGuarded, raw, readDesignManifest, readJson, removeProjectFiles, replaceProjectFiles, resetProjectWorkflow, resolveProject, resolveProjectMw, resolveServeConfig, sendError, sendJson, sendUnauthorized, startServer, touchProject, unauthorized, updateProjectMeta, validateConfigScene, validateDesignArtifacts, warnDeprecatedBootstrapKey, workflowFileKind, writeDesignManifest, writeProjectFiles };
647
+ /** stop/status 的 JSON 响应体(mode 标识来源,前端据此渲染差异字段)。 */
648
+ type RunControlResult = RunControlResultDTO;
649
+ interface RunController {
650
+ readonly mode: "local" | "lease";
651
+ /**
652
+ * 启动(幂等)。响应形态因模式而异,故直写 outgoing:
653
+ * local = SSE 事件直播(保持既有前端契约);lease = JSON 调度快照。
654
+ */
655
+ start(projectId: string, outgoing: ServerResponse): Promise<void>;
656
+ /** 停止(幂等)。local = 优雅停编排器;lease = 置 desired_state='stopped' 待 daemon 心跳收敛。 */
657
+ stop(projectId: string): Promise<RunControlResult>;
658
+ /** 运行状态快照(web 状态卡片轮询)。 */
659
+ status(projectId: string): Promise<RunControlResult>;
660
+ /** 工单列表 + 统计(两模式同构:local 读 runSnapshot,lease 读 PG 投影)。 */
661
+ listRecords(projectId: string, opts?: {
662
+ limit?: number;
663
+ }): Promise<RunRecordsPageDTO>;
664
+ }
665
+ declare class LocalRunController implements RunController {
666
+ private readonly services;
667
+ readonly mode: "local";
668
+ constructor(services: ServerServices);
669
+ start(projectId: string, outgoing: ServerResponse): Promise<void>;
670
+ stop(projectId: string): Promise<RunControlResult>;
671
+ status(projectId: string): Promise<RunControlResult>;
672
+ /**
673
+ * 数据源 = runSnapshot(引擎事件归约后落 runtime/state.json),故 server 重启后
674
+ * 历史工单仍完整可见。按 updatedAt 倒序与 lease 侧的 last_seen_at DESC 对齐。
675
+ */
676
+ listRecords(projectId: string, opts?: {
677
+ limit?: number;
678
+ }): Promise<RunRecordsPageDTO>;
679
+ }
680
+ declare class LeaseRunController implements RunController {
681
+ private readonly scheduler;
682
+ private readonly records?;
683
+ readonly mode: "lease";
684
+ constructor(scheduler: RunScheduler, records?: RunRecordsReader | undefined);
685
+ start(projectId: string, outgoing: ServerResponse): Promise<void>;
686
+ stop(projectId: string): Promise<RunControlResult>;
687
+ status(projectId: string): Promise<RunControlResult>;
688
+ listRecords(projectId: string, opts?: {
689
+ limit?: number;
690
+ }): Promise<RunRecordsPageDTO>;
691
+ }
692
+ /** 按执行域接缝装配控制器:注入了 runScheduler → lease,否则 local。 */
693
+ declare function resolveRunController(services: ServerServices): RunController;
694
+
695
+ export { type ActorContext, type AppEnv, type CreateProjectInit, type CreateProjectResult, type CreateWorkflowInit, type CreateWorkflowResult, type Ctx, DEFAULT_SERVE_HOST, DEFAULT_SERVE_PORT, type ExecutionBackend, type FilesPatch, type HttpEnv, type IdentityService, LeaseRunController, LocalExecutionBackend, LocalIdentityService, LocalProjectMutexStore, LocalProjectRepository, LocalProjectStore, LocalRunController, LocalWorkflowInstanceStore, type MaterializeOptions, type MaterializeResult, type ProjectFileKind, type ProjectMutexStore, type ProjectRepository, type ProjectStore, type RelayMachineInfo, type RunAppFactory, type RunControlResult, type RunController, type RunRecordsPage, type RunRecordsReader, type RunScheduleStatus, type RunScheduler, type RunSession, type RunSseWriter, type ServeConfig, type ServeConfigOverrides, type ServerRuntime, type ServerServices, type ServerServicesOptions, type StartServerOptions, type WorkflowExportDTO, type WorkflowInstanceStore, type WorkflowRepository, type Workspace, type WorkspaceOptions, type WriteProjectFilesResult, activeTaskOf, apiError, assertSafeProjectPath, assertSafeRelativePath, assertSafeWorkflowPath, assertWritableKind, backendOf, buildAITableUrl, cascadeDeleteProject, checksumContent, commitStageOnTerminal, configPath, createHonoApp, createProject, createServerRuntime, createServerServices, createWorkspace, deleteProject, errorBody, errorCode, errorDetails, errorMessage, errorStatus, handleRequest, handleRunRuntime, isForbiddenWritable, isStageActiveFor, isTerminalStatus, jsonBody, kindOf, listProjectFiles, listProjects, mergeTaskIntoState, normalizeProjectState, overlayRunSessionState, prepareWorkdirGuarded, raw, readDesignManifest, readJson, removeProjectFiles, replaceProjectFiles, resetProjectWorkflow, resolveProject, resolveProjectMw, resolveRunController, resolveServeConfig, sendError, sendJson, sendUnauthorized, stageStateOf, startServer, touchProject, unauthorized, updateProjectMeta, validateConfigScene, validateDesignArtifacts, warnDeprecatedBootstrapKey, workflowFileKind, writeDesignManifest, writeProjectFiles };
package/dist/index.js CHANGED
@@ -1,22 +1,19 @@
1
- var kr=Object.defineProperty;var s=(e,t)=>kr(e,"name",{value:t,configurable:!0});import An from"http";import{Hono as Jo}from"hono";import{detectAgents as Go}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 N(e,t,r=200){e.writeHead(r,{"content-type":"application/json; charset=utf-8"}),e.end(`${JSON.stringify(t)}
2
- `)}s(N,"sendJson");function U(e,t,r,o,n){N(e,{error:{code:r,message:o,details:n}},t)}s(U,"sendError");function _n(e){e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(`${JSON.stringify({error:"unauthorized"})}
3
- `)}s(_n,"sendUnauthorized");function te(e){return{code:E(e),message:v(e),details:W(e)}}s(te,"apiError");function re(e){return typeof e=="object"&&e!==null&&"status"in e&&typeof e.status=="number"?e.status:500}s(re,"errorStatus");function E(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:"INTERNAL_ERROR"}s(E,"errorCode");function v(e){return e instanceof Error?e.message:String(e)}s(v,"errorMessage");function W(e){if(typeof e=="object"&&e!==null&&"details"in e)return e.details}s(W,"errorDetails");import hr from"crypto";function Je(e,t){Tr(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 Tr(e,t){let r=vr();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(Tr,"applyCorsOrigin");function vr(){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(vr,"readAllowedOrigins");function jr(){let e=process.env.AITABLE_WORKFLOW_API_TOKEN,t=typeof e=="string"?e.trim():"";return t||void 0}s(jr,"readServerApiToken");function Ge(e){let t=jr();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?Pr(i,t):!1}s(Ge,"isRequestAuthorized");function Pr(e,t){let r=Buffer.from(e),o=Buffer.from(t);return r.length!==o.length?!1:hr.timingSafeEqual(r,o)}s(Pr,"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,t,r,o,n){return y(e,{error:{code:r,message:o,details:n}},t)}s(_,"errorBody");function Ye(e){return e.newResponse(`${JSON.stringify({error:"unauthorized"})}
5
- `,401,{"content-type":"application/json; charset=utf-8"})}s(Ye,"unauthorized");function C(e){return async t=>(await e(t),t.env.rawHandled=!0,t.body(null))}s(C,"raw");function G(e){return e.env.services.execution}s(G,"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 Uo}from"hono";import le from"path";import{validateDesignOutput as qo,buildEnvSource as zo,loadWorkflowTemplate as Zt}from"aitable-workflow-core";import{logger as Dr}from"aitable-workflow-core";var oe=new Set,ue=new Map;function Re(e,t,r){e.write(`id: ${t}
1
+ var xr=Object.defineProperty;var s=(e,t)=>xr(e,"name",{value:t,configurable:!0});import Qn from"http";import{Hono as Tn}from"hono";import{detectAgents as Sn}from"aitable-workflow-core";async function I(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(I,"readJson");function _(e,t,r=200){e.writeHead(r,{"content-type":"application/json; charset=utf-8"}),e.end(`${JSON.stringify(t)}
2
+ `)}s(_,"sendJson");function q(e,t,r,o,n){_(e,{error:{code:r,message:o,details:n}},t)}s(q,"sendError");function rs(e){e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(`${JSON.stringify({error:"unauthorized"})}
3
+ `)}s(rs,"sendUnauthorized");function ne(e){return{code:C(e),message:T(e),details:M(e)}}s(ne,"apiError");function se(e){return typeof e=="object"&&e!==null&&"status"in e&&typeof e.status=="number"?e.status:500}s(se,"errorStatus");function C(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:"INTERNAL_ERROR"}s(C,"errorCode");function T(e){return e instanceof Error?e.message:String(e)}s(T,"errorMessage");function M(e){if(typeof e=="object"&&e!==null&&"details"in e)return e.details}s(M,"errorDetails");import Er from"crypto";function Ze(e,t){_r(e,t),t.setHeader("access-control-allow-methods","GET,POST,PATCH,DELETE,OPTIONS"),t.setHeader("access-control-allow-headers","content-type, authorization")}s(Ze,"setCors");function _r(e,t){let r=Fr();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(_r,"applyCorsOrigin");function Fr(){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(Fr,"readAllowedOrigins");function Wr(){let e=process.env.AITABLE_WORKFLOW_API_TOKEN,t=typeof e=="string"?e.trim():"";return t||void 0}s(Wr,"readServerApiToken");function Xe(e){let t=Wr();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?Cr(i,t):!1}s(Xe,"isRequestAuthorized");function Cr(e,t){let r=Buffer.from(e),o=Buffer.from(t);return r.length!==o.length?!1:Er.timingSafeEqual(r,o)}s(Cr,"timingSafeEqualString");function et(e){return Array.isArray(e)?e[0]:e}s(et,"headerValue");function tt(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(tt,"isAuthExempt");function w(e,t,r=200){return e.newResponse(`${JSON.stringify(t)}
4
+ `,r,{"content-type":"application/json; charset=utf-8"})}s(w,"jsonBody");function F(e,t,r,o,n){return w(e,{error:{code:r,message:o,details:n}},t)}s(F,"errorBody");function rt(e){return e.newResponse(`${JSON.stringify({error:"unauthorized"})}
5
+ `,401,{"content-type":"application/json; charset=utf-8"})}s(rt,"unauthorized");function L(e){return async t=>(await e(t),t.env.rawHandled=!0,t.body(null))}s(L,"raw");function K(e){return e.env.services.execution}s(K,"backendOf");async function We(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(We,"resolveProjectMw");import{Hono as kn}from"hono";import V from"path";import{validateDesignArtifacts as vn,buildEnvSource as Pn,loadWorkflowTemplate as fr}from"aitable-workflow-core";import{logger as Nr}from"aitable-workflow-core";var ie=new Set,le=new Map;function Ce(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(Re,"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{Re(o,r.seq,t)}catch{e.subscribers.delete(o)}}}s(Qe,"publishDesignEvent");function Ze(e){oe.delete(e);let t=ue.get(e);if(ue.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 Sr(e,t){return e.runtime.runSessions.has(t)||oe.has(t)}s(Sr,"isStageActiveFor");function j(e,t){return t.projectStore.prepareWorkdir(e,{isStageActive:s(()=>Sr(t,e.id),"isStageActive")})}s(j,"prepareWorkdirGuarded");async function pe(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){Dr.warn("stage-sync","stage \u6D41\u56DE\u5199\u6743\u5A01\u6E90\u5931\u8D25",{projectId:t.id,stage:r,error:v(o)})}}s(pe,"commitStageOnTerminal");async function et(e,t){await e.projectStore.cascadeDelete(t).catch(()=>{}),await e.execution.unbindProjectMachine(t).catch(()=>{})}s(et,"cascadeDeleteProject");import Ce from"path";import{readFile as $r,writeFile as Hr,access as Ur,readdir as qr}from"fs/promises";import St from"yaml";import{scaffold as zr,writeRoleDefinitions as Jr,isRecord as Ot}from"aitable-workflow-core";import{logger as gt}from"aitable-workflow-core";import{createHash as Or,randomUUID as br}from"crypto";import{mkdir as xe,readdir as tt,readFile as Ee,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_-]+$/,Ir=/\.(json|ya?ml|ts|js|md|txt)$/i,Rr=["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 xe(e.projectsRoot,{recursive:!0});let t=new Date().toISOString(),r=(await _e(e)).length+1,o={id:`wf_${br().slice(0,8)}`,title:`\u5DE5\u4F5C\u6D41 #${r}`,dir:"",createdAt:t,updatedAt:t};return o.dir=lt(e,o.id),await xe(o.dir,{recursive:!0}),await we(o),o}s(at,"createProject");async function ne(e,t){let r=await A({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 we(o),o}s(ne,"updateProjectMeta");async function _e(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=>A(e,o.name).catch(()=>null)))).filter(o=>o!==null).sort((o,n)=>n.updatedAt.localeCompare(o.updatedAt))}s(_e,"listProjects");async function A(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 Ee(n,"utf8").catch(()=>"");if(!i){let c=new Date().toISOString(),u={id:t,dir:r,createdAt:c,updatedAt:c};return await we(u),u}return{...JSON.parse(i),dir:r}}s(A,"resolveProject");async function I(e){let t={...e,updatedAt:new Date().toISOString()};return await we(t),t}s(I,"touchProject");async function ct(e){return await Promise.all(Rr.map(t=>rt(P.join(e.dir,t),{recursive:!0,force:!0}))),await I(e)}s(ct,"resetProjectWorkflow");async function ge(e){await rt(e.dir,{recursive:!0,force:!0})}s(ge,"deleteProject");async function xr(e){let t=await Ee(dt(e),"utf8").catch(()=>"");return t.trim()?JSON.parse(t):null}s(xr,"readDesignManifest");async function Fe(e,t){await xe(pt(e),{recursive:!0}),await nt(dt(e),`${JSON.stringify(t,null,2)}
10
- `,"utf8")}s(Fe,"writeDesignManifest");async function ut(e){let t=await xr(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 de(e){return Or("sha256").update(e).digest("hex")}s(de,"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 F(e){return P.join(e.dir,"aitable-workflow.config.yml")}s(F,"configPath");function We(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(We,"buildAITableUrl");function Er(e){return P.join(e.dir,"runtime")}s(Er,"runtimeDir");function pt(e){return P.join(Er(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 we(e){await nt(P.join(e.dir,"project.json"),`${JSON.stringify(e,null,2)}
11
- `,"utf8")}s(we,"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()||!Ir.test(n.name))continue;let a=P.relative(e,i).split(P.sep).join("/"),c=await Ee(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 A(t,e),c=await r.getState(a),u=o.runSessions.get(e);if(u){wt(u,n,i);let m=await r.getState(a),d=m.activeTask?.stage==="run"?m.activeTask:m.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),_r(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 _r(e,t,r,o,n,i){let a=s(u=>{Tt(r,u,i),Wr(u)&&(gt.info("run-runtime","publish run execution event",Cr(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(F(e),l=>a(Fr(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:Nr(u)})}finally{o.runSessions.delete(e.id),Mr(r)}}s(_r,"startRunSession");function Fr(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(Fr,"toRunEventDTO");function Wr(e){return e.type.startsWith("run.record.")||e.type.startsWith("run.step.")}s(Wr,"isRunExecutionEvent");function Cr(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(Cr,"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 Mr(e){for(let t of e.subscribers)t.end();e.subscribers.clear()}s(Mr,"closeRunSubscribers");function Nr(e){return{code:vt(e),message:jt(e),details:Pt(e)}}s(Nr,"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 Lr(){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(Lr,"readSseHeartbeatMs");function L(e){e.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),Br(e)}s(L,"startSse");function Br(e){let t=Lr(),r=setInterval(()=>{if(e.writableEnded||!e.writable){clearInterval(r);return}try{e.write(`:keepalive
9
+ `)}s(Ce,"writeDesignSse");function ot(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{Ce(o,r.seq,t)}catch{e.subscribers.delete(o)}}}s(ot,"publishDesignEvent");function nt(e){ie.delete(e);let t=le.get(e);if(le.delete(e),!!t){for(let r of t.subscribers)if(!r.writableEnded)try{r.end()}catch{}t.subscribers.clear()}}s(nt,"closeDesignSession");function st(e,t){let r=e.searchParams.get("cursor")??et(t.headers["last-event-id"]);if(r==null||r==="")return;let o=Number(r);return Number.isFinite(o)?o:void 0}s(st,"parseReconnectCursor");function Mr(e,t){return e.runtime.runSessions.has(t)||ie.has(t)}s(Mr,"isStageActiveFor");function O(e,t){return t.projectStore.prepareWorkdir(e,{isStageActive:s(()=>Mr(t,e.id),"isStageActive")})}s(O,"prepareWorkdirGuarded");async function fe(e,t,r){try{let n=(await e.projectStore.instances.getState(t)).stages[r]?.task;if(!n)return;let i=n.status;if(i!=="succeeded"&&i!=="failed"&&i!=="cancelled")return;await e.projectStore.commitWorkdir(t,{stage:r})}catch(o){Nr.warn("stage-sync","stage \u6D41\u56DE\u5199\u6743\u5A01\u6E90\u5931\u8D25",{projectId:t.id,stage:r,error:T(o)})}}s(fe,"commitStageOnTerminal");async function it(e,t){await e.projectStore.cascadeDelete(t).catch(()=>{}),await e.execution.unbindProjectMachine(t).catch(()=>{})}s(it,"cascadeDeleteProject");import ve from"path";import{readFile as jt,writeFile as Kr,access as Gr,readdir as Vr}from"fs/promises";import He from"yaml";import{scaffold as Yr,writeProfileRoles as Qr,isRecord as Pe}from"aitable-workflow-core";import{createHash as Lr,randomUUID as Br}from"crypto";import{mkdir as Ne,readdir as at,readFile as Me,rm as ct,stat as ut,writeFile as pt}from"fs/promises";import S from"path";var $r=S.resolve(process.cwd(),".sandbox","aitable-workflow-server"),dt=/^[a-zA-Z0-9_-]+$/,Hr=/\.(json|ya?ml|ts|js|md|txt)$/i,qr=["workflow.yml","views.yml","recipes","traces"];function lt(e={}){let t=S.resolve(e.dataRoot??process.env.AITABLE_WORKFLOW_DATA_DIR??$r);return{dataRoot:t,projectsRoot:S.join(t,"projects")}}s(lt,"createWorkspace");async function ft(e){await Ne(e.projectsRoot,{recursive:!0});let t=new Date().toISOString(),r=(await Le(e)).length+1,o={id:`wf_${Br().slice(0,8)}`,title:`\u5DE5\u4F5C\u6D41 #${r}`,dir:"",createdAt:t,updatedAt:t};return o.dir=ht(e,o.id),await Ne(o.dir,{recursive:!0}),await ke(o),o}s(ft,"createProject");async function ae(e,t){let r=await R({dataRoot:S.dirname(S.dirname(e.dir)),projectsRoot:S.dirname(e.dir)},e.id),o={...r,...t,title:t.title?.trim()||r.title,updatedAt:new Date().toISOString()};return await ke(o),o}s(ae,"updateProjectMeta");async function Le(e){let t=await at(e.projectsRoot,{withFileTypes:!0}).catch(()=>[]);return(await Promise.all(t.filter(o=>o.isDirectory()&&dt.test(o.name)).map(o=>R(e,o.name).catch(()=>null)))).filter(o=>o!==null).sort((o,n)=>n.updatedAt.localeCompare(o.updatedAt))}s(Le,"listProjects");async function R(e,t){kt(t);let r=ht(e,t);if(!(await ut(r).catch(()=>null))?.isDirectory())throw Object.assign(new Error(`\u9879\u76EE\u4E0D\u5B58\u5728: ${t}`),{code:"PROJECT_NOT_FOUND",status:404});let n=S.join(r,"project.json"),i=await Me(n,"utf8").catch(()=>"");if(!i){let c=new Date().toISOString(),u={id:t,dir:r,createdAt:c,updatedAt:c};return await ke(u),u}return{...JSON.parse(i),dir:r}}s(R,"resolveProject");async function x(e){let t={...e,updatedAt:new Date().toISOString()};return await ke(t),t}s(x,"touchProject");async function mt(e){return await Promise.all(qr.map(t=>ct(S.join(e.dir,t),{recursive:!0,force:!0}))),await x(e)}s(mt,"resetProjectWorkflow");async function he(e){await ct(e.dir,{recursive:!0,force:!0})}s(he,"deleteProject");async function Ur(e){let t=await Me(yt(e),"utf8").catch(()=>"");return t.trim()?JSON.parse(t):null}s(Ur,"readDesignManifest");async function Be(e,t){await Ne(wt(e),{recursive:!0}),await pt(yt(e),`${JSON.stringify(t,null,2)}
10
+ `,"utf8")}s(Be,"writeDesignManifest");async function gt(e){let t=await Ur(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 ut(S.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(gt,"validateDesignArtifacts");function me(e){return Lr("sha256").update(e).digest("hex")}s(me,"checksumContent");async function D(e){let t=[];return await vt(e.dir,e.dir,t),t.sort((r,o)=>r.path.localeCompare(o.path))}s(D,"listProjectFiles");function B(e){return S.join(e.dir,"aitable-workflow.config.yml")}s(B,"configPath");function $e(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($e,"buildAITableUrl");function zr(e){return S.join(e.dir,"runtime")}s(zr,"runtimeDir");function wt(e){return S.join(zr(e),"artifacts")}s(wt,"artifactsDir");function yt(e){return S.join(wt(e),"design-manifest.json")}s(yt,"designManifestPath");function ht(e,t){return kt(t),S.join(e.projectsRoot,t)}s(ht,"projectDir");function kt(e){if(!dt.test(e))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${e}`),{code:"INVALID_PROJECT_ID"})}s(kt,"assertProjectId");async function ke(e){await pt(S.join(e.dir,"project.json"),`${JSON.stringify(e,null,2)}
11
+ `,"utf8")}s(ke,"writeProjectMeta");async function vt(e,t,r){let o=await at(t,{withFileTypes:!0}).catch(()=>[]);for(let n of o){if(Jr(e,S.join(t,n.name),n.name))continue;let i=S.join(t,n.name);if(n.isDirectory()){await vt(e,i,r);continue}if(!n.isFile()||!Hr.test(n.name))continue;let a=S.relative(e,i).split(S.sep).join("/"),c=await Me(i,"utf8").catch(()=>"");r.push({path:a,content:c})}}s(vt,"walk");function Jr(e,t,r){return r==="node_modules"||r==="traces"||r==="runtime"||r===".aitable"||r==="project.json"?!0:S.relative(e,t).split(S.sep).join("/").startsWith(".aitable/")}s(Jr,"isHiddenProjectFile");function Pt(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(Pt,"deriveProjectTitleFromSop");async function Tt(e,t,r,o,n,i){let a=await R(t,e),c=await I(o),u=await r.createTask(a,"init");try{let p=Xr(c),l=await Yr({answers:p,cwd:a.dir,force:!0}),f=await Qr(ve.join(a.dir,"profile","profile.yml"),c.roles??[]);c.machineId&&i&&await i(e,c.machineId).catch(()=>{});let h=await x(a),k=f.skippedKnowledgeBindings.map(y=>`\u89D2\u8272 ${y.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 profile\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${y.knowledge.join(", ")}`);await r.updateTask(a,u.id,{status:"succeeded",checkpoint:"done",currentAction:"\u914D\u7F6E\u5DF2\u5B8C\u6210",outputs:{warnings:k,roleFiles:[]}});let d=Pt(c.sop,1),v=await ae(h,{title:d});_(n,{project:v,scaffold:l,roleFiles:[],files:await D(h),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:C(p),message:T(p),retryable:!0,details:M(p)}}),p}}s(Tt,"handleInit");async function St(e,t,r,o,n){let i=await R(t,e),c=(await I(o)).tableId?.trim()??"";if(!c)throw Object.assign(new Error("Table Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"TABLE_ID_REQUIRED",status:422});let u=B(i),p=await jt(u,"utf8"),l=He.parse(p);if(!Pe(l)||!Pe(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 Kr(u,He.stringify(l),"utf8");let f=await x(i);_(n,{project:f,files:await D(f),state:await r.getRecoverableState(f)})}s(St,"handleUpdateProjectTableId");async function Dt(e,t,r,o,n,i,a){let c=await R(t,e),u=await I(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(d=>d==="\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 f=u.action==="confirm"?"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EE7\u7EED\u6D41\u7A0B":"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EC8\u6B62\u6D41\u7A0B",h=null;u.action==="confirm"&&(h=await Zr(p,n)),await p.tracker.updateState(n,l),h&&await p.tracker.updateCurrentStep(n,h),await p.tracker.appendEvent(n,f);let k=await r.updateRunSnapshotRecord(c,n,u.action==="confirm"?{state:l,status:"running",currentStepId:h??void 0}:{state:l,status:"done",currentStepId:null},f);_(a,{action:u.action,recordId:n,state:k})}s(Dt,"handleRunHumanAction");async function Zr(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(Zr,"resolveNextStepId");function Xr(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:to(e.agentsSelected),scene:eo(e),baseId:t,tableId:e.tableId?.trim()??"",llmProvider:r,llmModel:r?e.llmModel.trim()||ro(r):"",llmApiKeyEnv:r?oo(r):"",confirmed:!0}}s(Xr,"toInitAnswers");function eo(e){return 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"}s(eo,"buildScene");function to(e){return e.includes("qwenwork")?"qwenwork":e.includes("qoder")?"qoder":e.includes("codex")?"codex":"claudecode"}s(to,"toAgentType");function ro(e){return e==="openai"?"gpt-4o":e==="anthropic"?"claude-sonnet-4-20250514":e==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}s(ro,"defaultModel");function oo(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(oo,"defaultApiKeyEnv");async function Ot(e,t){let r=ve.join(e.dir,"aitable-workflow.config.yml");try{await Gr(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")}await no(e.dir)||t.warnings.push("\u672A\u627E\u5230\u4EFB\u4F55\u89D2\u8272\u5B9A\u4E49\uFF08profile/profile.yml \u7684 roles \u6BB5\u6216 roles/*.role.yml\uFF0Cdesign \u9636\u6BB5 requiresAgent \u7684 step \u9700\u7ED1\u5B9A role\uFF09")}s(Ot,"augmentProjectFileValidation");async function no(e){try{let r=He.parse(await jt(ve.join(e,"profile","profile.yml"),"utf8"));if(Pe(r)&&Pe(r.roles)&&Object.keys(r.roles).length>0)return!0}catch{}return(await Vr(ve.join(e,"roles")).catch(()=>[])).some(r=>r.endsWith(".role.yml")||r.endsWith(".role.yaml"))}s(no,"hasAnyRoleDefinition");import Rt from"fs";import so from"path";var io=/requiresAgent\s*:\s*(true|false)/,At=new Map;function bt(e,t){if(!t)return!1;for(let r of[".recipe.ts",".recipe.js"]){let o=so.join(e,`${t}${r}`);try{let n=Rt.statSync(o);if(!n.isFile())continue;let i=`${n.mtimeMs}:${n.size}`,a=At.get(o);if(a?.signature===i)return a.requiresAgent;let u=Rt.readFileSync(o,"utf8").match(io),p=u?u[1]==="true":!1;return At.set(o,{signature:i,requiresAgent:p}),p}catch(n){if(n.code==="ENOENT")continue;return!1}}return!1}s(bt,"readRecipeRequiresAgent");import{rm as xt,mkdir as ao,writeFile as co}from"fs/promises";import ge from"path";import uo from"yaml";import{isRecord as po,resolveInsideRoot as lo}from"aitable-workflow-core";var It=/\.(json|ya?ml|ts|js|md|txt)$/i,fo=new Set(["runtime","traces","node_modules"]),Et="aitable-workflow.config.yml";function _t(e,t){try{lo(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(_t,"assertSafeRelativePath");function Ft(e,t){_t(e.dir,t)}s(Ft,"assertSafeProjectPath");function qs(e){_t("/workflow-root",e)}s(qs,"assertSafeWorkflowPath");function Wt(e){let r=Nt(e).split("/")[0]??"";return fo.has(r)}s(Wt,"isForbiddenWritable");function mo(e){if(Wt(e))throw Object.assign(new Error(`\u7981\u6B62\u5199\u5165\u53D7\u4FDD\u62A4\u76EE\u5F55: ${e}`),{code:"invalid_path",status:400});if(!It.test(e))throw Object.assign(new Error(`\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8\u5199\u5165: ${e}\uFF08\u4EC5\u5141\u8BB8 ${It.source}\uFF09`),{code:"invalid_path",status:400})}s(mo,"assertWritableKind");function Ct(e){let t=Nt(e);return t===Et||t.endsWith(".config.yml")?"config":t==="workflow.yml"?"workflow":t==="views.yml"?"views":t.startsWith("recipes/")?"recipe":t.startsWith("roles/")?"role":"other"}s(Ct,"kindOf");function Nt(e){return ge.posix.normalize(e.replace(/\\/g,"/")).replace(/^\.\//,"")}s(Nt,"normalizeLogicalPath");function go(e){let t=[],r;try{r=uo.parse(e)}catch(n){return t.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),t}if(!po(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(go,"validateConfigScene");async function je(e,t){let r=[],o=[];for(let n of t){Ft(e,n.path),mo(n.path);let i=ge.join(e.dir,n.path);await ao(ge.dirname(i),{recursive:!0}),await co(i,n.content,"utf8"),r.push({path:n.path,content:n.content}),n.path===Et&&o.push(...go(n.content))}return{written:r,warnings:o}}s(je,"writeProjectFiles");async function Mt(e,t){for(let r of t){if(Ft(e,r),Wt(r))throw Object.assign(new Error(`\u7981\u6B62\u5220\u9664\u53D7\u4FDD\u62A4\u76EE\u5F55: ${r}`),{code:"invalid_path",status:400});await xt(ge.join(e.dir,r),{force:!0})}}s(Mt,"removeProjectFiles");async function Lt(e,t){let r=await wo(e);for(let o of r)await xt(ge.join(e.dir,o),{force:!0}).catch(()=>{});return je(e,t)}s(Lt,"replaceProjectFiles");async function wo(e){return(await D(e)).map(r=>r.path).filter(r=>Ct(r)!=="other")}s(wo,"collectBusinessFiles");function yo(e){return me(e.content)}s(yo,"checksumFile");async function Bt(e){let t=await D(e),r=t.map(o=>({path:o.path,sha256:yo(o)}));return{project:e,files:t,checksums:r,exportedAt:new Date().toISOString()}}s(Bt,"buildProjectExport");var ho="coding-agents.config.json";function $t(e){let t=[],r=e.files,o=e.checksums,n=r.findIndex(i=>i.path===ho);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 f=u[l];if(!f||typeof f!="object"||Array.isArray(f))continue;let h=f.env;if(h&&typeof h=="object"&&!Array.isArray(h)){let k=h;if(Object.values(k).some(v=>typeof v=="string"&&v!=="")){for(let v of Object.keys(k))k[v]="";p=!0}}}p&&(a=JSON.stringify(c,null,2)+`
12
+ `)}}}catch{}if(a!==i.content){let c={path:i.path,content:a};r=r.map((p,l)=>l===n?c:p);let u=me(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($t,"redactExportBundle");import{logger as Ht}from"aitable-workflow-core";function Te(e,t){let r={...e.stages,[t.stage]:we(t)};return U({id:t.projectId,dir:"",createdAt:"",updatedAt:t.updatedAt},{...e,projectId:t.projectId,activeStage:qe(t.status)?t.stage:e.activeStage===t.stage?null:e.activeStage,stages:r,updatedAt:t.updatedAt})}s(Te,"mergeTaskIntoState");function U(e,t){let r=new Date().toISOString(),o=t.stages??{};return{projectId:t.projectId??e.id,activeStage:t.activeStage??ko(o),stages:o,runSnapshot:t.runSnapshot,updatedAt:t.updatedAt??e.updatedAt??r}}s(U,"normalizeProjectState");function we(e){let t=vo(e);return t?{task:e,recoveryAction:t}:{task:e}}s(we,"stageStateOf");function N(e){if(!e.activeStage)return null;let t=e.stages[e.activeStage]?.task;return t&&qe(t.status)?t:null}s(N,"activeTaskOf");function qe(e){return e==="running"||e==="blocked"}s(qe,"isActiveStatus");function Se(e){return e==="failed"||e==="succeeded"||e==="cancelled"}s(Se,"isTerminalStatus");function ko(e){for(let[t,r]of Object.entries(e))if(r&&qe(r.task.status))return t;return null}s(ko,"findActiveStage");function vo(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??Po(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:jo(e.stage),description:e.error.message,api:{method:"POST",path:To(e)}}}s(vo,"recoveryActionForTask");function Po(e){return e==="setup"?"\u7EE7\u7EED\u642D\u5EFA":e==="design"?"\u7EE7\u7EED\u8BBE\u8BA1":e==="run"?"\u7EE7\u7EED\u8FD0\u884C":"\u7EE7\u7EED"}s(Po,"continueLabel");function jo(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(jo,"retryLabel");function To(e){return e.stage==="design"?`/api/projects/${e.projectId}/design`:`/api/projects/${e.projectId}/tasks/${e.stage}/retry`}s(To,"retryPath");function Ut(e){return{appFactory:e,runSessions:new Map}}s(Ut,"createServerRuntime");async function zt(e,t,r,o,n,i){let a=await R(t,e),c=await r.getState(a),u=o.runSessions.get(e);if(u){qt(u,n,i);let h=await r.getState(a),k=N(h),d=k?.stage==="run"?k:h.stages.run?.task;d&&Kt(u,{type:"task.snapshot",task:d},i);return}let p=N(c);if(p?.stage==="run"&&p.status==="running"){let k={type:"task.failed",task:await r.updateTask(a,p.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,k.type,k),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 l=await r.createTask(a,"run"),f={taskId:l.id,subscribers:new Set,events:[],app:null,snapshotWrite:Promise.resolve()};o.runSessions.set(e,f),qt(f,n,i),So(a,l,f,o,r,i)}s(zt,"handleRunRuntime");function Jt(e,t){if(!t)return e;let r=e.stages.run?.task;return!r||r.status==="running"?e:{...e,activeStage:"run",stages:{...e.stages,run:{task:{...r,id:t.taskId,status:"running",checkpoint:"listening",currentAction:"\u771F\u5B9E\u8FD0\u884C\u670D\u52A1\u5DF2\u542F\u52A8\uFF0C\u6B63\u5728\u76D1\u542C AI \u8868\u683C\u4E2D\u7684\u5F85\u5904\u7406\u8BB0\u5F55",block:void 0,error:void 0}}}}}s(Jt,"overlayRunSessionState");async function So(e,t,r,o,n,i){let a=s(u=>{Kt(r,u,i),Oo(u)&&(Ht.info("run-runtime","publish run execution event",Ro(u)),r.snapshotWrite=r.snapshotWrite.then(()=>n.appendRunSnapshotEvent(e,u)).catch(p=>{Ht.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(B(e),l=>a(Do(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:Gt(u),message:Vt(u),retryable:!0,details:Yt(u)}});a({type:"task.failed",task:p}),a({type:"error",error:bo(u)})}finally{o.runSessions.delete(e.id),Ao(r)}}s(So,"startRunSession");function Do(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(Do,"toRunEventDTO");function Oo(e){return e.type.startsWith("run.record.")||e.type.startsWith("run.step.")}s(Oo,"isRunExecutionEvent");function Ro(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(Ro,"summarizeRunExecutionEvent");function qt(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(qt,"attachRunSubscriber");function Kt(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(Kt,"publishRunEvent");function Ao(e){for(let t of e.subscribers)t.end();e.subscribers.clear()}s(Ao,"closeRunSubscribers");function bo(e){return{code:Gt(e),message:Vt(e),details:Yt(e)}}s(bo,"apiError");function Gt(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:"INTERNAL_ERROR"}s(Gt,"errorCode");function Vt(e){return e instanceof Error?e.message:String(e)}s(Vt,"errorMessage");function Yt(e){if(typeof e=="object"&&e!==null&&"details"in e)return e.details}s(Yt,"errorDetails");import Io from"path";import{loadWorkflowTemplate as xo}from"aitable-workflow-core";function Qt(e){let t=s(r=>r.env.services.projectStore.workflows?null:F(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{services:o,scope:n}=r.env;return o.projectStore.workflows?w(r,{workflows:await o.projectStore.workflows.list(r.env.project.id,n)}):w(r,{workflows:await Eo(r.env.project)})}),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 I(a);if(!u.name||!u.name.trim())return F(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 O(c,n);let l={workflow:p.workflow};return p.files&&(l.files=p.files),p.warnings&&p.warnings.length>0&&(l.warnings=p.warnings),w(r,l)}),e.get("/:projectId/workflows/:workflowId",async r=>{let{services:o,scope:n}=r.env;if(!o.projectStore.workflows){let a=await _o(r.env.project,r.req.param("workflowId")??"");return a?w(r,a):F(r,404,"WORKFLOW_NOT_FOUND","\u5DE5\u4F5C\u6D41\u4E0D\u5B58\u5728")}let i=await o.projectStore.workflows.exportWorkflow(r.env.project.id,r.req.param("workflowId")??"",n);return w(r,{workflow:i.workflow,files:i.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 F(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 O(a,n),w(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 I(a);if(!Array.isArray(p.files))return F(r,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");let l=await n.projectStore.workflows.replaceFiles(u,p.files,i);return await O(c,n),w(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 I(a),l=await n.projectStore.workflows.updateFiles(u,{upsert:p.upsert,remove:p.remove},i);return await O(c,n),w(r,{workflow:u,files:l})})}s(Qt,"registerWorkflowRoutes");async function Eo(e){let t=await D(e),r=Zt(t);return(await Promise.all(r.map(n=>rr(e,n,t)))).sort((n,i)=>n.name.localeCompare(i.name))}s(Eo,"listLocalWorkflows");async function _o(e,t){let r=await D(e),o=Zt(r).find(c=>Xt(c)===t);if(!o)return null;let n=await rr(e,o,r),i=er(o),a=r.filter(c=>tr(c.path,o)).map(c=>({...c,path:c.path.slice(i.length)}));return{workflow:n,files:a}}s(_o,"exportLocalWorkflow");function Zt(e){return e.map(t=>t.path).filter(t=>t==="workflow.yml"||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(t))}s(Zt,"localWorkflowTemplatePaths");function Xt(e){return e==="workflow.yml"?"main":e.split("/")[1]??"main"}s(Xt,"localWorkflowId");function er(e){return e==="workflow.yml"?"":e.replace(/workflow\.ya?ml$/,"")}s(er,"workflowBase");function tr(e,t){let r=er(t);return r?e.startsWith(r):e==="workflow.yml"||e==="views.yml"||e.startsWith("recipes/")}s(tr,"belongsToWorkflow");async function rr(e,t,r){let o=Xt(t),n=await xo(Io.join(e.dir,t)).catch(a=>(console.warn(`\u52A0\u8F7D\u672C\u5730\u5DE5\u4F5C\u6D41\u6A21\u677F\u5931\u8D25 [${t}]\uFF1A`,a instanceof Error?a.message:String(a)),null)),i=r.filter(a=>tr(a.path,t)).length;return{id:o,projectId:e.id,name:n?.meta.name??o,domain:n?.meta.domain,templatePath:t,tableId:n?.tracker?.table_id,fileCount:i,createdAt:e.createdAt,updatedAt:e.updatedAt}}s(rr,"buildLocalWorkflow");function Fo(){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(Fo,"readSseHeartbeatMs");function z(e){e.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),Wo(e)}s(z,"startSse");function Wo(e){let t=Fo(),r=setInterval(()=>{if(e.writableEnded||!e.writable){clearInterval(r);return}try{e.write(`:keepalive
12
13
 
13
- `)}catch{clearInterval(r)}},t);r.unref?.();let o=s(()=>clearInterval(r),"stop");e.on("close",o),e.on("finish",o)}s(Br,"startSseHeartbeat");function q(e,t,r){e.write(`event: ${t}
14
+ `)}catch{clearInterval(r)}},t);r.unref?.();let o=s(()=>clearInterval(r),"stop");e.on("close",o),e.on("finish",o)}s(Wo,"startSseHeartbeat");function G(e,t,r){e.write(`event: ${t}
14
15
  `),e.write(`data: ${JSON.stringify(r)}
15
16
 
16
- `)}s(q,"writeSse");async function bt(e,t,r,o,n,i){let a=await A(t,e),c=await b(o),u=await r.createTask(a,"init");try{let p=Kr(c),l=await zr({answers:p,cwd:a.dir,force:!0}),m=await Jr(Ce.join(a.dir,"roles"),c.roles??[]);c.machineId&&i&&await i(e,c.machineId).catch(()=>{});let d=await I(a),k=m.skippedKnowledgeBindings.map(V=>`\u89D2\u8272 ${V.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 role.yml\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${V.knowledge.join(", ")}`);await r.updateTask(a,u.id,{status:"succeeded",checkpoint:"done",currentAction:"\u914D\u7F6E\u5DF2\u5B8C\u6210",outputs:{warnings:k,roleFiles:m.files}});let w=Dt(c.sop,1),T=await ne(d,{title:w});N(n,{project:T,scaffold:l,roleFiles:m.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:E(p),message:v(p),retryable:!0,details:W(p)}}),p}}s(bt,"handleInit");async function At(e,t,r,o,n){let i=await A(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=F(i),p=await $r(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 Hr(u,St.stringify(l),"utf8");let m=await I(i);N(n,{project:m,files:await S(m),state:await r.getRecoverableState(m)})}s(At,"handleUpdateProjectTableId");async function It(e,t,r,o,n,i,a){let c=await A(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 m=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 Gr(p,n)),await p.tracker.updateState(n,l),d&&await p.tracker.updateCurrentStep(n,d),await p.tracker.appendEvent(n,m);let k=await r.updateRunSnapshotRecord(c,n,u.action==="confirm"?{state:l,status:"running",currentStepId:d??void 0}:{state:l,status:"done",currentStepId:null},m);N(a,{action:u.action,recordId:n,state:k})}s(It,"handleRunHumanAction");async function Gr(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(Gr,"resolveNextStepId");async function Me(e,t,r,o,n,i){L(i),await kt(e,t,r,o,i,q)}s(Me,"handleRun");function Kr(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:Yr(e.agentsSelected),scene:Vr(e),baseId:t,tableId:e.tableId?.trim()??"",llmProvider:r,llmModel:r?e.llmModel.trim()||Qr(r):"",llmApiKeyEnv:r?Zr(r):"",confirmed:!0}}s(Kr,"toInitAnswers");function Vr(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
- ${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
-
19
- `)}s(Vr,"buildScene");function Yr(e){return e.includes("qoder")?"qoder":e.includes("codex")?"codex":"claudecode"}s(Yr,"toAgentType");function Qr(e){return e==="openai"?"gpt-4o":e==="anthropic"?"claude-sonnet-4-20250514":e==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}s(Qr,"defaultModel");function Zr(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(Zr,"defaultApiKeyEnv");async function Rt(e,t){let r=Ce.join(e.dir,"aitable-workflow.config.yml");try{await Ur(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=Ce.join(e.dir,"roles");try{(await qr(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 Xr from"path";var eo=/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=Xr.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(eo),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 to,writeFile as ro}from"fs/promises";import R from"path";import oo from"yaml";import{isRecord as no}from"aitable-workflow-core";var Ft=/\.(json|ya?ml|ts|js|md|txt)$/i,so=new Set(["runtime","traces","node_modules"]),Ct="aitable-workflow.config.yml";function Mt(e,t){if(typeof t!="string"||t.trim()==="")throw Object.assign(new Error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A"),{code:"invalid_path",status:400});if(R.isAbsolute(t))throw Object.assign(new Error(`\u4E0D\u5141\u8BB8\u7EDD\u5BF9\u8DEF\u5F84: ${t}`),{code:"invalid_path",status:400});let r=R.normalize(t).split(R.sep).join("/");if(r===".."||r.startsWith("../")||r.includes("/../")||r.startsWith("..\\"))throw Object.assign(new Error(`\u8DEF\u5F84\u4E0D\u5141\u8BB8\u5305\u542B ..: ${t}`),{code:"invalid_path",status:400});let o=R.resolve(e,r),n=R.relative(e,o);if(n.startsWith("..")||R.isAbsolute(n))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 As(e){Mt("/workflow-root",e)}s(As,"assertSafeWorkflowPath");function Lt(e){let r=R.normalize(e).split(R.sep).join("/").split("/")[0]??"";return so.has(r)}s(Lt,"isForbiddenWritable");function io(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(io,"assertWritableKind");function Bt(e){let t=R.normalize(e).split(R.sep).join("/");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 ao(e){let t=[],r;try{r=oo.parse(e)}catch(n){return t.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${n instanceof Error?n.message:String(n)}`),t}if(!no(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(ao,"validateConfigScene");async function ye(e,t){let r=[],o=[];for(let n of t){Nt(e,n.path),io(n.path);let i=R.join(e.dir,n.path);await to(R.dirname(i),{recursive:!0}),await ro(i,n.content,"utf8"),r.push({path:n.path,content:n.content}),n.path===Ct&&o.push(...ao(n.content))}return{written:r,warnings:o}}s(ye,"writeProjectFiles");async function $t(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(R.join(e.dir,r),{force:!0})}}s($t,"removeProjectFiles");async function Ht(e,t){let r=await co(e);for(let o of r)await Wt(R.join(e.dir,o),{force:!0}).catch(()=>{});return ye(e,t)}s(Ht,"replaceProjectFiles");async function co(e){return(await S(e)).map(r=>r.path).filter(r=>Bt(r)!=="other")}s(co,"collectBusinessFiles");function uo(e){return de(e.content)}s(uo,"checksumFile");async function Ut(e){let t=await S(e),r=t.map(o=>({path:o.path,sha256:uo(o)}));return{project:e,files:t,checksums:r,exportedAt:new Date().toISOString()}}s(Ut,"buildProjectExport");var po="coding-agents.config.json";function qt(e){let t=[],r=e.files,o=e.checksums,n=r.findIndex(i=>i.path===po);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 m=u[l];if(!m||typeof m!="object"||Array.isArray(m))continue;let d=m.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=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(Pe,"writeTask");async function K(e,t){await De(e),await sr(cr(e),`${JSON.stringify(t,null,2)}
22
- `,"utf8")}s(K,"writeProjectState");async function se(e,t){let r=e.dir||e.id,n=(je.get(r)??Promise.resolve()).catch(()=>{}).then(t),i=n.then(()=>{},()=>{});je.set(r,i);try{return await n}finally{je.get(r)===i&&je.delete(r)}}s(se,"withProjectStateWrite");function yn(e){try{return JSON.parse(e)}catch(t){let r=kn(e);if(!r)throw t;return{...JSON.parse(r),repaired:!0}}}s(yn,"parseProjectStateJson");function kn(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(kn,"extractFirstJsonObject");function hn(e,t,r){return e.map(o=>o.id===t?r(o):o)}s(hn,"updateRunRecord");function Tn(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(Tn,"appendRunLog");function Ue(e){if(!sn.test(e))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${e}`),{code:"INVALID_PROJECT_ID"})}s(Ue,"assertProjectId");var Se=class{static{s(this,"LocalProjectStore")}projects;instances;workflows;constructor(t){this.projects=tr(t),this.instances=ir(t)}async prepareWorkdir(t,r){return{project:await I(t),materialized:0,warnings:[]}}async commitWorkdir(t,r){}async cascadeDelete(t){}};var Oe=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 be=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 pr(e={}){let t=e.workspace??it({dataRoot:e.dataRoot});return{workspace:t,runtime:yt(e.appFactory??((r,o)=>vn(r,{onRunEvent:o}))),projectStore:e.projectStore??new Se(t),execution:e.execution??new Oe,identityService:e.identityService??new be,extendApp:e.extendApp,webRoot:e.webRoot}}s(pr,"createServerServices");function dr(e=process.env){let t=e.AITABLE_RELAY_BOOTSTRAP_KEY;return typeof t=="string"&&t.trim()!==""?(jn.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(dr,"warnDeprecatedBootstrapKey");var Pn="127.0.0.1",ha=8787;function Ae(e){if(typeof e!="string")return;let t=e.trim();return t||void 0}s(Ae,"readEnvString");function Dn(e){let t=Ae(e);if(t===void 0)return;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>0?r:void 0}s(Dn,"readEnvPort");function lr(e={},t=process.env){let r=e.host??Ae(t.AITABLE_WORKFLOW_HOST)??Pn,o=e.port??Dn(t.AITABLE_WORKFLOW_PORT)??8787,n=e.dataRoot??Ae(t.AITABLE_WORKFLOW_DATA_DIR)??void 0,i=e.webRoot??Ae(t.AITABLE_WORKFLOW_WEB_ROOT)??void 0;return{host:r,port:o,dataRoot:n,webRoot:i}}s(lr,"resolveServeConfig");import fe from"path";import{readFile as Sn,access as On}from"fs/promises";var bn={".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 fr(e,t,r,o){let n=fe.resolve(e),i=fe.join(n,"index.html"),a=decodeURIComponent(t).replace(/^\/+/,""),c=a===""?i:fe.resolve(n,a),p=c===n||c.startsWith(n+fe.sep)?c:i;try{await On(p)}catch{p=i}try{let l=await Sn(p),m=fe.extname(p).toLowerCase(),d=bn[m]??"application/octet-stream";if(o.writeHead(200,{"Content-Type":d,"Content-Length":l.byteLength}),r.method==="HEAD"){o.end();return}o.end(l)}catch{U(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(fr,"serveStaticWeb");async function _a(e={}){dr();let t=lr({port:e.port,host:e.host,dataRoot:e.dataRoot,webRoot:e.webRoot}),r=e.services??pr({dataRoot:t.dataRoot,appFactory:e.appFactory,webRoot:t.webRoot}),o=An.createServer((n,i)=>{Rn(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(_a,"startServer");var mr=new WeakMap;function In(e){let t=mr.get(e);return t||(t=er(),e.extendApp?.(t),mr.set(e,t)),t}s(In,"appFor");async function Rn(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 fr(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:xn(t.headers)}),a=await In(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(Rn,"handleRequest");function xn(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(xn,"toFetchHeaders");import gr from"path";function Ma(e){let t=gr.normalize(e).split(gr.sep).join("/");return t==="workflow.yml"?"workflow":t==="views.yml"?"views":t.startsWith("recipes/")?"recipe":"other"}s(Ma,"workflowFileKind");function Ba(){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(Ba,"createProjectMutexStore");export{Pn as DEFAULT_SERVE_HOST,ha as DEFAULT_SERVE_PORT,Oe as LocalExecutionBackend,be as LocalIdentityService,Se as LocalProjectStore,te as apiError,Nt as assertSafeProjectPath,Mt as assertSafeRelativePath,As as assertSafeWorkflowPath,io as assertWritableKind,G as backendOf,We as buildAITableUrl,et as cascadeDeleteProject,de as checksumContent,pe as commitStageOnTerminal,F as configPath,er as createHonoApp,tr as createLocalProjectRepository,ir as createLocalWorkflowInstanceStore,at as createProject,Ba as createProjectMutexStore,yt as createServerRuntime,pr as createServerServices,it as createWorkspace,ge as deleteProject,_ as errorBody,E as errorCode,W as errorDetails,v as errorMessage,re as errorStatus,Rn as handleRequest,kt as handleRunRuntime,Lt as isForbiddenWritable,Sr as isStageActiveFor,ve as isTerminalStatus,y as jsonBody,Bt as kindOf,S as listProjectFiles,_e as listProjects,Te as mergeTaskIntoState,B as normalizeProjectState,ht as overlayRunSessionState,j as prepareWorkdirGuarded,C as raw,xr as readDesignManifest,b as readJson,$t as removeProjectFiles,Ht as replaceProjectFiles,ct as resetProjectWorkflow,A as resolveProject,Ie as resolveProjectMw,lr as resolveServeConfig,U as sendError,N as sendJson,_n as sendUnauthorized,_a as startServer,I as touchProject,Ye as unauthorized,ne as updateProjectMeta,ao as validateConfigScene,ut as validateDesignArtifacts,dr as warnDeprecatedBootstrapKey,Ma as workflowFileKind,Fe as writeDesignManifest,ye as writeProjectFiles};
17
+ `)}s(G,"writeSse");var Ue=class{constructor(t){this.services=t}services;static{s(this,"LocalRunController")}mode="local";async start(t,r){z(r),await zt(t,this.services.workspace,this.services.projectStore.instances,this.services.runtime,r,G)}async stop(t){let r=this.services.runtime.runSessions.get(t);if(!r)return{mode:this.mode,running:!1,stopped:!1};if(!r.app)throw Object.assign(new Error("\u8FD0\u884C\u4F1A\u8BDD\u6B63\u5728\u542F\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"),{code:"RUN_STARTING",status:409});return await r.app.stop(),{mode:this.mode,running:!1,stopped:!0,taskId:r.taskId}}async status(t){let r=this.services.runtime.runSessions.get(t);return{mode:this.mode,running:r!=null,taskId:r?.taskId??null}}async listRecords(t,r){let o=await R(this.services.workspace,t),i=(await this.services.projectStore.instances.getState(o)).runSnapshot?.records??[],a=r?.limit??100;return{items:[...i].sort((u,p)=>p.updatedAt-u.updatedAt).slice(0,a).map(u=>({itemId:u.id,title:u.title,state:u.state,currentStepId:u.currentStepId,doneStepIds:u.doneStepIds,completedAt:u.status==="done"?new Date(u.updatedAt).toISOString():null,updatedAt:new Date(u.updatedAt).toISOString(),status:u.status})),counts:{total:i.length,completed:i.filter(u=>u.status==="done").length}}}},ze=class{constructor(t,r){this.scheduler=t;this.records=r}scheduler;records;static{s(this,"LeaseRunController")}mode="lease";async start(t,r){_(r,{mode:this.mode,action:"start",schedule:await this.scheduler.start(t)})}async stop(t){return{mode:this.mode,action:"stop",schedule:await this.scheduler.stop(t)}}async status(t){return{mode:this.mode,action:"status",schedule:await this.scheduler.getStatus(t)}}async listRecords(t,r){return this.records?this.records.listRecords(t,r):{items:[],counts:{total:0,completed:0}}}};function ce(e){let{runScheduler:t,runRecords:r}=e.execution;return t?new ze(t,r):new Ue(e)}s(ce,"resolveRunController");import Co from"path";import{collectDesignContext as sr,runDesign as No,runClarifyRound as Mo,syncFieldsFromWorkflow as Lo,syncViewsFromDesign as Bo,summarizeForms as $o,validateFormAnswers as Ho,pruneHiddenAnswers as qo,logger as or}from"aitable-workflow-core";var De=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 ir(e,t,r,o,n){let i=await R(t,e),a=await r.getState(i),c=a.stages.design?.task,u=c?.status==="failed"?c:null;if(u){await r.clearActiveTask(i,u.id),_(o,{task:u,error:{code:"DESIGN_RETRY_REQUIRED",message:u.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 p=N(a),l=p?.stage==="design"?p:null,f=l||await r.createTask(i,"design");try{let h=B(i),k=await sr({configPath:h,yes:!0}),d=k.agentType?await Mo(k,{...await ar(n,i,k.agentType),timeoutMs:k.agentTimeoutMs,interactive:!0,judgeOnly:!0}):void 0;if(!d?.form){let A=k.agentType?"Agent \u5224\u65AD\u5F53\u524D\u9700\u6C42\u5DF2\u8DB3\u591F\u660E\u786E\uFF0C\u672A\u63D0\u51FA\u6F84\u6E05\u95EE\u9898\uFF0C\u76F4\u63A5\u5F00\u59CB\u751F\u6210\u3002":"\u5F53\u524D\u5B9E\u4F8B\u672A\u914D\u7F6E coding agent\uFF0C\u8DF3\u8FC7\u9700\u6C42\u6F84\u6E05\u3002",Z={form:{id:"clarify",title:"\u65E0\u9700\u6F84\u6E05",questions:[]},answers:{},summary:A,clarifications:A,confirmed:!0,...d?.sessionId?{agentSessionId:d.sessionId}:{}},X=await r.updateTask(i,f.id,{status:"running",checkpoint:"discovery_confirmed",currentAction:"\u9700\u6C42\u5DF2\u660E\u786E\uFF0C\u51C6\u5907\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848",block:void 0,error:void 0,outputs:{...f.outputs,discovery:Z,clarifications:A}});_(o,{task:X,discovery:Z});return}let v={form:d.form,answers:Uo(d.form),summary:d.form.description??d.form.title,confirmed:!1,...d.sessionId?{agentSessionId:d.sessionId}:{}},y=await r.updateTask(i,f.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:{...f.outputs,discovery:v}});_(o,{task:y,discovery:v})}catch(h){let k=await r.updateTask(i,f.id,{status:"failed",checkpoint:"discovery_precheck",currentAction:"\u9700\u6C42\u6F84\u6E05\u51C6\u5907\u5931\u8D25",error:{code:"DESIGN_PRECHECK_FAILED",message:T(h),retryable:!0,details:M(h)}});_(o,{task:k,error:ne(h)},500)}}s(ir,"handleDesignDiscovery");async function ar(e,t,r){let o=await e.buildDesignExecutor({projectId:t.id,agent:r,projectDir:t.dir});return o?{executor:o}:{}}s(ar,"relayExecutorFor");function Uo(e){let t=Object.fromEntries(e.questions.map(r=>[r.id,r.defaultValue??(r.type==="checkbox"?[]:"")]));return qo(e,t)}s(Uo,"seedAnswers");async function cr(e,t,r,o,n){let i=await R(t,e),a=await r.getState(i),c=N(a),u=c?.stage==="design"?c:a.stages.design?.task,p=u?.outputs?.discovery;if(!u||!p){q(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 l=o.answers,f=l&&Object.keys(l).length>0?l:p.answers,h=Ho(p.form,f);if(h.length>0){q(n,400,"DISCOVERY_INVALID_ANSWERS",`\u9700\u6C42\u6F84\u6E05\u7B54\u6848\u4E0D\u5B8C\u6574\uFF1A${h.map(y=>y.message).join("\uFF1B")}`,{issues:h});return}let k=$o([{form:p.form,answers:f}]),d={...p,answers:f,clarifications:k,summary:k.replace(/\s+/g," ").trim(),confirmed:!0},v=await r.updateTask(i,u.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:{...u.outputs,discovery:d,clarifications:k}});_(n,{task:v,discovery:d})}s(cr,"handleDesignDiscoveryConfirm");async function ur(e,t,r,o,n,i){let a=await R(t,e);try{n.ensureAvailable()}catch(g){q(o,se(g),C(g),T(g));return}let c=await r.getState(a),u=N(c),p=u?.stage==="design"?u:null;if(p&&p.status==="blocked"){z(o),G(o,"task.blocked",{type:"task.blocked",task:p}),o.end();return}if(ie.has(a.id)){z(o);let g=le.get(a.id);if(g){for(let P of g.buffer.replayAfter(i))Ce(o,P.seq,P.event);g.subscribers.add(o),o.on("close",()=>g.subscribers.delete(o));return}p&&G(o,"task.snapshot",{type:"task.snapshot",task:p}),o.end();return}let l=c.stages.design?.task,f=l?.outputs?.discovery,h=f?.confirmed&&typeof l?.outputs?.clarifications=="string";if(p&&p.status==="running"&&!h){z(o),G(o,"task.snapshot",{type:"task.snapshot",task:p}),o.end();return}let k=l?.status==="failed"&&f?.confirmed&&typeof l.outputs?.clarifications=="string",d=p&&h?p:k?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:f,clarifications:l.outputs?.clarifications}}):await r.createTask(a,"design");ie.add(a.id),z(o);let v={buffer:new De,subscribers:new Set([o])};le.set(a.id,v),o.on("close",()=>v.subscribers.delete(o));let y=s(g=>ot(v,g),"send"),A=Date.now(),Z=A,X=0,ee=[],J=[],$=s((g,P,j)=>{let W=Date.now(),oe=W-A,E=W-Z;Z=W,ee.push({phase:g,message:P,elapsedMs:oe,deltaMs:E,detail:j}),or.info("design-runtime",P,{projectId:a.id,taskId:d.id,phase:g,elapsedMs:oe,deltaMs:E,...j?{detail:j}:{}}),y({type:"design.progress",phase:g,message:P,elapsedMs:oe,deltaMs:E,detail:j})},"emitProgress"),b=s(async(g,P,j)=>{$(g,P,j);let W=await r.updateTask(a,d.id,{currentAction:P,checkpoint:g});y({type:"task.progress",taskId:W.id,message:P,checkpoint:g})},"progress"),ye="",pe=!1,de=!1,Y=s(async()=>{if(pe){de=!0;return}pe=!0;try{do{de=!1;let P=(await D(a)).filter(j=>j.path!=="project.json").map(j=>`${j.path}:${j.content}`).join("|");if(P&&P!==ye){ye=P;let j=await x(a),W=await D(j);$("file_snapshot",`\u540C\u6B65 ${W.length} \u4E2A\u751F\u6210\u6587\u4EF6`,{fileCount:W.length}),y({type:"design.files",files:W})}}while(de)}finally{pe=!1}},"sendFileSnapshot");try{y({type:"task.started",task:d}),y({type:"design.started",projectId:e}),await Y();let g,P;try{await b("precheck","\u8BFB\u53D6 Design \u914D\u7F6E"),P=B(a),g=await sr({configPath:P,yes:!0}),await b("precheck_done","Design \u914D\u7F6E\u8BFB\u53D6\u5B8C\u6210",{agent:g.agentType,timeoutMs:g.agentTimeoutMs})}catch(m){let H=await r.updateTask(a,d.id,{status:"failed",checkpoint:"precheck",currentAction:"Design \u9884\u68C0\u67E5\u5931\u8D25",error:{code:"DESIGN_PRECHECK_FAILED",message:T(m),retryable:!0,details:M(m)}});y({type:"task.failed",task:H}),y({type:"error",error:ne(m)}),o.end();return}let j=d.outputs?.discovery,W=typeof d.outputs?.clarifications=="string"?d.outputs.clarifications:j?.clarifications;if(!j?.confirmed||!W){await b("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});y({type:"task.blocked",task:m}),o.end();return}g.clarifications=W,await b("brief_ready","\u9700\u6C42\u6458\u8981\u5DF2\u786E\u8BA4\uFF0C\u51C6\u5907\u542F\u52A8 Agent"),y({type:"design.discovery",summary:j.summary}),await b("agent_start","\u542F\u52A8 Coding Agent \u751F\u6210\u6D41\u7A0B\u65B9\u6848",{agent:g.agentType,timeoutMs:null,timeoutSource:"disabled"});let oe=!1,E=await No(g,{...await ar(n,a,g.agentType),...j.agentSessionId?{resume:{sessionId:j.agentSessionId,answered:[{form:j.form,answers:j.answers}]}}:{},timeoutMs:null,onRoundStart:s((m,H)=>{$("agent_round",`\u7B2C ${m} \u8F6E ${H?"\u4FEE\u6B63":"\u751F\u6210"}\u5F00\u59CB`,{round:m,isFix:H}),y({type:"design.round_start",round:m,isFix:H})},"onRoundStart"),onEvent:s(m=>{zo(m)&&(J.push(Jo(m)),J.length>30&&J.shift(),oe||(oe=!0,$("agent_first_event",`\u6536\u5230 Agent \u9996\u4E2A\u4E8B\u4EF6\uFF1A${m.type}`,{eventType:m.type})),m.type==="tool_use"&&$("agent_tool","Agent \u8C03\u7528\u5DE5\u5177",{toolName:m.toolName}),(m.type==="text"||m.type==="thinking")&&Date.now()-X>5e3&&(X=Date.now(),$("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)})),y({type:"design.agent_event",event:m}),(m.type==="tool_use"||m.type==="tool_result")&&Y())},"onEvent"),onAgentLifecycle:s(m=>{$(Ko(m.phase),Go(m),Vo(m))},"onAgentLifecycle"),onValidation:s((m,H)=>{$("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:H,valid:m.valid,errorCount:m.errors.length}),y({type:"design.validation",round:H,validation:m}),Y()},"onValidation")});if(!E.success){await Y();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:E.response,retryable:!0},outputs:{...d.outputs,diagnostics:Je(A,ee,J,E.validation)}});await nr(a,m,E.response),y({type:"task.failed",task:m}),y({type:"design.done",success:!1,rounds:E.rounds,response:E.response}),o.end();return}await b("sync_fields","\u540C\u6B65\u5B57\u6BB5\u8BA1\u5212\u5230\u914D\u7F6E");for(let m of g.workflows)await Lo({workflowPath:m.workflowPath,configPath:P,autoUpdate:!0}).catch(H=>(or.warn("design","\u5B57\u6BB5\u540C\u6B65\u5931\u8D25(\u4E0D\u963B\u65AD)",{workflow:m.id,error:T(H)}),null));await b("sync_views","\u540C\u6B65\u89C6\u56FE\u8BA1\u5212\u5230\u914D\u7F6E"),await Bo({viewsPath:Co.resolve(g.workDir,"views.yml"),configPath:P,autoUpdate:!0}).catch(()=>null),await Y(),await b("manifest","\u5199\u5165 Design \u4EA7\u7269\u6E05\u5355");let br=await D(a),Qe=Yo(a,d,br);await Be(a,Qe);let Ir=await r.updateTask(a,d.id,{status:"succeeded",currentAction:"\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u5B8C\u6210",checkpoint:"done",outputs:{...d.outputs,manifest:Qe,diagnostics:Je(A,ee,J,E.validation)}});y({type:"task.succeeded",task:Ir}),y({type:"design.done",success:!0,rounds:E.rounds,response:E.response}),o.end()}catch(g){await Y().catch(()=>{});let P=await r.updateTask(a,d.id,{status:"failed",checkpoint:"generating",currentAction:"\u771F\u5B9E\u8BBE\u8BA1\u751F\u6210\u5931\u8D25",error:{code:C(g)==="INTERNAL_ERROR"?"DESIGN_GENERATION_FAILED":C(g),message:T(g),retryable:!0,details:M(g)},outputs:{...d.outputs,diagnostics:Je(A,ee,J)}});await nr(a,P,T(g)),y({type:"task.failed",task:P}),y({type:"error",error:ne(g)}),y({type:"design.done",success:!1,rounds:0,response:T(g)}),o.end()}finally{nt(a.id)}}s(ur,"handleDesign");function zo(e){return e.type!=="text"&&e.type!=="thinking"?!0:typeof e.content=="string"&&e.content.trim().length>0}s(zo,"isDisplayableAgentEvent");function Jo(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(Jo,"summarizeAgentEvent");function Ko(e){return`agent_${e}`}s(Ko,"agentLifecyclePhase");function Go(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(Go,"agentLifecycleMessage");function Vo(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(Vo,"sanitizeAgentLifecycle");function Je(e,t,r,o){return{elapsedMs:Date.now()-e,timeline:t.slice(-40),recentAgentEvents:r,validation:o}}s(Je,"buildDesignDiagnostics");function Yo(e,t,r){let o=r.filter(a=>Qo(a.path)).map(a=>({path:a.path,kind:pr(a.path),checksum:me(a.content),required:Zo(a.path)})),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(Yo,"buildDesignManifest");function Qo(e){return e==="workflow.yml"||e==="views.yml"||e.startsWith("recipes/")||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(e)||/^workflows\/[^/]+\/views\.ya?ml$/.test(e)||/^workflows\/[^/]+\/recipes\/.+\.(ts|js)$/.test(e)}s(Qo,"isDesignArtifactPath");function pr(e){return e.endsWith("workflow.yml")||e.endsWith("workflow.yaml")?"workflow":e.endsWith("views.yml")||e.endsWith("views.yaml")?"views":"recipe"}s(pr,"designArtifactKind");function Zo(e){return pr(e)!=="views"}s(Zo,"isRequiredDesignArtifact");async function nr(e,t,r){let o=new Date().toISOString();await Be(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(nr,"writeInvalidDesignManifest");import an from"path";import{loadSettings as cn,resolveConfigPath as un,loadWorkflowTemplate as pn,initTable as dn,ensureTableExists as ln,syncViewsFromDesign as fn,runWithExecutor as mn,runWithDwsRunner as gn,DwsError as wn,logger as yn}from"aitable-workflow-core";var Xo={singleSelect:"single_select",multipleSelect:"multiple_select",date:"datetime"},en={Grid:"grid",FormDesigner:"form",Kanban:"kanban",Calendar:"calendar",Gantt:"gantt"};function dr(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 f=o.get(c);r.set(c,{id:nn(c),name:c,type:on(f?.type??p),...f?.options??l?{options:f?.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",rn(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=tn(e.tracker.views??[],t).map(c=>({id:c.id,name:c.name,kind:en[c.type]??"grid",desc:c.description??sn(c)})),a=[...r.values()];return{fieldCount:a.length,viewCount:i.length,fields:a,views:i}}s(dr,"buildSetupSchemaSummary");function tn(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(tn,"expandViews");function rn(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(rn,"stateOptions");function on(e){return Xo[e]??e}s(on,"displayFieldType");function nn(e){return`fld_${e.replace(/[^\p{L}\p{N}]+/gu,"_").replace(/^_+|_+$/g,"")||"field"}`}s(nn,"fieldId");function sn(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(sn,"viewDescription");async function Ke(e,t,r,o,n){let i=await R(t,e);try{n.ensureAvailable()}catch(d){q(o,se(d),C(d),T(d));return}let a=await r.getState(i),c=N(a),u=c?.stage==="setup"?c:null;if(u?.status==="running"){z(o),G(o,"task.snapshot",{type:"task.snapshot",task:u}),o.end();return}let p=u?.status==="blocked"?await r.updateTask(i,u.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");z(o);let l=s(d=>G(o,d.type,d),"send"),f=s(async(d,v)=>{let y=await r.updateTask(i,p.id,{currentAction:d,checkpoint:v});l({type:"task.progress",taskId:y.id,message:d,checkpoint:v}),l({type:"setup.progress",message:d})},"progress"),h=n.buildSetupExecutor({projectId:i.id,projectDir:i.dir}),k=n.buildDwsRunner();try{await mn(h,async()=>{await gn(k,async()=>{l({type:"task.started",task:p}),l({type:"setup.started",projectId:e}),await f("\u52A0\u8F7D\u914D\u7F6E\u4E0E\u5DE5\u4F5C\u6D41\u6A21\u677F","preflight"),await fn({viewsPath:an.resolve(i.dir,"views.yml"),configPath:B(i),autoUpdate:!0}).catch(b=>(yn.warn("setup","setup \u524D\u540C\u6B65 views.yml \u5931\u8D25\uFF0C\u7EE7\u7EED\u4F7F\u7528 config \u4E2D\u7684\u89C6\u56FE\u914D\u7F6E",{error:T(b)}),null));let d=await cn(B(i),{lenientEnv:!0}),v=await pn(d.workflowTemplatePath,{envSource:d.envSource}),y=d.tracker.base_id==="__placeholder__"?void 0:d.tracker,A=y??v.tracker,Z=!!A&&!A.table_id.trim();if(A&&!A.table_id.trim()){let b=y?await un(B(i)):d.workflowTemplatePath,ye=y?d:{...d,tracker:A},pe=await ln({trackerFilePath:b,settings:ye,workflow:v,onProgress:s((de,Y)=>f(de,Y),"onProgress")});d={...d,tracker:pe.tracker}}await f("\u5F00\u59CB\u521B\u5EFA\u5B57\u6BB5\u548C\u89C6\u56FE","sync_schema");let X=await dn({settings:d,workflow:v,cleanEmptyRows:!0,tableJustCreated:Z});for(let b of X.warnings)await f(`\u6CE8\u610F\uFF1A${b.message}`,"sync_schema");let ee=dr(d,v),J=X.warnings.map(b=>b.message);await x(i);let $=await r.updateTask(i,p.id,{status:"succeeded",currentAction:"AI \u8868\u683C\u642D\u5EFA\u5B8C\u6210",checkpoint:"done",outputs:{tableUrl:$e(d.tracker.base_id,d.tracker.table_id),baseId:d.tracker.base_id,tableId:d.tracker.table_id,schema:ee,warnings:J}});l({type:"task.succeeded",task:$}),l({type:"setup.done",tableUrl:$e(d.tracker.base_id,d.tracker.table_id),baseId:d.tracker.base_id,tableId:d.tracker.table_id,schema:ee,warnings:J}),o.end()})})}catch(d){if(hn(d)){let y=T(d),A=await r.updateTask(i,p.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${y}`,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"}});l({type:"task.blocked",task:A}),o.end();return}let v=await r.updateTask(i,p.id,{status:"failed",currentAction:"AI \u8868\u683C\u642D\u5EFA\u5931\u8D25",error:{code:C(d),message:T(d),retryable:!0,details:M(d)}});l({type:"task.failed",task:v}),l({type:"error",error:ne(d)}),o.end()}}s(Ke,"handleSetup");function hn(e){let t=T(e).toLowerCase(),r=e instanceof wn?e.stderr.toLowerCase():"",o=`${t} ${r}`;return["auth","login","permission","unauthorized","forbidden","access denied"].some(n=>o.includes(n))}s(hn,"isSetupAuthBlocker");function lr(e){e.post("/:projectId/tasks/:stage/:taskAction",L(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project,i=t.req.param("stage")??"",a=t.req.param("taskAction")??"",c=a==="start"||a==="continue"||a==="retry";if(c&&i==="setup"){await O(n,r),await Ke(n.id,r.workspace,r.projectStore.instances,o,K(t));return}if(c&&i==="run"){await O(n,r),await ce(r).start(n.id,o);return}q(o,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")})),e.post("/:projectId/design/discovery",L(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await O(n,r),await ir(n.id,r.workspace,r.projectStore.instances,o,K(t))})),e.post("/:projectId/design/discovery/confirm",L(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await O(i,r);let a=await I(o);await cr(i.id,r.workspace,r.projectStore.instances,a,n)})),e.post("/:projectId/design",L(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await O(i,r);let a=new URL(t.req.url),c=st(a,o);await ur(i.id,r.workspace,r.projectStore.instances,n,K(t),c),await fe(r,i,"design")})),e.post("/:projectId/setup",L(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await O(n,r),await Ke(n.id,r.workspace,r.projectStore.instances,o,K(t)),await fe(r,n,"setup")})),e.post("/:projectId/run/records/:recordId/human-action",L(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await O(i,r),await Dt(i.id,r.workspace,r.projectStore.instances,r.runtime,t.req.param("recordId")??"",o,n)})),e.post("/:projectId/run",L(async t=>{let{services:r,outgoing:o}=t.env,n=t.env.project;await O(n,r),await ce(r).start(n.id,o)})),e.post("/:projectId/run/stop",async t=>{let r=t.env.project;return w(t,await ce(t.env.services).stop(r.id))}),e.get("/:projectId/run/status",async t=>{let r=t.env.project;return w(t,await ce(t.env.services).status(r.id))}),e.get("/:projectId/run/records",async t=>{let r=t.env.project,o=Number(t.req.query("limit")),n=Number.isInteger(o)&&o>0?o:void 0;return w(t,await ce(t.env.services).listRecords(r.id,{limit:n}))})}s(lr,"registerStageRoutes");async function jn(e,t,r,o){let n=r&&/^[A-Za-z0-9_-]+$/.test(r)?r:null;if(n&&t){let c=await t.resolve(e.id,n,o);return V.join(e.dir,c.templatePath)}let i=await D(e);if(n){let c=`workflows/${n}/workflow.yml`;if(i.some(u=>u.path===c))return V.join(e.dir,c)}if(i.some(c=>c.path==="workflow.yml"))return V.join(e.dir,"workflow.yml");let a=i.find(c=>/^workflows\/[^/]+\/workflow\.ya?ml$/.test(c.path));return V.join(e.dir,a?.path??"workflow.yml")}s(jn,"resolvePreviewWorkflowPath");function mr(){let e=new kn;return e.get("/",async t=>w(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 I(n),a=await r.projectStore.projects.create(o,{title:i.title,files:i.files});await O(a,r);let c={project:a};return a.files&&(c.files=a.files),a.warnings&&a.warnings.length>0&&(c.warnings=a.warnings),w(t,c)}),e.use("/:projectId",We),e.use("/:projectId/*",We),e.delete("/:projectId",async t=>{let{services:r,scope:o}=t.env,n=t.env.project;return r.runtime.runSessions.has(n.id)?F(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 he(n),await it(r,n.id),w(t,{ok:!0,id:n.id}))}),e.patch("/:projectId",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=await I(n);return w(t,{project:await r.projectStore.projects.updateMeta(t.env.project,{title:i.title},o)})}),e.post("/:projectId/init",L(async t=>{let{services:r,incoming:o,outgoing:n}=t.env,i=t.env.project;await O(i,r);let a=K(t);await Tt(i.id,r.workspace,r.projectStore.instances,o,n,(c,u)=>a.bindProjectMachine(c,u)),await fe(r,i,"init")})),e.get("/:projectId/engine",async t=>{let r=t.env.project,o=K(t),n=await o.getProjectMachine(r.id);if(!n)return w(t,{machineId:null,machine:null,status:"unbound"});let i=o.isMachineOnline(n),c=(o.listMachines()??[]).find(u=>u.machineId===n);return w(t,{machineId:n,machine:c??null,status:i?"online":"offline"})}),e.put("/:projectId/engine",async t=>{let{incoming:r}=t.env,o=await I(r);return o.machineId?(await K(t).bindProjectMachine(t.env.project.id,o.machineId),w(t,{ok:!0,machineId:o.machineId})):F(t,422,"INVALID_INPUT","machineId \u4E0D\u80FD\u4E3A\u7A7A")}),e.get("/:projectId/files",async t=>{let r=t.env.project;return w(t,{project:r,files:await D(r)})}),e.put("/:projectId/files",async t=>{let{services:r,scope:o,incoming:n}=t.env,i=t.env.project,a=await I(n);if(!Array.isArray(a.files))return F(t,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");let c=await r.projectStore.projects.replaceFiles(i,a.files,o),u=await O(i,r);return w(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 I(n),c=await r.projectStore.projects.updateFiles(i,{upsert:a.upsert,remove:a.remove},o),u=await O(i,r);return w(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=$t(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 w(t,{...a,workflows:u})}return w(t,a)}),e.post("/:projectId/validate",async t=>{let r=t.env.project,o=await vn({workDir:r.dir,configPath:V.join(r.dir,"aitable-workflow.config.yml"),workflows:[],workflowPath:V.join(r.dir,"workflow.yml"),recipeDir:V.join(r.dir,"recipes")});return await Ot(r,o),w(t,o)}),e.get("/:projectId/workflow",async t=>{let r=t.env.project,o=await Pn(r.dir),n=await jn(r,t.env.services.projectStore.workflows,t.req.query("workflowId")??null,t.env.scope),i=await fr(n,{envSource:o}).catch(()=>fr(n)),a=V.join(V.dirname(n),"recipes"),c=i.steps.map(u=>({...u,requires_agent:u.recipe?bt(a,u.recipe):!!u.prompt}));return w(t,{workflow:{...i,steps:c}})}),e.post("/:projectId/reset-workflow",async t=>{let r=await mt(t.env.project);return w(t,{project:r,files:await D(r)})}),e.get("/:projectId/state",async t=>{let{services:r}=t.env,o=t.env.project,n=await r.projectStore.instances.getRecoverableState(o);return w(t,Jt(n,r.runtime.runSessions.get(o.id)))}),e.patch("/:projectId/table-id",L(async t=>{let{services:r,incoming:o,outgoing:n}=t.env;await St(t.env.project.id,r.workspace,r.projectStore.instances,o,n)})),Qt(e),lr(e),e}s(mr,"projectRoutes");function gr(){let e=new Tn;return e.onError((t,r)=>F(r,se(t),C(t),T(t),M(t))),e.notFound(t=>F(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(!(tt(o,n)||n==="GET"&&o==="/api/public-config")&&!await t.env.services.identityService.authenticate(t.env.incoming))return rt(t);await r()}),e.get("/api/health",t=>w(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 w(t,{authEnabled:t.env.services.identityService.authRequired,...r?{relayGatewayUrl:r}:{}})}),e.route("/api/projects",mr()),e.get("/api/agents",t=>w(t,Sn())),e}s(gr,"createHonoApp");import{createApp as qn,logger as Un}from"aitable-workflow-core";var Oe=class{static{s(this,"LocalProjectRepository")}workspace;constructor(t){this.workspace=t}async create(t,r){let o=await ft(this.workspace),n=[];if(r?.files&&r.files.length>0){let i=await je(o,r.files);n.push(...i.warnings);let a=await x(o);return r.title&&r.title.trim()&&(a=await ae(a,{title:r.title.trim()})),{...a,files:i.written,warnings:n}}if(r?.title&&r.title.trim()){let i=await ae(o,{title:r.title.trim()});return n.length?{...i,warnings:n}:{...i}}return n.length?{...o,warnings:n}:{...o}}async list(t){return Le(this.workspace)}async resolve(t,r){return R(this.workspace,t)}async updateMeta(t,r,o){return ae(t,r)}async delete(t,r){await he(t)}async updateFiles(t,r,o){return r.remove&&r.remove.length>0&&await Mt(t,r.remove),r.upsert&&r.upsert.length>0&&await je(t,r.upsert),await x(t),D(t)}async replaceFiles(t,r,o){return await Lt(t,r),await x(t),D(t)}async exportProject(t,r){return Bt(t)}async syncHotFields(){}};import{randomUUID as Dn}from"crypto";import{mkdir as wr,readFile as yr,rm as On,writeFile as hr}from"fs/promises";import te from"path";import{applyRunExecutionEvent as Rn}from"aitable-workflow-core";var Re=new Map,An=/^[a-zA-Z0-9_-]+$/,Ae=class{static{s(this,"LocalWorkflowInstanceStore")}workspace;constructor(t){this.workspace=t}getState(t){return re(t)}getRecoverableState(t){return Wn(t)}createTask(t,r){return xn(t,r)}updateTask(t,r,o){return En(t,r,o)}clearActiveTask(t,r){return Cn(t,r)}appendRunSnapshotEvent(t,r){return _n(t,r)}updateRunSnapshotRecord(t,r,o,n){return Fn(t,r,o,n)}deleteProjectState(t){return bn(this.workspace,t)}};async function bn(e,t){Ve(t);let r=In(e,t);await On(te.join(r,"runtime"),{recursive:!0,force:!0})}s(bn,"deleteProjectState");function In(e,t){return Ve(t),te.join(e.projectsRoot,t)}s(In,"projectDir");async function xn(e,t){return ue(e,async()=>{await Ie(e);let r=await re(e),o=(r.stages[t]?.task.attempt??0)+1,n=new Date().toISOString(),i={id:`task_${Dn().slice(0,8)}`,projectId:e.id,stage:t,status:"running",attempt:o,startedAt:n,updatedAt:n,currentAction:"\u4EFB\u52A1\u5DF2\u542F\u52A8"};return await be(e,i),await Q(e,Te(r,i)),i})}s(xn,"createTask");async function En(e,t,r){return ue(e,async()=>{let o=await Mn(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??(Se(r.status)?n:o.completedAt),block:Object.prototype.hasOwnProperty.call(r,"block")?r.block:Se(r.status)?void 0:o.block};await be(e,i);let a=await re(e);return await Q(e,Te(a,i)),i})}s(En,"updateTask");async function re(e){await Ie(e);let t=await yr(vr(e),"utf8").catch(()=>"");if(t.trim()){let r=Ln(t),o=U(e,r);return r.repaired&&await Q(e,o),o}return U(e,{projectId:e.id,activeStage:null,stages:{},updatedAt:e.updatedAt})}s(re,"getState");async function _n(e,t){return ue(e,async()=>{let r=await re(e),o=Rn(r.runSnapshot??{records:[],logs:[]},t),n=U(e,{...r,runSnapshot:o,updatedAt:new Date().toISOString()});return await Q(e,n),n})}s(_n,"appendRunSnapshotEvent");async function Fn(e,t,r,o){return ue(e,async()=>{let n=await re(e);if(!n.runSnapshot)return n;let i=Date.now(),a={records:$n(n.runSnapshot.records,t,u=>({...u,...r,updatedAt:i})),logs:o?Hn(n.runSnapshot.logs,t,r.currentStepId??"run","info",o):n.runSnapshot.logs},c=U(e,{...n,runSnapshot:a,updatedAt:new Date().toISOString()});return await Q(e,c),c})}s(Fn,"updateRunSnapshotRecord");async function Wn(e){return ue(e,async()=>{let t=await re(e),r=t.stages.design?.task,o=await gt(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 be(e,u);let p=U(e,{...t,activeStage:t.activeStage==="design"?null:t.activeStage,stages:{...t.stages,design:we(u)},updatedAt:c});return await Q(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=U(e,{...t,activeStage:t.activeStage==="design"?null:t.activeStage,stages:{...t.stages,design:we(i)},updatedAt:n});return await be(e,i),await Q(e,a),a})}s(Wn,"getRecoverableState");async function Cn(e,t){return ue(e,async()=>{let r=await re(e);if(N(r)?.id!==t)return r;let o=U(e,{...r,activeStage:null,updatedAt:new Date().toISOString()});return await Q(e,o),o})}s(Cn,"clearActiveTask");function Ge(e){return te.join(e.dir,"runtime")}s(Ge,"runtimeDir");function Nn(e){return te.join(Ge(e),"artifacts")}s(Nn,"artifactsDir");function kr(e){return te.join(Ge(e),"tasks")}s(kr,"tasksDir");function vr(e){return te.join(Ge(e),"state.json")}s(vr,"statePath");function Pr(e,t){return Ve(t),te.join(kr(e),`${t}.json`)}s(Pr,"taskPath");async function Ie(e){await wr(kr(e),{recursive:!0}),await wr(Nn(e),{recursive:!0})}s(Ie,"ensureRuntimeDirs");async function Mn(e,t){let r=await yr(Pr(e,t),"utf8");return JSON.parse(r)}s(Mn,"readTask");async function be(e,t){await Ie(e),await hr(Pr(e,t.id),`${JSON.stringify(t,null,2)}
18
+ `,"utf8")}s(be,"writeTask");async function Q(e,t){await Ie(e),await hr(vr(e),`${JSON.stringify(t,null,2)}
19
+ `,"utf8")}s(Q,"writeProjectState");async function ue(e,t){let r=e.dir||e.id,n=(Re.get(r)??Promise.resolve()).catch(()=>{}).then(t),i=n.then(()=>{},()=>{});Re.set(r,i);try{return await n}finally{Re.get(r)===i&&Re.delete(r)}}s(ue,"withProjectStateWrite");function Ln(e){try{return JSON.parse(e)}catch(t){let r=Bn(e);if(!r)throw t;return{...JSON.parse(r),repaired:!0}}}s(Ln,"parseProjectStateJson");function Bn(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(Bn,"extractFirstJsonObject");function $n(e,t,r){return e.map(o=>o.id===t?r(o):o)}s($n,"updateRunRecord");function Hn(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(Hn,"appendRunLog");function Ve(e){if(!An.test(e))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${e}`),{code:"INVALID_PROJECT_ID"})}s(Ve,"assertProjectId");var xe=class{static{s(this,"LocalProjectStore")}projects;instances;workflows;constructor(t){this.projects=new Oe(t),this.instances=new Ae(t)}async prepareWorkdir(t,r){return{project:await x(t),materialized:0,warnings:[]}}async commitWorkdir(t,r){}async cascadeDelete(t){}};var Ee=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 _e=class{static{s(this,"LocalIdentityService")}authRequired=!1;authenticate(t){return Xe(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 jr(e={}){let t=e.workspace??lt({dataRoot:e.dataRoot});return{workspace:t,runtime:Ut(e.appFactory??((r,o)=>qn(r,{onRunEvent:o}))),projectStore:e.projectStore??new xe(t),execution:e.execution??new Ee,identityService:e.identityService??new _e,extendApp:e.extendApp,webRoot:e.webRoot}}s(jr,"createServerServices");function Tr(e=process.env){let t=e.AITABLE_RELAY_BOOTSTRAP_KEY;return typeof t=="string"&&t.trim()!==""?(Un.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(Tr,"warnDeprecatedBootstrapKey");var zn="127.0.0.1",Xa=8787;function Fe(e){if(typeof e!="string")return;let t=e.trim();return t||void 0}s(Fe,"readEnvString");function Jn(e){let t=Fe(e);if(t===void 0)return;let r=Number.parseInt(t,10);return Number.isFinite(r)&&r>0?r:void 0}s(Jn,"readEnvPort");function Sr(e={},t=process.env){let r=e.host??Fe(t.AITABLE_WORKFLOW_HOST)??zn,o=e.port??Jn(t.AITABLE_WORKFLOW_PORT)??8787,n=e.dataRoot??Fe(t.AITABLE_WORKFLOW_DATA_DIR)??void 0,i=e.webRoot??Fe(t.AITABLE_WORKFLOW_WEB_ROOT)??void 0;return{host:r,port:o,dataRoot:n,webRoot:i}}s(Sr,"resolveServeConfig");import Ye from"path";import{readFile as Kn,access as Gn}from"fs/promises";import{resolveInsideRoot as Vn}from"aitable-workflow-core";var Yn={".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 Dr(e,t,r,o){let n=Ye.resolve(e),i=Ye.join(n,"index.html"),a=decodeURIComponent(t).replace(/^\/+/,""),c;try{c=a===""?i:Vn(n,a,{allowRoot:!1})}catch{c=i}try{await Gn(c)}catch{c=i}try{let u=await Kn(c),p=Ye.extname(c).toLowerCase(),l=Yn[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{q(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(Dr,"serveStaticWeb");async function mc(e={}){Tr();let t=Sr({port:e.port,host:e.host,dataRoot:e.dataRoot,webRoot:e.webRoot}),r=e.services??jr({dataRoot:t.dataRoot,appFactory:e.appFactory,webRoot:t.webRoot}),o=Qn.createServer((n,i)=>{Xn(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(mc,"startServer");var Or=new WeakMap;function Zn(e){let t=Or.get(e);return t||(t=gr(),e.extendApp?.(t),Or.set(e,t)),t}s(Zn,"appFor");async function Xn(e,t,r){if(Ze(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 Dr(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:es(t.headers)}),a=await Zn(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(Xn,"handleRequest");function es(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(es,"toFetchHeaders");import Rr from"path";function hc(e){let t=Rr.normalize(e).split(Rr.sep).join("/");return t==="workflow.yml"?"workflow":t==="views.yml"?"views":t.startsWith("recipes/")?"recipe":"other"}s(hc,"workflowFileKind");var Ar=class{static{s(this,"LocalProjectMutexStore")}queues=new Map;withProjectLock(t,r){let n=(this.queues.get(t)??Promise.resolve()).then(r,r);return this.queues.set(t,n),n.then(()=>{this.queues.get(t)===n&&this.queues.delete(t)},()=>{this.queues.get(t)===n&&this.queues.delete(t)}).catch(()=>{}),n}};export{zn as DEFAULT_SERVE_HOST,Xa as DEFAULT_SERVE_PORT,ze as LeaseRunController,Ee as LocalExecutionBackend,_e as LocalIdentityService,Ar as LocalProjectMutexStore,Oe as LocalProjectRepository,xe as LocalProjectStore,Ue as LocalRunController,Ae as LocalWorkflowInstanceStore,N as activeTaskOf,ne as apiError,Ft as assertSafeProjectPath,_t as assertSafeRelativePath,qs as assertSafeWorkflowPath,mo as assertWritableKind,K as backendOf,$e as buildAITableUrl,it as cascadeDeleteProject,me as checksumContent,fe as commitStageOnTerminal,B as configPath,gr as createHonoApp,ft as createProject,Ut as createServerRuntime,jr as createServerServices,lt as createWorkspace,he as deleteProject,F as errorBody,C as errorCode,M as errorDetails,T as errorMessage,se as errorStatus,Xn as handleRequest,zt as handleRunRuntime,Wt as isForbiddenWritable,Mr as isStageActiveFor,Se as isTerminalStatus,w as jsonBody,Ct as kindOf,D as listProjectFiles,Le as listProjects,Te as mergeTaskIntoState,U as normalizeProjectState,Jt as overlayRunSessionState,O as prepareWorkdirGuarded,L as raw,Ur as readDesignManifest,I as readJson,Mt as removeProjectFiles,Lt as replaceProjectFiles,mt as resetProjectWorkflow,R as resolveProject,We as resolveProjectMw,ce as resolveRunController,Sr as resolveServeConfig,q as sendError,_ as sendJson,rs as sendUnauthorized,we as stageStateOf,mc as startServer,x as touchProject,rt as unauthorized,ae as updateProjectMeta,go as validateConfigScene,gt as validateDesignArtifacts,Tr as warnDeprecatedBootstrapKey,hc as workflowFileKind,Be as writeDesignManifest,je as writeProjectFiles};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aitable-workflow-server",
3
- "version": "0.1.16",
3
+ "version": "0.1.17-beta.1786415522134",
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.16",
25
+ "aitable-workflow-core": "0.1.17-beta.1786415522134",
26
26
  "@hono/node-server": "^2.0.12",
27
27
  "hono": "^4.12.32",
28
28
  "yaml": "^2.8.1"