aitable-workflow-server 0.1.28 → 0.1.29-beta.1790670244714

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, { IncomingMessage, ServerResponse } from 'node:http';
2
- import { ProjectDTO, ProjectFileDTO, DesignArtifactManifestDTO, DesignArtifactValidationDTO, ProjectExportDTO, ProjectStateDTO, StageIdDTO, StageTaskIdentityDTO, StageStateDTO, RunExecutionEventDTO, RunSnapshotDTO, AgentType, AgentExecutor, DwsRunner, RunScheduleDTO, RunRecordsPageDTO, DetectedCodingAgent, RunEventSink, App, RunEventDTO, CreateWorkflowResponseDTO, ProjectWorkflowDTO, ApiError, RunControlResultDTO } from 'aitable-workflow-core';
2
+ import { ProjectDTO, ProjectFileDTO, DesignArtifactManifestDTO, DesignArtifactValidationDTO, ProjectExportDTO, ProjectStateDTO, StageIdDTO, StageTaskIdentityDTO, StageStateDTO, RunExecutionEventDTO, RunEventsPageDTO, RunSnapshotDTO, AgentType, AgentExecutor, RecipeRunner, DwsRunner, RunScheduleDTO, RunRecordsPageDTO, DetectedCodingAgent, RunEventSink, App, RunEventDTO, RunEngineTag, CreateWorkflowResponseDTO, ProjectWorkflowDTO, ApiError, RunControlResultDTO, RunState } from 'aitable-workflow-core';
3
3
  import * as core from '@midwayjs/core';
4
4
 
5
5
  type WorkspaceOptions = {
@@ -35,7 +35,7 @@ declare function removeLegacyViewsFiles(root: string, dir?: string): Promise<voi
35
35
  type ActorContext = {
36
36
  actorId?: string;
37
37
  /**
38
- * WP-10-002:项目 owner 隔离用。relay 模式由 owner-token 派生,local 模式可空。
38
+ * WP-10-002:项目 owner 隔离用。relay 模式由 machine token 对应的机器归属派生,local 模式可空。
39
39
  * 004 接入鉴权后由路由层注入;本字段仅由 repository 存取(owner_user_id 列)。
40
40
  */
41
41
  ownerUserId?: string;
@@ -104,7 +104,7 @@ declare class LocalProjectRepository implements ProjectRepository {
104
104
  */
105
105
  type RequestIdentity = {
106
106
  /** 命中的凭据类型,仅用于日志与排查。 */
107
- credential: "none" | "api-token" | "artifact" | "machine" | "owner" | "dingtalk";
107
+ credential: "none" | "api-token" | "artifact" | "machine" | "dingtalk";
108
108
  /** 是否放行。false 时中间件按 loginUrl 有无决定 302 还是 401。 */
109
109
  authenticated: boolean;
110
110
  /**
@@ -115,7 +115,7 @@ type RequestIdentity = {
115
115
  openId: string;
116
116
  orgId?: string;
117
117
  };
118
- /** daemon 身份(machine-key 命中)。ownerUserId 为 null 表示该机器未绑定用户。 */
118
+ /** daemon 身份(machine token 命中)。ownerUserId 为 null 表示该机器未绑定用户。 */
119
119
  machine?: {
120
120
  machineId: string;
121
121
  ownerUserId: string | null;
@@ -247,6 +247,13 @@ interface WorkflowInstanceStore {
247
247
  /** 整块写入某阶段的状态。state 必须已由 transition() 算出。 */
248
248
  putStageState(project: ProjectDTO, stage: StageIdDTO, stageState: StageStateDTO): Promise<ProjectStateDTO>;
249
249
  appendRunSnapshotEvent(project: ProjectDTO, event: RunExecutionEventDTO): Promise<ProjectStateDTO>;
250
+ /** Run event API read source: local state file or Gateway's PG event ledger. */
251
+ listRunEvents?(project: ProjectDTO, opts?: {
252
+ afterSeq?: number;
253
+ limit?: number;
254
+ }): Promise<RunEventsPageDTO>;
255
+ /** Clear only this project's previous run event ledger/projection before a new in-process run. */
256
+ resetRunEvents?(projectId: string): Promise<void>;
250
257
  updateRunSnapshotRecord(project: ProjectDTO, itemId: string, patch: Partial<Pick<RunSnapshotDTO["records"][number], "state" | "status" | "currentStepId">>, logText?: string): Promise<ProjectStateDTO>;
251
258
  /**
252
259
  * WP-10-002:删除项目的运行时状态(state.json)。
@@ -263,6 +270,11 @@ declare class LocalWorkflowInstanceStore implements WorkflowInstanceStore {
263
270
  createStageIdentity(project: ProjectDTO, stage: StageIdDTO): Promise<StageTaskIdentityDTO>;
264
271
  putStageState(project: ProjectDTO, stage: StageIdDTO, stageState: StageStateDTO): Promise<ProjectStateDTO>;
265
272
  appendRunSnapshotEvent(project: ProjectDTO, event: RunExecutionEventDTO): Promise<ProjectStateDTO>;
273
+ listRunEvents(project: ProjectDTO, opts?: {
274
+ afterSeq?: number;
275
+ limit?: number;
276
+ }): Promise<RunEventsPageDTO>;
277
+ resetRunEvents(_projectId: string): Promise<void>;
266
278
  updateRunSnapshotRecord(project: ProjectDTO, itemId: string, patch: Partial<Pick<RunSnapshotDTO["records"][number], "state" | "status" | "currentStepId">>, logText?: string): Promise<ProjectStateDTO>;
267
279
  deleteProjectState(projectId: string): Promise<void>;
268
280
  }
@@ -271,9 +283,11 @@ declare class LocalWorkflowInstanceStore implements WorkflowInstanceStore {
271
283
  * run 阶段运行模式(P0/P1 分化)。
272
284
  * - `"local"`:服务端进程内跑引擎 + SSE(缺省,无 DB / 未配调度器)。
273
285
  * - `"server-run-relay-agent"`:服务端进程内跑引擎 + SSE,但 `coding.run()` 经 relay 投递到本地 daemon(P0)。
286
+ * - `"server-run-relay-recipe"`:同 P0 的进程内引擎,但 **recipe 步骤本身**经 `run:recipe`
287
+ * 单步下发到 daemon 执行(方案三,SPEC §2/Phase 4)。
274
288
  * - `"workflow-pull-claim"`:不启引擎,翻转 DB 期望态等 daemon 认领整条 workflow(P1)。
275
289
  */
276
- type RunMode = "local" | "server-run-relay-agent" | "workflow-pull-claim";
290
+ type RunMode = "local" | "server-run-relay-agent" | "server-run-relay-recipe" | "workflow-pull-claim";
277
291
  /** 在线机器快照(供路由 / 账号中心展示;relay gateway 侧生产,接口层只读)。 */
278
292
  interface RelayMachineInfo {
279
293
  machineId: string;
@@ -315,6 +329,12 @@ interface RunRecordsReader {
315
329
  limit?: number;
316
330
  }): Promise<RunRecordsPageDTO>;
317
331
  }
332
+ interface RunEventsReader {
333
+ listEvents(projectId: string, opts?: {
334
+ afterSeq?: number;
335
+ limit?: number;
336
+ }): Promise<RunEventsPageDTO>;
337
+ }
318
338
  interface ExecutionBackend {
319
339
  readonly kind: "local" | "relay";
320
340
  /**
@@ -353,14 +373,32 @@ interface ExecutionBackend {
353
373
  projectDir: string;
354
374
  agent?: AgentType;
355
375
  }): Promise<AgentExecutor | undefined>;
356
- /** setup 阶段 dws runner;local 返回 undefined → dws 本机 spawn。 */
357
- buildDwsRunner(): DwsRunner | undefined;
376
+ /**
377
+ * run 阶段 recipe 单步下发 transport(方案三 server-run-relay-recipe)。
378
+ * 仅在生效模式为 `server-run-relay-recipe` 时被 run-runtime 调用;
379
+ * local / 未启用返回 undefined → core 默认使用本地 runner。
380
+ */
381
+ buildRunRecipeRunner?(ctx: {
382
+ projectId: string;
383
+ projectDir: string;
384
+ }): Promise<RecipeRunner | undefined>;
385
+ /**
386
+ * setup 阶段 dws runner;local 返回 undefined → dws 本机 spawn。
387
+ * relay 绑定优先(路由契约 §3.2-G3):project 绑定机在线且有 dws 用它,否则回退能力匹配。
388
+ */
389
+ buildDwsRunner(ctx: {
390
+ projectId: string;
391
+ }): Promise<DwsRunner | undefined>;
358
392
  /** 在线机器列表;local 合成单元素「本机运行时」(管理面 engine 选择器用)。 */
359
393
  listMachines(): RelayMachineInfo[] | undefined;
360
394
  /** 指定机器是否在线;local 仅本机这一台恒 true。 */
361
395
  isMachineOnline(machineId: string): boolean;
362
396
  /** 项目当前绑定的执行机器;local 恒返回 LOCAL_MACHINE_ID(engine 面视为 bound)。 */
363
397
  getProjectMachine(projectId: string): Promise<string | null>;
398
+ /** Resolve a presented machine token to the internal ID, enforcing owner scope when supplied. */
399
+ resolveMachineToken(machineToken: string, ownerUserId: string): Promise<string | null>;
400
+ /** Return the current token for an internal machine ID; never expose the ID to Web callers. */
401
+ getMachineToken(machineId: string): Promise<string | null>;
364
402
  /** 绑定项目到执行机器;local 幂等接受(只有本机可选,无需真实绑定)。 */
365
403
  bindProjectMachine(projectId: string, machineId: string): Promise<void>;
366
404
  /** 解绑项目的执行机器(项目删除级联);local no-op。 */
@@ -375,6 +413,8 @@ interface ExecutionBackend {
375
413
  * gateway)→ `GET /run/records` 由 LocalRunController 读 runSnapshot。
376
414
  */
377
415
  readonly runRecords?: RunRecordsReader;
416
+ /** Gateway run event ledger; local mode reads the project state file instead. */
417
+ readonly runEvents?: RunEventsReader;
378
418
  }
379
419
  /** local 模式合成出的「本机运行时」标识:无 relay,引擎即本进程所在机器。 */
380
420
  declare const LOCAL_MACHINE_ID = "local";
@@ -392,7 +432,9 @@ declare class LocalExecutionBackend implements ExecutionBackend {
392
432
  buildDesignExecutor(): Promise<AgentExecutor | undefined>;
393
433
  buildSetupExecutor(): AgentExecutor | undefined;
394
434
  buildRunExecutor(): Promise<AgentExecutor | undefined>;
395
- buildDwsRunner(): DwsRunner | undefined;
435
+ buildDwsRunner(_ctx?: {
436
+ projectId: string;
437
+ }): Promise<DwsRunner | undefined>;
396
438
  /**
397
439
  * local 无 relay,但管理面仍要能展示「本机运行时」而非空列表(plan:engine unbound→bound)。
398
440
  * 探测带 TTL 缓存;spawn 失败降级为空 runtimes,不让 GET 整条挂掉。
@@ -402,6 +444,8 @@ declare class LocalExecutionBackend implements ExecutionBackend {
402
444
  isMachineOnline(machineId: string): boolean;
403
445
  /** local 无「绑定」概念,直接把每个 project 的引擎视为跑在本机。 */
404
446
  getProjectMachine(): Promise<string | null>;
447
+ resolveMachineToken(): Promise<string | null>;
448
+ getMachineToken(): Promise<string | null>;
405
449
  /** local 恒等于本机,绑定动作是幂等接受(前端选择器只会给出 LOCAL_MACHINE_ID)。 */
406
450
  bindProjectMachine(): Promise<void>;
407
451
  unbindProjectMachine(): Promise<void>;
@@ -412,6 +456,7 @@ type RunExecutionEvent = Parameters<RunEventSink>[0];
412
456
  type RunAppFactory = (configPath: string, onRunEvent?: (event: RunExecutionEvent) => void) => Promise<App>;
413
457
  type RunSession = {
414
458
  taskId: string;
459
+ eventSequence: number;
415
460
  subscribers: Set<ServerResponse>;
416
461
  events: RunEventDTO[];
417
462
  app: App | null;
@@ -423,7 +468,7 @@ type ServerRuntime = {
423
468
  };
424
469
  type RunSseWriter = (res: ServerResponse, event: string, data: unknown) => void;
425
470
  declare function createServerRuntime(appFactory: RunAppFactory): ServerRuntime;
426
- declare function handleRunRuntime(projectId: string, workspace: Workspace, projectStateStore: WorkflowInstanceStore, runtime: ServerRuntime, res: ServerResponse, writeSse: RunSseWriter, execution?: ExecutionBackend): Promise<void>;
471
+ declare function handleRunRuntime(projectId: string, workspace: Workspace, projectStateStore: WorkflowInstanceStore, runtime: ServerRuntime, res: ServerResponse, writeSse: RunSseWriter, execution?: ExecutionBackend, runMode?: RunMode): Promise<void>;
427
472
  /** 重放缓冲总上限(沿用原实现的 100)。 */
428
473
  declare const RUN_REPLAY_EVENT_CAP = 100;
429
474
  /** 重放缓冲里逐轮工具流的单独上限:超了先从最旧一条 agent_event 丢弃。 */
@@ -437,6 +482,12 @@ declare const RUN_REPLAY_AGENT_CAP = 60;
437
482
  * 2. 再守总量上限,保持原有「最多重放 100 条」的语义不变。
438
483
  */
439
484
  declare function trimRunReplayEvents(events: RunEventDTO[]): void;
485
+ /**
486
+ * 遗留③出口统一打戳:给工单/步骤/逐轮事件补产生时刻(`at`)与执行引擎标签(`engine`)。
487
+ * `stage.changed` / `error` 不打:前者是阶段状态机事实(自带落盘语义),后者是协议帧。
488
+ * 导出的纯函数:SSE 直播、重放缓冲与 runSnapshot 落盘共享同一份戳,刷新续流不假时间。
489
+ */
490
+ declare function stampRunEvent(event: RunEventDTO, engine: RunEngineTag): RunEventDTO;
440
491
 
441
492
  /** 带内容创建工作流的初始载荷。 */
442
493
  type CreateWorkflowInit = {
@@ -549,7 +600,7 @@ type ServerServices = {
549
600
  projectStore: ProjectStore;
550
601
  /** ② 执行域:design/setup 的 agent/dws 执行 + 项目↔机器绑定(local spawn / relay 投递)。 */
551
602
  execution: ExecutionBackend;
552
- /** ③ 身份域:请求鉴权 + actor 归属解析(local API token / gateway JWT+owner-token)。 */
603
+ /** ③ 身份域:请求鉴权 + actor 归属解析(local API token / gateway JWT+machine token)。 */
553
604
  identityService: IdentityService;
554
605
  /** 本地 web 静态资源目录;配置时 StaticWebMiddleware 托管前端页面。 */
555
606
  webRoot?: string;
@@ -577,7 +628,7 @@ declare function createServerServices(options?: ServerServicesOptions): ServerSe
577
628
  /**
578
629
  * 启动期一次性废弃告警:§3 已彻底移除 bootstrap 认证及其配置项。若部署环境仍配置了
579
630
  * `AITABLE_RELAY_BOOTSTRAP_KEY`,打印 warn 提示"已废弃、被忽略",**不参与任何认证/装配逻辑**
580
- * (认证只保留 owner-token `sk_owner_*` 与 per-machine key `sk_machine_*`)。
631
+ * (daemon 认证由账号中心预先创建的 per-machine token 负责)。
581
632
  *
582
633
  * @param env 环境变量来源,缺省 `process.env`(测试可注入)。
583
634
  * @returns 是否发出了告警(便于单测断言)。
@@ -600,7 +651,13 @@ declare class SystemController {
600
651
  checkNode(): Promise<void>;
601
652
  /**
602
653
  * 公开只读端点:下发运行时前端配置——是否启用登录(authEnabled,前端据此决定
603
- * 是否展示登录页)+ 可选 relay 网关地址(RELAY_PUBLIC_GATEWAY_URL 注入)。
654
+ * 是否展示登录页)+ 可选 relay 网关地址(RELAY_PUBLIC_GATEWAY_URL 注入)
655
+ * + 请求级运行方式可选项(runOverrideModes)。
656
+ *
657
+ * runOverrideModes 仅 relay 形态非空:覆盖值都依赖 relay 执行基建
658
+ * (pull-claim 要 RunScheduler/lease,server-run 要 daemon 投递);local 形态
659
+ * 硬选 pull-claim 只会被 RUN_SCHEDULER_REQUIRED 拒掉(500),server-run 则
660
+ * 退化为与本进程执行无差别。前端据此不渲染覆盖下拉,避免诱导选择必败/无效项。
604
661
  */
605
662
  publicConfig(): Promise<void>;
606
663
  /**
@@ -689,6 +746,7 @@ declare class StagesController {
689
746
  */
690
747
  designEvents(): Promise<void>;
691
748
  setup(): Promise<void>;
749
+ setupVerify(): Promise<void>;
692
750
  runHumanAction(): Promise<void>;
693
751
  /**
694
752
  * 启动 run。可选请求体 `{runMode}`(Phase 1.0 快速切片,per-project 配置落地前的验证入口):
@@ -700,6 +758,8 @@ declare class StagesController {
700
758
  runStatus(): Promise<void>;
701
759
  /** 工单列表:两模式同构读模型(local=runSnapshot / lease=PG work_items 投影)。 */
702
760
  runRecords(): Promise<void>;
761
+ /** 事件时间线:从统一 RunController 读取,local/Gateway 的存储源由后端选择。 */
762
+ runEvents(): Promise<void>;
703
763
  }
704
764
 
705
765
  declare class CorsMiddleware {
@@ -1022,11 +1082,18 @@ interface RunController {
1022
1082
  listRecords(projectId: string, opts?: {
1023
1083
  limit?: number;
1024
1084
  }): Promise<RunRecordsPageDTO>;
1085
+ /** 事件时间线(两模式同构;数据来源由服务端执行面选择)。 */
1086
+ listEvents(projectId: string, opts?: {
1087
+ afterSeq?: number;
1088
+ limit?: number;
1089
+ }): Promise<RunEventsPageDTO>;
1025
1090
  }
1026
1091
  declare class LocalRunController implements RunController {
1027
1092
  private readonly services;
1093
+ private readonly runMode?;
1028
1094
  readonly mode: "local";
1029
- constructor(services: ServerServices);
1095
+ /** runMode 缺省 = 不做 recipe 单步下发(P0/local 现状);显式选中方案三时透传给 run-runtime。 */
1096
+ constructor(services: ServerServices, runMode?: RunMode | undefined);
1030
1097
  start(projectId: string, outgoing: ServerResponse): Promise<void>;
1031
1098
  stop(projectId: string): Promise<RunControlResult>;
1032
1099
  status(projectId: string): Promise<RunControlResult>;
@@ -1037,18 +1104,27 @@ declare class LocalRunController implements RunController {
1037
1104
  listRecords(projectId: string, opts?: {
1038
1105
  limit?: number;
1039
1106
  }): Promise<RunRecordsPageDTO>;
1107
+ listEvents(projectId: string, opts?: {
1108
+ afterSeq?: number;
1109
+ limit?: number;
1110
+ }): Promise<RunEventsPageDTO>;
1040
1111
  }
1041
1112
  declare class RelayRunController implements RunController {
1042
1113
  private readonly scheduler;
1043
1114
  private readonly records?;
1115
+ private readonly events?;
1044
1116
  readonly mode: "relay";
1045
- constructor(scheduler: RunScheduler, records?: RunRecordsReader | undefined);
1117
+ constructor(scheduler: RunScheduler, records?: RunRecordsReader | undefined, events?: RunEventsReader | undefined);
1046
1118
  start(projectId: string, outgoing: ServerResponse): Promise<void>;
1047
1119
  stop(projectId: string): Promise<RunControlResult>;
1048
1120
  status(projectId: string): Promise<RunControlResult>;
1049
1121
  listRecords(projectId: string, opts?: {
1050
1122
  limit?: number;
1051
1123
  }): Promise<RunRecordsPageDTO>;
1124
+ listEvents(projectId: string, opts?: {
1125
+ afterSeq?: number;
1126
+ limit?: number;
1127
+ }): Promise<RunEventsPageDTO>;
1052
1128
  }
1053
1129
  /**
1054
1130
  * 请求级显式指定的执行模式(Phase 1.0 快速切片:per-project 配置落地前的临时入口,
@@ -1057,8 +1133,21 @@ declare class RelayRunController implements RunController {
1057
1133
  * 不是请求可选项。
1058
1134
  */
1059
1135
  type RequestedRunMode = Exclude<RunMode, "local">;
1136
+ /** 请求级可覆盖的 relay 模式(public-config 下发给前端决定是否渲染覆盖下拉)。 */
1137
+ declare const REQUESTED_RUN_MODES: readonly RequestedRunMode[];
1060
1138
  /** 校验请求体 `runMode`;缺省(无字段/空 body)返回 undefined 走部署默认。 */
1061
1139
  declare function parseRequestedRunMode(value: unknown): RequestedRunMode | undefined;
1140
+ /**
1141
+ * 纯函数:从落盘的 run 阶段 phase 里取「可恢复的进程内 relay 模式」。
1142
+ * 只认两个进程内 relay 模式;`local` / 缺省 / pull-claim 一律返回 undefined
1143
+ * (pull-claim 的真源是 lease 行,由 hasActiveLease 粘性处理,不在此恢复)。
1144
+ */
1145
+ declare function pickRecoverableRunMode(run: RunState | undefined): RequestedRunMode | undefined;
1146
+ /**
1147
+ * 从落盘的 run 阶段状态恢复「上一次进程内 run 用的执行粒度」,供 retry / 服务重启后
1148
+ * 的续跑使用——否则 retry 会回落部署缺省(gateway 上恒为 P0),把 recipe 下发跑成 agent 下发。
1149
+ */
1150
+ declare function recoverPersistedRunMode(services: ServerServices, projectId: string): Promise<RequestedRunMode | undefined>;
1062
1151
  /**
1063
1152
  * 按执行域 runMode 装配控制器(P0/P1 分化 + Phase 1.0 project/request 粒度覆盖)。
1064
1153
  *
@@ -1075,4 +1164,4 @@ declare function parseRequestedRunMode(value: unknown): RequestedRunMode | undef
1075
1164
  */
1076
1165
  declare function resolveRunController(services: ServerServices, projectId?: string, requestedMode?: RequestedRunMode): Promise<RunController>;
1077
1166
 
1078
- export { type ActorContext, type CreateProjectInit, type CreateProjectResult, type CreateWorkflowInit, type CreateWorkflowResult, DEFAULT_SERVE_HOST, DEFAULT_SERVE_PORT, type ExecutionBackend, type FilesPatch, type IdentityService, LOCAL_MACHINE_ID, LocalExecutionBackend, LocalIdentityService, LocalProjectMutexStore, LocalProjectRepository, LocalProjectStore, LocalRunController, LocalWorkflowInstanceStore, type MaterializeOptions, type MaterializeResult, type ProjectFileKind, type ProjectMutexStore, type ProjectRepository, type ProjectStore, RUN_REPLAY_AGENT_CAP, RUN_REPLAY_EVENT_CAP, type RelayMachineInfo, RelayRunController, type RequestIdentity, type RequestedRunMode, type RunAppFactory, type RunControlResult, type RunController, type RunMode, type RunRecordsPage, type RunRecordsReader, type RunScheduleStatus, type RunScheduler, type RunSession, type RunSseWriter, type ServeConfig, type ServeConfigOverrides, type ServerCtx, type ServerCtxState, 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, buildAITableUrl, buildLocalMachineInfo, cascadeDeleteProject, checksumContent, commitStageOnTerminal, configPath, createProject, createServerRuntime, createServerServices, createWorkspace, deleteProject, errorCode, errorDetails, errorMessage, errorStack, errorStatus, firstQueryValue, handleRunRuntime, identityOf, isForbiddenWritable, isLegacyViewsPath, isStageActiveFor, kindOf, listProjectFiles, listProjects, midway as midwayComponent, parseRequestedRunMode, prepareWorkdirGuarded, readBuffer, readDesignManifest, readJson, removeLegacyViewsFiles, removeProjectFiles, replaceProjectFiles, resetProjectWorkflow, resolveProject, resolveRunController, resolveServeConfig, scopeOf, sendError, sendJson, sendText, sendUnauthorized, silentLoggerFactory, startServer, touchProject, trimRunReplayEvents, updateProjectMeta, validateConfigScene, validateDesignArtifacts, warnDeprecatedBootstrapKey, withoutLeakedMidwayPortEnv, workflowFileKind, writeDesignManifest, writeProjectFiles };
1167
+ export { type ActorContext, type CreateProjectInit, type CreateProjectResult, type CreateWorkflowInit, type CreateWorkflowResult, DEFAULT_SERVE_HOST, DEFAULT_SERVE_PORT, type ExecutionBackend, type FilesPatch, type IdentityService, LOCAL_MACHINE_ID, LocalExecutionBackend, LocalIdentityService, LocalProjectMutexStore, LocalProjectRepository, LocalProjectStore, LocalRunController, LocalWorkflowInstanceStore, type MaterializeOptions, type MaterializeResult, type ProjectFileKind, type ProjectMutexStore, type ProjectRepository, type ProjectStore, REQUESTED_RUN_MODES, RUN_REPLAY_AGENT_CAP, RUN_REPLAY_EVENT_CAP, type RelayMachineInfo, RelayRunController, type RequestIdentity, type RequestedRunMode, type RunAppFactory, type RunControlResult, type RunController, type RunEventsReader, type RunMode, type RunRecordsPage, type RunRecordsReader, type RunScheduleStatus, type RunScheduler, type RunSession, type RunSseWriter, type ServeConfig, type ServeConfigOverrides, type ServerCtx, type ServerCtxState, 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, buildAITableUrl, buildLocalMachineInfo, cascadeDeleteProject, checksumContent, commitStageOnTerminal, configPath, createProject, createServerRuntime, createServerServices, createWorkspace, deleteProject, errorCode, errorDetails, errorMessage, errorStack, errorStatus, firstQueryValue, handleRunRuntime, identityOf, isForbiddenWritable, isLegacyViewsPath, isStageActiveFor, kindOf, listProjectFiles, listProjects, midway as midwayComponent, parseRequestedRunMode, pickRecoverableRunMode, prepareWorkdirGuarded, readBuffer, readDesignManifest, readJson, recoverPersistedRunMode, removeLegacyViewsFiles, removeProjectFiles, replaceProjectFiles, resetProjectWorkflow, resolveProject, resolveRunController, resolveServeConfig, scopeOf, sendError, sendJson, sendText, sendUnauthorized, silentLoggerFactory, stampRunEvent, startServer, touchProject, trimRunReplayEvents, updateProjectMeta, validateConfigScene, validateDesignArtifacts, warnDeprecatedBootstrapKey, withoutLeakedMidwayPortEnv, workflowFileKind, writeDesignManifest, writeProjectFiles };
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- var Je=Object.defineProperty;var wn=Object.getOwnPropertyDescriptor;var s=(t,e)=>Je(t,"name",{value:e,configurable:!0});var hn=(t,e)=>{for(var r in e)Je(t,r,{get:e[r],enumerable:!0})};var u=(t,e,r,n)=>{for(var o=n>1?void 0:n?wn(e,r):e,i=t.length-1,a;i>=0;i--)(a=t[i])&&(o=(n?a(e,r,o):a(o))||o);return n&&o&&Je(e,r,o),o};function he(t){let e=Array.isArray(t)?t[0]:t;return e!=null&&e!==""?e:null}s(he,"firstQueryValue");function O(t){return t.state.scope??{}}s(O,"scopeOf");function Vi(t){return t.state.identity}s(Vi,"identityOf");var We={};hn(We,{Configuration:()=>re,CorsMiddleware:()=>X,ErrorMappingMiddleware:()=>te,IdentityMiddleware:()=>V,ProjectsController:()=>v,ResolveProjectMiddleware:()=>G,ServerConfiguration:()=>re,StagesController:()=>R,StaticWebMiddleware:()=>K,SystemController:()=>M,WorkflowsController:()=>W});import{Configuration as Bn,App as Un}from"@midwayjs/core";import{Middleware as jn}from"@midwayjs/core";import yn from"crypto";function ht(t,e){Sn(t,e),e.setHeader("access-control-allow-methods","GET,POST,PUT,PATCH,DELETE,OPTIONS"),e.setHeader("access-control-allow-headers","content-type, authorization")}s(ht,"setCors");function Sn(t,e){let r=vn();if(!r){e.setHeader("access-control-allow-origin","*");return}let n=t.headers.origin,o=Array.isArray(n)?n[0]:n;o&&r.includes(o)&&(e.setHeader("access-control-allow-origin",o),e.setHeader("vary","Origin"))}s(Sn,"applyCorsOrigin");function vn(){let t=process.env.AITABLE_WORKFLOW_ALLOWED_ORIGINS;if(typeof t!="string")return;let e=t.split(",").map(r=>r.trim()).filter(Boolean);return e.length?e:void 0}s(vn,"readAllowedOrigins");function Pn(){let t=process.env.AITABLE_WORKFLOW_API_TOKEN,e=typeof t=="string"?t.trim():"";return e||void 0}s(Pn,"readServerApiToken");function yt(t){let e=Pn();if(!e)return!0;let r=t.headers.authorization,n=Array.isArray(r)?r[0]:r;if(!n)return!1;let i=/^Bearer\s+(.+)$/i.exec(n.trim())?.[1]?.trim();return i?xn(i,e):!1}s(yt,"isRequestAuthorized");function xn(t,e){let r=Buffer.from(t),n=Buffer.from(e);return r.length!==n.length?!1:yn.timingSafeEqual(r,n)}s(xn,"timingSafeEqualString");function St(t){return Array.isArray(t)?t[0]:t}s(St,"headerValue");function vt(t,e){let r=e.toUpperCase();return r==="OPTIONS"||r==="GET"&&t==="/api/health"||r==="GET"&&t==="/api/public-config"||r==="GET"&&t==="/check.node"}s(vt,"isAuthExempt");var X=class{resolve(){return async(e,r)=>{if(ht(e.req,e.res),e.method.toUpperCase()==="OPTIONS"){e.respond=!1,e.res.writeHead(204),e.res.end();return}await r()}}static getName(){return"aitableCors"}};s(X,"CorsMiddleware"),X=u([jn()],X);import{Middleware as Dn}from"@midwayjs/core";import{logger as Ge}from"aitable-workflow-core";async function k(t){let r=(await He(t)).toString("utf8").trim();return r?JSON.parse(r):{}}s(k,"readJson");async function He(t,e){let r=[],n=0,o=!1;for await(let i of t){if(o)continue;let a=Buffer.isBuffer(i)?i:Buffer.from(i);if(n+=a.length,e!==void 0&&n>e){o=!0,r.length=0;continue}r.push(a)}if(o)throw Object.assign(new Error(`\u8BF7\u6C42\u4F53\u8D85\u8FC7\u4E0A\u9650 ${e} \u5B57\u8282\uFF0C\u5DF2\u62D2\u7EDD\uFF08\u5F53\u524D\u5DF2\u7D2F\u8BA1 ${n} \u5B57\u8282\uFF09`),{code:"PAYLOAD_TOO_LARGE",status:413});return Buffer.concat(r)}s(He,"readBuffer");function f(t,e,r=200){t.writeHead(r,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify(e)}
2
- `)}s(f,"sendJson");function Pt(t,e,r=200){t.writeHead(r,{"content-type":"text/plain; charset=UTF-8"}),t.end(e)}s(Pt,"sendText");function S(t,e,r,n,o){f(t,{error:{code:r,message:n,details:o}},e)}s(S,"sendError");function xt(t){t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify({error:"unauthorized"})}
3
- `)}s(xt,"sendUnauthorized");function pe(t){return{code:F(t),message:P(t),details:$(t)}}s(pe,"apiError");function ee(t){return typeof t=="object"&&t!==null&&"status"in t&&typeof t.status=="number"?t.status:500}s(ee,"errorStatus");function F(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}s(F,"errorCode");function P(t){return t instanceof Error?t.message:String(t)}s(P,"errorMessage");function $(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}s($,"errorDetails");function Ve(t){return t instanceof Error?t.stack:void 0}s(Ve,"errorStack");function Tn(t){if(ee(t)!==404||typeof t!="object"||t===null)return!1;let{code:e,name:r}=t;return e==="404"||e===404||r==="NotFoundError"}s(Tn,"isFrameworkRouteMiss");var te=class{resolve(){return async(e,r)=>{try{await r(),e.res.headersSent||(e.respond=!1,S(e.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728"))}catch(n){if(e.res.headersSent){Ge.error("http",`${e.method} ${e.path} \u54CD\u5E94\u5DF2\u53D1\u51FA\u540E\u629B\u9519\uFF0C\u8FDE\u63A5\u4E2D\u65AD`,{method:e.method,path:e.path,code:F(n),reason:P(n),stack:Ve(n)}),e.res.writableEnded||e.res.end();return}if(e.respond=!1,Tn(n)){S(e.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728");return}let o=ee(n),i=F(n),a=P(n);o>=500?Ge.error("http",`${e.method} ${e.path} ${o} ${i}`,{method:e.method,path:e.path,status:o,code:i,reason:a,stack:Ve(n)}):Ge.warn("http",`${e.method} ${e.path} ${o} ${i}`,{method:e.method,path:e.path,status:o,code:i,reason:a}),S(e.res,o,i,a,$(n))}}}static getName(){return"aitableErrorMapping"}};s(te,"ErrorMappingMiddleware"),te=u([Dn()],te);import{Middleware as Rn,Inject as On}from"@midwayjs/core";import{enrichLogContext as In}from"aitable-workflow-core";var V=class{serverServices;resolve(){return async(e,r)=>{let{identityService:n}=this.serverServices;if(vt(e.path,e.method)){e.state.scope={},await r();return}let o=await n.resolveIdentity(e.req);if(e.state.identity=o,e.state.scope=o.actor,In({uid:o.machine?o.machine.ownerUserId??void 0:o.user?.openId??o.actor.actorId}),!o.authenticated){if(e.respond=!1,o.loginUrl){kn(e.req)?(e.res.writeHead(302,{location:o.loginUrl}),e.res.end()):(e.res.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.res.end(`${JSON.stringify({error:{code:"UNAUTHORIZED",message:"\u672A\u767B\u5F55",loginUrl:o.loginUrl}})}
4
- `));return}xt(e.res);return}await r()}}static getName(){return"aitableIdentity"}};s(V,"IdentityMiddleware"),u([On()],V.prototype,"serverServices",2),V=u([Rn()],V);function kn(t){let e=(t.method??"").toUpperCase();if(e!=="GET"&&e!=="HEAD")return!1;let r=t.headers.accept??"";return(Array.isArray(r)?r.join(","):r).includes("text/html")}s(kn,"shouldRedirectBrowser");import{Middleware as bn,Inject as En}from"@midwayjs/core";var An=new Set(["import-zip"]);function _n(t){let r=/^\/api\/projects\/([^/?#]+)/.exec(t)?.[1];if(r&&!An.has(r))try{return decodeURIComponent(r)}catch{return r}}s(_n,"projectIdFromPath");var G=class{serverServices;resolve(){return async(e,r)=>{let n=_n(e.path);n&&!e.state.project&&(e.state.project=await this.serverServices.projectStore.projects.resolve(n,O(e))),await r()}}static getName(){return"aitableResolveProject"}};s(G,"ResolveProjectMiddleware"),u([En()],G.prototype,"serverServices",2),G=u([bn()],G);import{Middleware as Mn,Inject as Cn}from"@midwayjs/core";import Ke from"path";import{readFile as Fn,access as Wn}from"fs/promises";import{resolveInsideRoot as Nn}from"aitable-workflow-core";var Ln={".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 jt(t,e,r,n){let o=Ke.resolve(t),i=Ke.join(o,"index.html"),a=decodeURIComponent(e).replace(/^\/+/,""),c;try{c=a===""?i:Nn(o,a,{allowRoot:!1})}catch{c=i}try{await Wn(c)}catch{c=i}try{let d=await Fn(c),p=Ke.extname(c).toLowerCase(),w=Ln[p]??"application/octet-stream";if(n.writeHead(200,{"Content-Type":w,"Content-Length":d.byteLength}),r.method==="HEAD"){n.end();return}n.end(d)}catch{S(n,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(jt,"serveStaticWeb");var K=class{serverServices;resolve(){return async(e,r)=>{let n=this.serverServices.webRoot,o=e.method.toUpperCase(),i=e.path;if(n&&(o==="GET"||o==="HEAD")&&!i.startsWith("/api/")&&i!=="/check.node"){e.respond=!1,await jt(n,i,e.req,e.res);return}await r()}}static getName(){return"aitableStaticWeb"}};s(K,"StaticWebMiddleware"),u([Cn()],K.prototype,"serverServices",2),K=u([Mn()],K);var re=class{app;async onReady(){this.app.useMiddleware([X,te,K,V,G])}};s(re,"ServerConfiguration"),u([Un()],re.prototype,"app",2),re=u([Bn({namespace:"aitableServer"})],re);import{Controller as $n,Get as ye,Inject as Dt}from"@midwayjs/core";import{detectAgents as qn}from"aitable-workflow-core";var M=class{ctx;serverServices;async health(){this.ctx.respond=!1,f(this.ctx.res,{ok:!0})}async checkNode(){this.ctx.respond=!1,Pt(this.ctx.res,"success")}async publicConfig(){let e=process.env.RELAY_PUBLIC_GATEWAY_URL?.trim();this.ctx.respond=!1,f(this.ctx.res,{authEnabled:this.serverServices.identityService.authRequired,...e?{relayGatewayUrl:e}:{}})}async agents(){this.ctx.respond=!1,f(this.ctx.res,qn())}async machines(){this.ctx.respond=!1,f(this.ctx.res,{machines:this.serverServices.execution.listMachines()??[]})}};s(M,"SystemController"),u([Dt()],M.prototype,"ctx",2),u([Dt()],M.prototype,"serverServices",2),u([ye("/api/health")],M.prototype,"health",1),u([ye("/check.node")],M.prototype,"checkNode",1),u([ye("/api/public-config")],M.prototype,"publicConfig",1),u([ye("/api/agents")],M.prototype,"agents",1),u([ye("/api/machines")],M.prototype,"machines",1),M=u([$n("/")],M);import ne from"path";import{Controller as Xo,Del as es,Get as ce,Inject as Dr,Patch as ct,Post as me,Put as Tr}from"@midwayjs/core";import{validateDesignArtifacts as ts,buildEnvSource as rs,loadWorkflowTemplate as Rr,loadSettings as Or}from"aitable-workflow-core";import{DwsClient as Tt,dwsPayload as Ye,findArrayPayload as Rt}from"aitable-workflow-core";function zn(t,e){let r={},n=s((o,i)=>{o&&i!==void 0&&(typeof i=="string"&&i.trim()===""||(r[o]=i))},"put");return n(t.name,e.name),n(t.type,e.type),n(t.owner,e.owner),n(t.runtime,e.runtime),n(t.online,e.online),n(t.visibility,e.visibility),n(t.enabled,e.enabled),n(t.description,e.description),r}s(zn,"buildRegistryCells");function Ot(t){let e=new Map;for(let r of Rt(t)){let n=r;n.fieldId&&n.fieldName&&e.set(n.fieldName,n.fieldId)}return e}s(Ot,"fieldIdByName");function Jn(t,e){let r={};for(let[n,o]of Object.entries(t)){let i=e.get(n);i&&(r[i]=o)}return r}s(Jn,"translateCellsToIds");async function It(t){let{registry:e,input:r}=t,n=t.dws??new Tt({bin:"dws"}),o=await n.runJson(["aitable","field","list","--base-id",e.base_id,"--table-id",e.table_id]),i=Ot(Ye(o)),a=Jn(zn(e.fields,r),i);if(Object.keys(a).length===0)throw new Error("\u767B\u8BB0\u8868\u5217\u540D\u4E0E identity.registry.fields \u4E0D\u5339\u914D\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u5355\u5143\u683C");let c=await n.runJson(["aitable","record","create","--base-id",e.base_id,"--table-id",e.table_id,"--records",JSON.stringify([{cells:a}]),"--yes"]),p=Ye(c)?.newRecordIds?.[0];if(!p)throw new Error("dws \u672A\u8FD4\u56DE\u65B0\u884C recordId");return{recordId:p}}s(It,"createRegistryAgent");function Ze(t){if(t==null)return;if(typeof t=="boolean"||typeof t=="string")return t;if(typeof t=="number")return String(t);if(Array.isArray(t))return t.map(n=>Ze(n)).filter(n=>n!==void 0).map(String).join("\u3001");let e=t,r=e.name??e.text??e.value;if(r!==void 0)return Ze(r)}s(Ze,"cellToScalar");function se(t,e,r){if(!r)return;let n=e.get(r);if(n)return Ze(t[n])}s(se,"readColumn");async function kt(t){let{registry:e}=t,r=t.dws??new Tt({bin:"dws"}),n=await r.runJson(["aitable","field","list","--base-id",e.base_id,"--table-id",e.table_id]),o=Ot(Ye(n)),i=await r.runJson(["aitable","record","list","--base-id",e.base_id,"--table-id",e.table_id]),a=[];for(let c of Rt(i)){let d=c;if(!d.recordId||!d.cells)continue;let p=d.cells,w=se(p,o,e.fields.enabled);a.push({recordId:d.recordId,name:String(se(p,o,e.fields.name)??""),type:se(p,o,e.fields.type),owner:se(p,o,e.fields.owner),runtime:se(p,o,e.fields.runtime),online:se(p,o,e.fields.online),visibility:se(p,o,e.fields.visibility),enabled:typeof w=="boolean"?w:w===void 0?void 0:!!w,description:se(p,o,e.fields.description)})}return a}s(kt,"listRegistryAgents");import{isTerminalPhase as Vn,logger as Gn}from"aitable-workflow-core";var Se=new Set,ie=new Map,Hn=8,ue=new Map;function bt(t){let e=ie.get(t);if(e)return{buffer:e.buffer,live:!0};let r=ue.get(t);return r?{buffer:r,live:!1}:null}s(bt,"retainedDesignBuffer");function Qe(t,e,r){t.write(`id: ${e}
1
+ var Ye=Object.defineProperty;var Pn=Object.getOwnPropertyDescriptor;var o=(t,e)=>Ye(t,"name",{value:e,configurable:!0});var xn=(t,e)=>{for(var r in e)Ye(t,r,{get:e[r],enumerable:!0})};var p=(t,e,r,n)=>{for(var s=n>1?void 0:n?Pn(e,r):e,a=t.length-1,i;a>=0;a--)(i=t[a])&&(s=(n?i(e,r,s):i(s))||s);return n&&s&&Ye(e,r,s),s};function ie(t){let e=Array.isArray(t)?t[0]:t;return e!=null&&e!==""?e:null}o(ie,"firstQueryValue");function O(t){return t.state.scope??{}}o(O,"scopeOf");function Zi(t){return t.state.identity}o(Zi,"identityOf");var Le={};xn(Le,{Configuration:()=>X,CorsMiddleware:()=>Y,ErrorMappingMiddleware:()=>Q,IdentityMiddleware:()=>V,ProjectsController:()=>R,ResolveProjectMiddleware:()=>H,ServerConfiguration:()=>X,StagesController:()=>T,StaticWebMiddleware:()=>z,SystemController:()=>C,WorkflowsController:()=>N});import{Configuration as Vn,App as Hn}from"@midwayjs/core";import{Middleware as In}from"@midwayjs/core";import Rn from"crypto";function Pt(t,e){Dn(t,e),e.setHeader("access-control-allow-methods","GET,POST,PUT,PATCH,DELETE,OPTIONS"),e.setHeader("access-control-allow-headers","content-type, authorization")}o(Pt,"setCors");function Dn(t,e){let r=jn();if(!r){e.setHeader("access-control-allow-origin","*");return}let n=t.headers.origin,s=Array.isArray(n)?n[0]:n;s&&r.includes(s)&&(e.setHeader("access-control-allow-origin",s),e.setHeader("vary","Origin"))}o(Dn,"applyCorsOrigin");function jn(){let t=process.env.AITABLE_WORKFLOW_ALLOWED_ORIGINS;if(typeof t!="string")return;let e=t.split(",").map(r=>r.trim()).filter(Boolean);return e.length?e:void 0}o(jn,"readAllowedOrigins");function Tn(){let t=process.env.AITABLE_WORKFLOW_API_TOKEN,e=typeof t=="string"?t.trim():"";return e||void 0}o(Tn,"readServerApiToken");function xt(t){let e=Tn();if(!e)return!0;let r=t.headers.authorization,n=Array.isArray(r)?r[0]:r;if(!n)return!1;let a=/^Bearer\s+(.+)$/i.exec(n.trim())?.[1]?.trim();return a?On(a,e):!1}o(xt,"isRequestAuthorized");function On(t,e){let r=Buffer.from(t),n=Buffer.from(e);return r.length!==n.length?!1:Rn.timingSafeEqual(r,n)}o(On,"timingSafeEqualString");function Rt(t){return Array.isArray(t)?t[0]:t}o(Rt,"headerValue");function Dt(t,e){let r=e.toUpperCase();return r==="OPTIONS"||r==="GET"&&t==="/api/health"||r==="GET"&&t==="/api/public-config"||r==="GET"&&t==="/check.node"}o(Dt,"isAuthExempt");var Y=class{resolve(){return async(e,r)=>{if(Pt(e.req,e.res),e.method.toUpperCase()==="OPTIONS"){e.respond=!1,e.res.writeHead(204),e.res.end();return}await r()}}static getName(){return"aitableCors"}};o(Y,"CorsMiddleware"),Y=p([In()],Y);import{Middleware as kn}from"@midwayjs/core";import{logger as Xe}from"aitable-workflow-core";async function A(t){let r=(await Ze(t)).toString("utf8").trim();return r?JSON.parse(r):{}}o(A,"readJson");async function Ze(t,e){let r=[],n=0,s=!1;for await(let a of t){if(s)continue;let i=Buffer.isBuffer(a)?a:Buffer.from(a);if(n+=i.length,e!==void 0&&n>e){s=!0,r.length=0;continue}r.push(i)}if(s)throw Object.assign(new Error(`\u8BF7\u6C42\u4F53\u8D85\u8FC7\u4E0A\u9650 ${e} \u5B57\u8282\uFF0C\u5DF2\u62D2\u7EDD\uFF08\u5F53\u524D\u5DF2\u7D2F\u8BA1 ${n} \u5B57\u8282\uFF09`),{code:"PAYLOAD_TOO_LARGE",status:413});return Buffer.concat(r)}o(Ze,"readBuffer");function g(t,e,r=200){t.writeHead(r,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify(e)}
2
+ `)}o(g,"sendJson");function jt(t,e,r=200){t.writeHead(r,{"content-type":"text/plain; charset=UTF-8"}),t.end(e)}o(jt,"sendText");function S(t,e,r,n,s){g(t,{error:{code:r,message:n,details:s}},e)}o(S,"sendError");function Tt(t){t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify({error:"unauthorized"})}
3
+ `)}o(Tt,"sendUnauthorized");function le(t){return{code:F(t),message:v(t),details:B(t)}}o(le,"apiError");function Z(t){return typeof t=="object"&&t!==null&&"status"in t&&typeof t.status=="number"?t.status:500}o(Z,"errorStatus");function F(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}o(F,"errorCode");function v(t){return t instanceof Error?t.message:String(t)}o(v,"errorMessage");function B(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}o(B,"errorDetails");function Qe(t){return t instanceof Error?t.stack:void 0}o(Qe,"errorStack");function En(t){if(Z(t)!==404||typeof t!="object"||t===null)return!1;let{code:e,name:r}=t;return e==="404"||e===404||r==="NotFoundError"}o(En,"isFrameworkRouteMiss");var Q=class{resolve(){return async(e,r)=>{try{await r(),e.res.headersSent||(e.respond=!1,S(e.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728"))}catch(n){if(e.res.headersSent){Xe.error("http",`${e.method} ${e.path} \u54CD\u5E94\u5DF2\u53D1\u51FA\u540E\u629B\u9519\uFF0C\u8FDE\u63A5\u4E2D\u65AD`,{method:e.method,path:e.path,code:F(n),reason:v(n),stack:Qe(n)}),e.res.writableEnded||e.res.end();return}if(e.respond=!1,En(n)){S(e.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728");return}let s=Z(n),a=F(n),i=v(n);s>=500?Xe.error("http",`${e.method} ${e.path} ${s} ${a}`,{method:e.method,path:e.path,status:s,code:a,reason:i,stack:Qe(n)}):Xe.warn("http",`${e.method} ${e.path} ${s} ${a}`,{method:e.method,path:e.path,status:s,code:a,reason:i}),S(e.res,s,a,i,B(n))}}}static getName(){return"aitableErrorMapping"}};o(Q,"ErrorMappingMiddleware"),Q=p([kn()],Q);import{Middleware as bn,Inject as An}from"@midwayjs/core";import{enrichLogContext as _n}from"aitable-workflow-core";var V=class{serverServices;resolve(){return async(e,r)=>{let{identityService:n}=this.serverServices;if(Dt(e.path,e.method)){e.state.scope={},await r();return}let s=await n.resolveIdentity(e.req);if(e.state.identity=s,e.state.scope=s.actor,_n({uid:s.machine?s.machine.ownerUserId??void 0:s.user?.openId??s.actor.actorId}),!s.authenticated){if(e.respond=!1,s.loginUrl){Fn(e.req)?(e.res.writeHead(302,{location:s.loginUrl}),e.res.end()):(e.res.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.res.end(`${JSON.stringify({error:{code:"UNAUTHORIZED",message:"\u672A\u767B\u5F55",loginUrl:s.loginUrl}})}
4
+ `));return}Tt(e.res);return}await r()}}static getName(){return"aitableIdentity"}};o(V,"IdentityMiddleware"),p([An()],V.prototype,"serverServices",2),V=p([bn()],V);function Fn(t){let e=(t.method??"").toUpperCase();if(e!=="GET"&&e!=="HEAD")return!1;let r=t.headers.accept??"";return(Array.isArray(r)?r.join(","):r).includes("text/html")}o(Fn,"shouldRedirectBrowser");import{Middleware as Nn,Inject as Mn}from"@midwayjs/core";var Wn=new Set(["import-zip"]);function Ln(t){let r=/^\/api\/projects\/([^/?#]+)/.exec(t)?.[1];if(r&&!Wn.has(r))try{return decodeURIComponent(r)}catch{return r}}o(Ln,"projectIdFromPath");var H=class{serverServices;resolve(){return async(e,r)=>{let n=Ln(e.path);n&&!e.state.project&&(e.state.project=await this.serverServices.projectStore.projects.resolve(n,O(e))),await r()}}static getName(){return"aitableResolveProject"}};o(H,"ResolveProjectMiddleware"),p([Mn()],H.prototype,"serverServices",2),H=p([Nn()],H);import{Middleware as $n,Inject as Jn}from"@midwayjs/core";import et from"path";import{readFile as Cn,access as Un}from"fs/promises";import{resolveInsideRoot as qn}from"aitable-workflow-core";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",".sh":"text/plain; charset=utf-8",".ps1":"text/plain; charset=utf-8"};async function Ot(t,e,r,n){let s=et.resolve(t),a=et.join(s,"index.html"),i=decodeURIComponent(e).replace(/^\/+/,""),c;try{c=i===""?a:qn(s,i,{allowRoot:!1})}catch{c=a}try{await Un(c)}catch{c=a}try{let d=await Cn(c),u=et.extname(c).toLowerCase(),w=Bn[u]??"application/octet-stream";if(n.writeHead(200,{"Content-Type":w,"Content-Length":d.byteLength}),r.method==="HEAD"){n.end();return}n.end(d)}catch{S(n,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")}}o(Ot,"serveStaticWeb");var z=class{serverServices;resolve(){return async(e,r)=>{let n=this.serverServices.webRoot,s=e.method.toUpperCase(),a=e.path;if(n&&(s==="GET"||s==="HEAD")&&!a.startsWith("/api/")&&a!=="/check.node"){e.respond=!1,await Ot(n,a,e.req,e.res);return}await r()}}static getName(){return"aitableStaticWeb"}};o(z,"StaticWebMiddleware"),p([Jn()],z.prototype,"serverServices",2),z=p([$n()],z);var X=class{app;async onReady(){this.app.useMiddleware([Y,Q,z,V,H])}};o(X,"ServerConfiguration"),p([Hn()],X.prototype,"app",2),X=p([Vn({namespace:"aitableServer"})],X);import{Controller as Es,Get as Se,Inject as or}from"@midwayjs/core";import{detectAgents as bs}from"aitable-workflow-core";import{logger as Kt,loadSettings as fs,runWithExecutor as ms,runWithRecipeRunner as gs}from"aitable-workflow-core";import{createHash as zn,randomUUID as Gn}from"crypto";import{mkdir as tt,readdir as rt,readFile as nt,rm as st,stat as It,writeFile as kt}from"fs/promises";import j from"path";var Kn=j.resolve(process.cwd(),".sandbox","aitable-workflow-server"),Et=/^[a-zA-Z0-9_-]+$/,Yn=/\.(json|ya?ml|ts|js|md|txt)$/i,Zn=["workflow.yml","recipes","traces"];function bt(t={}){let e=j.resolve(t.dataRoot??process.env.AITABLE_WORKFLOW_DATA_DIR??Kn);return{dataRoot:e,projectsRoot:j.join(e,"projects")}}o(bt,"createWorkspace");async function At(t){await tt(t.projectsRoot,{recursive:!0});let e=new Date().toISOString(),r=(await ot(t)).length+1,n={id:`wf_${Gn().slice(0,8)}`,title:`\u5DE5\u4F5C\u6D41 #${r}`,dir:"",createdAt:e,updatedAt:e};return n.dir=Lt(t,n.id),await tt(n.dir,{recursive:!0}),await Oe(n),n}o(At,"createProject");async function fe(t,e){let r=await I({dataRoot:j.dirname(j.dirname(t.dir)),projectsRoot:j.dirname(t.dir)},t.id),n={...r,...e,title:e.title?.trim()||r.title,updatedAt:new Date().toISOString()};return await Oe(n),n}o(fe,"updateProjectMeta");async function ot(t){let e=await rt(t.projectsRoot,{withFileTypes:!0}).catch(()=>[]);return(await Promise.all(e.filter(n=>n.isDirectory()&&Et.test(n.name)).map(n=>I(t,n.name).catch(()=>null)))).filter(n=>n!==null).sort((n,s)=>s.updatedAt.localeCompare(n.updatedAt))}o(ot,"listProjects");async function I(t,e){Ct(e);let r=Lt(t,e);if(!(await It(r).catch(()=>null))?.isDirectory())throw Object.assign(new Error(`\u9879\u76EE\u4E0D\u5B58\u5728: ${e}`),{code:"PROJECT_NOT_FOUND",status:404});let s=j.join(r,"project.json"),a=await nt(s,"utf8").catch(()=>"");if(!a){let c=new Date().toISOString(),d={id:e,dir:r,createdAt:c,updatedAt:c};return await Oe(d),d}return{...JSON.parse(a),dir:r}}o(I,"resolveProject");async function L(t){let e={...t,updatedAt:new Date().toISOString()};return await Oe(e),e}o(L,"touchProject");async function _t(t){return await Promise.all([...Zn.map(e=>st(j.join(t.dir,e),{recursive:!0,force:!0})),Ie(t.dir)]),await L(t)}o(_t,"resetProjectWorkflow");async function Te(t){await st(t.dir,{recursive:!0,force:!0})}o(Te,"deleteProject");async function Qn(t){let e=await nt(Wt(t),"utf8").catch(()=>"");return e.trim()?JSON.parse(e):null}o(Qn,"readDesignManifest");async function it(t,e){await tt(Mt(t),{recursive:!0}),await kt(Wt(t),`${JSON.stringify(e,null,2)}
5
+ `,"utf8")}o(it,"writeDesignManifest");async function Ft(t){let e=await Qn(t);if(!e)return{status:"missing_manifest",manifest:null,errors:["\u7F3A\u5C11 Design \u4EA7\u7269\u6E05\u5355"],missing:["runtime/artifacts/design-manifest.json"]};if(e.status!=="ready"||!e.validation.passed)return{status:"invalid",manifest:e,errors:e.validation.errors.length?e.validation.errors:["Design \u4EA7\u7269\u6E05\u5355\u672A\u5C31\u7EEA"],missing:[]};let r=e.generated.filter(s=>s.required).map(s=>s.path),n=[];for(let s of r)(await It(j.join(t.dir,s)).catch(()=>null))?.isFile()||n.push(s);return n.length>0?{status:"artifact_missing",manifest:e,errors:[`\u7F3A\u5C11 Design \u4EA7\u7269\uFF1A${n.join(", ")}`],missing:n}:{status:"ready",manifest:e,errors:[],missing:[]}}o(Ft,"validateDesignArtifacts");function we(t){return zn("sha256").update(t).digest("hex")}o(we,"checksumContent");async function k(t){let e=[];return await qt(t.dir,t.dir,e),e.sort((r,n)=>r.path.localeCompare(n.path))}o(k,"listProjectFiles");function _(t){return j.join(t.dir,"aitable-workflow.config.yml")}o(_,"configPath");function Nt(t,e,r){let n=new URLSearchParams({entrance:"data",sheetId:e});return r?.trim()&&n.set("viewId",r.trim()),`https://alidocs.dingtalk.com/i/nodes/${t}?iframeQuery=${encodeURIComponent(n.toString())}`}o(Nt,"buildAITableUrl");function Xn(t){return j.join(t.dir,"runtime")}o(Xn,"runtimeDir");function Mt(t){return j.join(Xn(t),"artifacts")}o(Mt,"artifactsDir");function Wt(t){return j.join(Mt(t),"design-manifest.json")}o(Wt,"designManifestPath");function Lt(t,e){return Ct(e),j.join(t.projectsRoot,e)}o(Lt,"projectDir");function Ct(t){if(!Et.test(t))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${t}`),{code:"INVALID_PROJECT_ID"})}o(Ct,"assertProjectId");async function Oe(t){await kt(j.join(t.dir,"project.json"),`${JSON.stringify(t,null,2)}
6
+ `,"utf8")}o(Oe,"writeProjectMeta");function Ut(t){return t==="views.yml"||t.endsWith("/views.yml")}o(Ut,"isLegacyViewsPath");async function Ie(t,e=t){let r=await rt(e,{withFileTypes:!0}).catch(()=>[]);await Promise.all(r.map(async n=>{if(n.name==="node_modules"||n.name==="runtime"||n.name==="traces")return;let s=j.join(e,n.name);if(n.isDirectory()){await Ie(t,s);return}if(!n.isFile())return;let a=j.relative(t,s).split(j.sep).join("/");Ut(a)&&await st(s,{force:!0})}))}o(Ie,"removeLegacyViewsFiles");async function qt(t,e,r){let n=await rt(e,{withFileTypes:!0}).catch(()=>[]);for(let s of n){if(es(t,j.join(e,s.name),s.name))continue;let a=j.join(e,s.name);if(s.isDirectory()){await qt(t,a,r);continue}if(!s.isFile()||!Yn.test(s.name))continue;let i=j.relative(t,a).split(j.sep).join("/");if(Ut(i))continue;let c=await nt(a,"utf8").catch(()=>"");r.push({path:i,content:c})}}o(qt,"walk");function es(t,e,r){return r==="node_modules"||r==="traces"||r==="runtime"||r===".aitable"||r==="project.json"?!0:j.relative(t,e).split(j.sep).join("/").startsWith(".aitable/")}o(es,"isHiddenProjectFile");import{isTerminalPhase as Bt,nextFor as ts,transition as rs}from"aitable-workflow-core";var G=class t{constructor(e,r){this.options=e;this.currentState=r?.state??null,this.identity=r?.identity??null,this.diagnostics=r?.diagnostics}options;static{o(this,"StageWriter")}currentState;identity;diagnostics;tail=Promise.resolve();emit;static async open(e){let n=(await e.store.getState(e.project)).stages[e.stage];return new t(e,n??null)}get state(){return this.currentState}get taskId(){return this.identity?.id??null}get attempt(){return this.identity?.attempt??0}get startedAt(){return this.identity?.startedAt??null}setDiagnostics(e){this.diagnostics=e}advance(e){let r=this.tail.then(()=>this.write(e),()=>this.write(e));return this.tail=r.then(()=>{},()=>{}),r}advanceDetached(e,r){this.advance(e).catch(r)}async write(e){let{project:r,stage:n,store:s,driver:a}=this.options,i=rs(n,this.currentState,e,a);if(i===this.currentState&&this.identity)return this.decorate({identity:this.identity,state:i,...this.diagnostics?{diagnostics:this.diagnostics}:{}});let c=!this.identity||this.currentState!==null&&Bt(n,this.currentState),d=new Date().toISOString(),u=c?await s.createStageIdentity(r,n):{...this.identity,updatedAt:d},m={identity:Bt(n,i)?{...u,completedAt:u.completedAt??d}:u,state:i,...this.diagnostics?{diagnostics:this.diagnostics}:{}};return await s.putStageState(r,n,m),this.currentState=i,this.identity=m.identity,this.decorate(m)}decorate(e){let{project:r,stage:n}=this.options,s={...e,next:ts({projectId:r.id,stage:n,state:e.state,facts:this.options.facts()})};return this.emit?.(s),s}};import{deriveRelayRunState as ss,mergeStageIntoState as os,nextFor as is,transition as as,withStageNext as cs}from"aitable-workflow-core";import{access as ds}from"fs/promises";import us from"path";var he=new Set,ne=new Map,ns=8,me=new Map;function $t(t){let e=ne.get(t);if(e)return{buffer:e.buffer,live:!0};let r=me.get(t);return r?{buffer:r,live:!1}:null}o($t,"retainedDesignBuffer");function at(t,e,r){t.write(`id: ${e}
5
7
  `),t.write(`event: ${r.type}
6
8
  `),t.write(`data: ${JSON.stringify(r)}
7
9
 
8
- `)}s(Qe,"writeDesignSse");function Et(t,e){let r=t.buffer.push(e);for(let n of t.subscribers){if(n.destroyed||n.writableEnded){t.subscribers.delete(n);continue}try{Qe(n,r.seq,e)}catch{t.subscribers.delete(n)}}}s(Et,"publishDesignEvent");function At(t){Se.delete(t);let e=ie.get(t);if(ie.delete(t),!!e){for(ue.delete(t),ue.set(t,e.buffer);ue.size>Hn;){let r=ue.keys().next();if(r.done)break;ue.delete(r.value)}for(let r of e.subscribers)if(!r.writableEnded)try{r.end()}catch{}e.subscribers.clear()}}s(At,"closeDesignSession");function _t(t,e){let r=t.searchParams.get("cursor")??St(e.headers["last-event-id"]);if(r==null||r==="")return;let n=Number(r);return Number.isFinite(n)?n:void 0}s(_t,"parseReconnectCursor");function Kn(t,e){return t.runtime.runSessions.has(e)||Se.has(e)}s(Kn,"isStageActiveFor");function T(t,e){return e.projectStore.prepareWorkdir(t,{isStageActive:s(()=>Kn(e,t.id),"isStageActive")})}s(T,"prepareWorkdirGuarded");async function ve(t,e,r){try{let o=(await t.projectStore.instances.getState(e)).stages[r];if(!o||!Vn(r,o.state))return;await t.projectStore.commitWorkdir(e,{stage:r})}catch(n){Gn.warn("stage-sync","stage \u6D41\u56DE\u5199\u6743\u5A01\u6E90\u5931\u8D25",{projectId:e.id,stage:r,error:P(n)})}}s(ve,"commitStageOnTerminal");async function Ft(t,e){await t.projectStore.cascadeDelete(e).catch(()=>{}),await t.execution.unbindProjectMachine(e).catch(()=>{})}s(Ft,"cascadeDeleteProject");import be from"path";import{readFile as Xt,writeFile as wo,access as ho,readdir as yo}from"fs/promises";import st from"yaml";import{scaffold as So,writeProfileRoles as vo,isRecord as fe}from"aitable-workflow-core";import{isTerminalPhase as Wt,nextFor as Yn,transition as Zn}from"aitable-workflow-core";var Y=class t{constructor(e,r){this.options=e;this.currentState=r?.state??null,this.identity=r?.identity??null,this.diagnostics=r?.diagnostics}options;static{s(this,"StageWriter")}currentState;identity;diagnostics;tail=Promise.resolve();emit;static async open(e){let n=(await e.store.getState(e.project)).stages[e.stage];return new t(e,n??null)}get state(){return this.currentState}get taskId(){return this.identity?.id??null}get attempt(){return this.identity?.attempt??0}get startedAt(){return this.identity?.startedAt??null}setDiagnostics(e){this.diagnostics=e}advance(e){let r=this.tail.then(()=>this.write(e),()=>this.write(e));return this.tail=r.then(()=>{},()=>{}),r}advanceDetached(e,r){this.advance(e).catch(r)}async write(e){let{project:r,stage:n,store:o,driver:i}=this.options,a=Zn(n,this.currentState,e,i);if(a===this.currentState&&this.identity)return this.decorate({identity:this.identity,state:a,...this.diagnostics?{diagnostics:this.diagnostics}:{}});let c=!this.identity||this.currentState!==null&&Wt(n,this.currentState),d=new Date().toISOString(),p=c?await o.createStageIdentity(r,n):{...this.identity,updatedAt:d},m={identity:Wt(n,a)?{...p,completedAt:p.completedAt??d}:p,state:a,...this.diagnostics?{diagnostics:this.diagnostics}:{}};return await o.putStageState(r,n,m),this.currentState=a,this.identity=m.identity,this.decorate(m)}decorate(e){let{project:r,stage:n}=this.options,o={...e,next:Yn({projectId:r.id,stage:n,state:e.state,facts:this.options.facts()})};return this.emit?.(o),o}};import{deriveRelayRunState as io,mergeStageIntoState as ao,nextFor as co,transition as po,withStageNext as uo}from"aitable-workflow-core";import{access as lo}from"fs/promises";import fo from"path";import{createHash as Qn,randomUUID as Xn}from"crypto";import{mkdir as Xe,readdir as et,readFile as tt,rm as rt,stat as Nt,writeFile as Lt}from"fs/promises";import x from"path";var eo=x.resolve(process.cwd(),".sandbox","aitable-workflow-server"),Mt=/^[a-zA-Z0-9_-]+$/,to=/\.(json|ya?ml|ts|js|md|txt)$/i,ro=["workflow.yml","recipes","traces"];function Ct(t={}){let e=x.resolve(t.dataRoot??process.env.AITABLE_WORKFLOW_DATA_DIR??eo);return{dataRoot:e,projectsRoot:x.join(e,"projects")}}s(Ct,"createWorkspace");async function Bt(t){await Xe(t.projectsRoot,{recursive:!0});let e=new Date().toISOString(),r=(await nt(t)).length+1,n={id:`wf_${Xn().slice(0,8)}`,title:`\u5DE5\u4F5C\u6D41 #${r}`,dir:"",createdAt:e,updatedAt:e};return n.dir=Ht(t,n.id),await Xe(n.dir,{recursive:!0}),await Oe(n),n}s(Bt,"createProject");async function le(t,e){let r=await b({dataRoot:x.dirname(x.dirname(t.dir)),projectsRoot:x.dirname(t.dir)},t.id),n={...r,...e,title:e.title?.trim()||r.title,updatedAt:new Date().toISOString()};return await Oe(n),n}s(le,"updateProjectMeta");async function nt(t){let e=await et(t.projectsRoot,{withFileTypes:!0}).catch(()=>[]);return(await Promise.all(e.filter(n=>n.isDirectory()&&Mt.test(n.name)).map(n=>b(t,n.name).catch(()=>null)))).filter(n=>n!==null).sort((n,o)=>o.updatedAt.localeCompare(n.updatedAt))}s(nt,"listProjects");async function b(t,e){Vt(e);let r=Ht(t,e);if(!(await Nt(r).catch(()=>null))?.isDirectory())throw Object.assign(new Error(`\u9879\u76EE\u4E0D\u5B58\u5728: ${e}`),{code:"PROJECT_NOT_FOUND",status:404});let o=x.join(r,"project.json"),i=await tt(o,"utf8").catch(()=>"");if(!i){let c=new Date().toISOString(),d={id:e,dir:r,createdAt:c,updatedAt:c};return await Oe(d),d}return{...JSON.parse(i),dir:r}}s(b,"resolveProject");async function C(t){let e={...t,updatedAt:new Date().toISOString()};return await Oe(e),e}s(C,"touchProject");async function Ut(t){return await Promise.all([...ro.map(e=>rt(x.join(t.dir,e),{recursive:!0,force:!0})),Ie(t.dir)]),await C(t)}s(Ut,"resetProjectWorkflow");async function Re(t){await rt(t.dir,{recursive:!0,force:!0})}s(Re,"deleteProject");async function no(t){let e=await tt(Jt(t),"utf8").catch(()=>"");return e.trim()?JSON.parse(e):null}s(no,"readDesignManifest");async function ot(t,e){await Xe(zt(t),{recursive:!0}),await Lt(Jt(t),`${JSON.stringify(e,null,2)}
9
- `,"utf8")}s(ot,"writeDesignManifest");async function $t(t){let e=await no(t);if(!e)return{status:"missing_manifest",manifest:null,errors:["\u7F3A\u5C11 Design \u4EA7\u7269\u6E05\u5355"],missing:["runtime/artifacts/design-manifest.json"]};if(e.status!=="ready"||!e.validation.passed)return{status:"invalid",manifest:e,errors:e.validation.errors.length?e.validation.errors:["Design \u4EA7\u7269\u6E05\u5355\u672A\u5C31\u7EEA"],missing:[]};let r=e.generated.filter(o=>o.required).map(o=>o.path),n=[];for(let o of r)(await Nt(x.join(t.dir,o)).catch(()=>null))?.isFile()||n.push(o);return n.length>0?{status:"artifact_missing",manifest:e,errors:[`\u7F3A\u5C11 Design \u4EA7\u7269\uFF1A${n.join(", ")}`],missing:n}:{status:"ready",manifest:e,errors:[],missing:[]}}s($t,"validateDesignArtifacts");function Pe(t){return Qn("sha256").update(t).digest("hex")}s(Pe,"checksumContent");async function j(t){let e=[];return await Kt(t.dir,t.dir,e),e.sort((r,n)=>r.path.localeCompare(n.path))}s(j,"listProjectFiles");function A(t){return x.join(t.dir,"aitable-workflow.config.yml")}s(A,"configPath");function qt(t,e,r){let n=new URLSearchParams({entrance:"data",sheetId:e});return r?.trim()&&n.set("viewId",r.trim()),`https://alidocs.dingtalk.com/i/nodes/${t}?iframeQuery=${encodeURIComponent(n.toString())}`}s(qt,"buildAITableUrl");function oo(t){return x.join(t.dir,"runtime")}s(oo,"runtimeDir");function zt(t){return x.join(oo(t),"artifacts")}s(zt,"artifactsDir");function Jt(t){return x.join(zt(t),"design-manifest.json")}s(Jt,"designManifestPath");function Ht(t,e){return Vt(e),x.join(t.projectsRoot,e)}s(Ht,"projectDir");function Vt(t){if(!Mt.test(t))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${t}`),{code:"INVALID_PROJECT_ID"})}s(Vt,"assertProjectId");async function Oe(t){await Lt(x.join(t.dir,"project.json"),`${JSON.stringify(t,null,2)}
10
- `,"utf8")}s(Oe,"writeProjectMeta");function Gt(t){return t==="views.yml"||t.endsWith("/views.yml")}s(Gt,"isLegacyViewsPath");async function Ie(t,e=t){let r=await et(e,{withFileTypes:!0}).catch(()=>[]);await Promise.all(r.map(async n=>{if(n.name==="node_modules"||n.name==="runtime"||n.name==="traces")return;let o=x.join(e,n.name);if(n.isDirectory()){await Ie(t,o);return}if(!n.isFile())return;let i=x.relative(t,o).split(x.sep).join("/");Gt(i)&&await rt(o,{force:!0})}))}s(Ie,"removeLegacyViewsFiles");async function Kt(t,e,r){let n=await et(e,{withFileTypes:!0}).catch(()=>[]);for(let o of n){if(so(t,x.join(e,o.name),o.name))continue;let i=x.join(e,o.name);if(o.isDirectory()){await Kt(t,i,r);continue}if(!o.isFile()||!to.test(o.name))continue;let a=x.relative(t,i).split(x.sep).join("/");if(Gt(a))continue;let c=await tt(i,"utf8").catch(()=>"");r.push({path:a,content:c})}}s(Kt,"walk");function so(t,e,r){return r==="node_modules"||r==="traces"||r==="runtime"||r===".aitable"||r==="project.json"?!0:x.relative(t,e).split(x.sep).join("/").startsWith(".aitable/")}s(so,"isHiddenProjectFile");function Z(t,e,r){if(e==="design"){let n=ie.get(t);return n?{sessionLocal:!0,cursor:n.buffer.cursor}:{sessionLocal:!1}}return e==="run"?{sessionLocal:r.hasRunSession(t)}:{sessionLocal:!1}}s(Z,"stageFactsFor");function Yt(t,e){return uo(t,(r,n)=>co({projectId:t.projectId,stage:r,state:n.state,facts:Z(t.projectId,r,e)}))}s(Yt,"decorateProjectState");async function ke(t,e){let r=await t.projectStore.instances.getRecoverableState(e),n=await mo(t,e,r),o={hasRunSession:s(c=>t.runtime.runSessions.has(c),"hasRunSession")},i=t.execution.runScheduler;if(!i)return Yt(n,o);let a=await i.getStatus(e.id).catch(()=>null);return Yt(a?go(n,a):n,o)}s(ke,"readProjectState");async function mo(t,e,r){if(r.stages.init||!await Promise.all([Zt(A(e)),Zt(fo.join(e.dir,"workflow.yml"))]).then(a=>a.some(Boolean)))return r;let o=new Date().toISOString(),i=po("init",null,{phase:"ready",warnings:[],roleFiles:[]},"system");return await t.projectStore.instances.putStageState(e,"init",{identity:{id:`init_import_${e.id}`,projectId:e.id,stage:"init",attempt:1,startedAt:e.createdAt||o,updatedAt:o,completedAt:o},state:i})}s(mo,"backfillImportedInit");function go(t,e){let r=io(e),n=t.stages.run;if(!n&&r.phase==="stopped")return t;let o=new Date().toISOString();return ao(t,"run",{identity:n?.identity??{id:`run_relay_${t.projectId}`,projectId:t.projectId,stage:"run",attempt:1,startedAt:e.lastHeartbeatAt??o,updatedAt:o},state:r})}s(go,"injectRelayRunState");function Zt(t){return lo(t).then(()=>!0,()=>!1)}s(Zt,"fileExists");function Qt(t,e=1){let r=t.replace(/\s+/g," ").trim();if(!r)return`\u5DE5\u4F5C\u6D41 #${e}`;let n=r.split(/[。.!!?\n]/u)[0]?.split(/[::,,;;]/u)[0]?.trim();return n?n.length>16?n.slice(0,16):n:`\u5DE5\u4F5C\u6D41 #${e}`}s(Qt,"deriveProjectTitleFromSop");async function er(t,e,r,n,o,i){let a=await b(e,t),c=await k(n),d=await Y.open({project:a,stage:"init",store:r,driver:"init.http",facts:s(()=>Z(a.id,"init",{hasRunSession:s(()=>!1,"hasRunSession")}),"facts")});await d.advance({phase:"configuring"});try{let p=xo(c),w=await So({answers:p,cwd:a.dir,force:!0}),m=await vo(be.join(a.dir,"profile","profile.yml"),c.roles??[]);c.machineId&&i&&await i(t,c.machineId).catch(()=>{});let g=await C(a),l=m.skippedKnowledgeBindings.map(I=>`\u89D2\u8272 ${I.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 profile\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${I.knowledge.join(", ")}`);await d.advance({phase:"ready",warnings:l,roleFiles:[]});let D=Qt(c.sop,1),E=await le(g,{title:D});f(o,{project:E,scaffold:w,roleFiles:[],files:await j(g),warnings:l})}catch(p){throw await d.advance({phase:"failed",error:{code:F(p),message:P(p),retryable:!0,details:$(p)}}),p}}s(er,"handleInit");async function tr(t,e,r,n){let o=await b(e.workspace,t),a=(await k(r)).tableId?.trim()??"";if(!a)throw Object.assign(new Error("Table Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"TABLE_ID_REQUIRED",status:422});let c=A(o),d=await Xt(c,"utf8"),p=st.parse(d);if(!fe(p)||!fe(p.tracker)){let m=fe(p)&&fe(p.workflows);throw Object.assign(new Error(m?"\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u7684 table_id \u5C5E\u4E8E\u5404\u81EA\u7684 workflows/<id>/workflow.yml\uFF0C\u8BF7\u76F4\u63A5\u6539\u5BF9\u5E94\u6587\u4EF6\u7684 tracker.table_id":"\u914D\u7F6E\u6587\u4EF6\u7F3A\u5C11 tracker\uFF0C\u65E0\u6CD5\u5199\u56DE Table Id"),{code:m?"TABLE_ID_PER_WORKFLOW":"CONFIG_TRACKER_MISSING",status:m?422:500})}p.tracker.table_id=a,await wo(c,st.stringify(p),"utf8");let w=await C(o);f(n,{project:w,files:await j(w),state:await ke(e,w)})}s(tr,"handleUpdateProjectTableId");async function rr(t,e,r,n,o,i,a){let c=await b(e,t),d=await k(i);if(d.action!=="confirm"&&d.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=n.runSessions.get(t)?.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 w=d.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(!w)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=d.action==="confirm"?"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EE7\u7EED\u6D41\u7A0B":"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EC8\u6B62\u6D41\u7A0B",g=null;d.action==="confirm"&&(g=await Po(p,o)),await p.tracker.updateState(o,w),g&&await p.tracker.updateCurrentStep(o,g),await p.tracker.appendEvent(o,m);let l=await r.updateRunSnapshotRecord(c,o,d.action==="confirm"?{state:w,status:"running",currentStepId:g??void 0}:{state:w,status:"done",currentStepId:null},m);f(a,{action:d.action,recordId:o,state:l})}s(rr,"handleRunHumanAction");async function Po(t,e){let[r]=await t.tracker.fetchItemsByIds([e]).catch(()=>[]),n=r?.currentStep;if(!n)return null;let o=t.workflow.orderedStepIds.indexOf(n);return o<0?null:t.workflow.orderedStepIds[o+1]??null}s(Po,"resolveNextStepId");function xo(t){let e=t.tableBaseId.trim();if(!e)throw Object.assign(new Error("Base Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"BASE_ID_REQUIRED",status:422});let r=t.llmProvider.trim();return{agentType:Do(t.agentsSelected),scene:jo(t),baseId:e,llmProvider:r,llmModel:r?t.llmModel.trim()||To(r):"",llmApiKeyEnv:r?Ro(r):"",confirmed:!0}}s(xo,"toInitAnswers");function jo(t){return t.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(jo,"buildScene");function Do(t){return t.includes("qwenwork")?"qwenwork":t.includes("qoder")?"qoder":t.includes("codex")?"codex":"claudecode"}s(Do,"toAgentType");function To(t){return t==="openai"?"gpt-4o":t==="anthropic"?"claude-sonnet-4-20250514":t==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}s(To,"defaultModel");function Ro(t){return t==="openai"?"OPENAI_API_KEY":t==="anthropic"?"ANTHROPIC_API_KEY":t==="dashscope"?"DASHSCOPE_API_KEY":t==="idealab"?"IDEALAB_API_KEY":"LLM_API_KEY"}s(Ro,"defaultApiKeyEnv");async function nr(t,e){let r=be.join(t.dir,"aitable-workflow.config.yml");try{await ho(r)}catch{e.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 Oo(t.dir)||e.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(nr,"augmentProjectFileValidation");async function Oo(t){try{let r=st.parse(await Xt(be.join(t,"profile","profile.yml"),"utf8"));if(fe(r)&&fe(r.roles)&&Object.keys(r.roles).length>0)return!0}catch{}return(await yo(be.join(t,"roles")).catch(()=>[])).some(r=>r.endsWith(".role.yml")||r.endsWith(".role.yaml"))}s(Oo,"hasAnyRoleDefinition");import or from"fs";import Io from"path";var ko=/requiresAgent\s*:\s*(true|false)/,sr=new Map;function ir(t,e){if(!e)return!1;for(let r of[".recipe.ts",".recipe.js"]){let n=Io.join(t,`${e}${r}`);try{let o=or.statSync(n);if(!o.isFile())continue;let i=`${o.mtimeMs}:${o.size}`,a=sr.get(n);if(a?.signature===i)return a.requiresAgent;let d=or.readFileSync(n,"utf8").match(ko),p=d?d[1]==="true":!1;return sr.set(n,{signature:i,requiresAgent:p}),p}catch(o){if(o.code==="ENOENT")continue;return!1}}return!1}s(ir,"readRecipeRequiresAgent");import{rm as cr,mkdir as bo,writeFile as Eo}from"fs/promises";import xe from"path";import Ao from"yaml";import{isRecord as _o,resolveInsideRoot as Fo}from"aitable-workflow-core";var ar=/\.(json|ya?ml|ts|js|md|txt)$/i,Wo=new Set(["runtime","traces","node_modules"]),dr="aitable-workflow.config.yml";function pr(t,e){try{Fo(t,e,{allowRoot:!1})}catch{throw Object.assign(new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u76EE\u5F55: ${e}`),{code:"invalid_path",status:400})}}s(pr,"assertSafeRelativePath");function it(t,e){pr(t.dir,e)}s(it,"assertSafeProjectPath");function Mc(t){pr("/workflow-root",t)}s(Mc,"assertSafeWorkflowPath");function ur(t){let r=at(t).split("/")[0]??"";return Wo.has(r)}s(ur,"isForbiddenWritable");function lr(t){if(mr(t))throw Object.assign(new Error(`\u5DF2\u5E9F\u5F03\u7684\u89C6\u56FE\u6587\u4EF6\u5FC5\u987B\u5185\u8054\u5230 workflow.yml \u7684 tracker.views: ${t}`),{code:"invalid_path",status:400});if(ur(t))throw Object.assign(new Error(`\u7981\u6B62\u5199\u5165\u53D7\u4FDD\u62A4\u76EE\u5F55: ${t}`),{code:"invalid_path",status:400});if(!ar.test(t))throw Object.assign(new Error(`\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8\u5199\u5165: ${t}\uFF08\u4EC5\u5141\u8BB8 ${ar.source}\uFF09`),{code:"invalid_path",status:400})}s(lr,"assertWritableKind");function fr(t){let e=at(t);return e===dr||e.endsWith(".config.yml")?"config":e==="workflow.yml"?"workflow":e.startsWith("recipes/")?"recipe":e.startsWith("roles/")?"role":"other"}s(fr,"kindOf");function mr(t){let e=at(t);return e==="views.yml"||e.endsWith("/views.yml")}s(mr,"isLegacyViewsPath");function at(t){return xe.posix.normalize(t.replace(/\\/g,"/")).replace(/^\.\//,"")}s(at,"normalizeLogicalPath");function No(t){let e=[],r;try{r=Ao.parse(t)}catch(o){return e.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${o instanceof Error?o.message:String(o)}`),e}if(!_o(r))return e.push("aitable-workflow.config.yml \u9876\u5C42\u5E94\u4E3A\u5BF9\u8C61"),e;let n=r.scene;return(typeof n!="string"||n.trim()==="")&&e.push("aitable-workflow.config.yml \u7F3A\u5C11 scene \u5B57\u6BB5\uFF08\u5EFA\u8BAE\u586B\u5199\u4E1A\u52A1\u573A\u666F\u63CF\u8FF0\uFF09"),e}s(No,"validateConfigScene");async function Ee(t,e){let r=[],n=[];for(let o of e){it(t,o.path),lr(o.path);let i=xe.join(t.dir,o.path);await bo(xe.dirname(i),{recursive:!0}),await Eo(i,o.content,"utf8"),r.push({path:o.path,content:o.content}),o.path===dr&&n.push(...No(o.content))}return{written:r,warnings:n}}s(Ee,"writeProjectFiles");async function gr(t,e){for(let r of e){if(it(t,r),ur(r))throw Object.assign(new Error(`\u7981\u6B62\u5220\u9664\u53D7\u4FDD\u62A4\u76EE\u5F55: ${r}`),{code:"invalid_path",status:400});await cr(xe.join(t.dir,r),{force:!0})}}s(gr,"removeProjectFiles");async function wr(t,e){for(let n of e)it(t,n.path),lr(n.path);let r=await Lo(t);for(let n of r)await cr(xe.join(t.dir,n),{force:!0}).catch(()=>{});return await Ie(t.dir),Ee(t,e)}s(wr,"replaceProjectFiles");async function Lo(t){return(await j(t)).map(r=>r.path).filter(r=>fr(r)!=="other"||mr(r))}s(Lo,"collectBusinessFiles");function Mo(t){return Pe(t.content)}s(Mo,"checksumFile");async function hr(t){let e=await j(t),r=e.map(n=>({path:n.path,sha256:Mo(n)}));return{project:t,files:e,checksums:r,exportedAt:new Date().toISOString()}}s(hr,"buildProjectExport");var Co="coding-agents.config.json";function yr(t){let e=[],r=t.files,n=t.checksums,o=r.findIndex(i=>i.path===Co);if(o>=0){let i=r[o],a=i.content;try{let c=JSON.parse(i.content);if(c&&typeof c=="object"&&!Array.isArray(c)){let d=c.agents;if(d&&typeof d=="object"&&!Array.isArray(d)){let p=!1;for(let w of Object.keys(d)){let m=d[w];if(!m||typeof m!="object"||Array.isArray(m))continue;let g=m.env;if(g&&typeof g=="object"&&!Array.isArray(g)){let l=g;if(Object.values(l).some(E=>typeof E=="string"&&E!=="")){for(let E of Object.keys(l))l[E]="";p=!0}}}p&&(a=JSON.stringify(c,null,2)+`
11
- `)}}}catch{}if(a!==i.content){let c={path:i.path,content:a};r=r.map((p,w)=>w===o?c:p);let d=Pe(a);n=n.map((p,w)=>w===o?{path:p.path,sha256:d}:p),e.push(i.path)}}return{...t,files:r,checksums:n,redacted:e.length>0?e:t.redacted}}s(yr,"redactExportBundle");import Sr from"path";import{strFromU8 as vr,unzipSync as Bo}from"fflate";var Uo=/\.(json|ya?ml|ts|js|md|txt)$/i,$o=new Set(["runtime","traces","node_modules"]),qo=new Set(["__MACOSX"]),zo=/(^|\/)\.(_|DS_Store)/,Jo="project-manifest.json",Ho="project.json",Pr=20*1024*1024,Vo=5e3,Go=100*1024*1024;function xr(t,e={}){let r=e.maxEntries??Vo,n=e.maxTotalUncompressedBytes??Go,o=0,i=0,a,c;try{c=Bo(new Uint8Array(t),{filter:s(l=>l.name.endsWith("/")||a?!1:(o+=1,i+=l.originalSize,o>r?(a=`zip \u6761\u76EE\u6570\u8D85\u8FC7\u4E0A\u9650\uFF08${r}\uFF09`,!1):i>n?(a=`zip \u89E3\u538B\u540E\u603B\u5927\u5C0F\u8D85\u8FC7\u4E0A\u9650\uFF08${n} \u5B57\u8282\uFF09`,!1):!0),"filter")})}catch(l){throw a?Object.assign(new Error(`zip \u8D85\u8FC7\u5BFC\u5165\u5BB9\u91CF\u4E0A\u9650\uFF1A${a}`),{code:"ZIP_TOO_LARGE",status:413}):Object.assign(new Error(`zip \u89E3\u6790\u5931\u8D25: ${l instanceof Error?l.message:String(l)}`),{code:"INVALID_ZIP",status:400})}if(a)throw Object.assign(new Error(`zip \u8D85\u8FC7\u5BFC\u5165\u5BB9\u91CF\u4E0A\u9650\uFF1A${a}`),{code:"ZIP_TOO_LARGE",status:413});let d=Object.entries(c).filter(([l])=>!l.endsWith("/")).map(([l,D])=>({path:Ko(l),data:D})).filter(l=>!!l.path),p=Yo(d.map(l=>l.path)),w=new Map,m;for(let l of d){let D=p(l.path);if(D===Jo){let I=vr(l.data);m=Qo(I)??m;continue}if(!D||Zo(D))continue;let E=vr(l.data);w.set(D,{path:D,content:E})}let g=Array.from(w.values()).sort((l,D)=>l.path.localeCompare(D.path));if(g.length===0)throw Object.assign(new Error("zip \u4E2D\u672A\u89E3\u6790\u5230\u53EF\u5BFC\u5165\u7684\u9879\u76EE\u6587\u4EF6\uFF08\u4EC5\u652F\u6301 .json/.yml/.yaml/.ts/.js/.md/.txt\uFF0C\u4E14\u4E0D\u80FD\u4F4D\u4E8E runtime/traces/node_modules\uFF09"),{code:"EMPTY_ZIP_PROJECT",status:422});return{files:g,title:m}}s(xr,"parseProjectZip");function Ko(t){let e=t.replace(/\\/g,"/").replace(/^\/+/,"");if(!e||e.includes("\0"))return null;let r=Sr.posix.normalize(e).replace(/^\.\//,"");return!r||r==="."||r===".."||r.startsWith("../")||Sr.posix.isAbsolute(r)?null:r}s(Ko,"normalizeZipPath");function Yo(t){let e=t.filter(a=>!jr(a)),r=new Set,n=!1;for(let a of e){let c=a.split("/",2),d=c[0],p=c[1];if(!d||!p){n=!0;break}r.add(d)}if(n||r.size!==1)return a=>a;let[o]=Array.from(r);if(!o)return a=>a;let i=`${o}/`;return a=>a.startsWith(i)?a.slice(i.length):a}s(Yo,"detectSingleTopDir");function Zo(t){if(!t||t===Ho||jr(t))return!0;let e=t.split("/")[0]??"";return $o.has(e)?!0:!Uo.test(t)}s(Zo,"shouldSkipPath");function jr(t){let e=t.split("/")[0]??"";return qo.has(e)||zo.test(t)}s(jr,"isJunkPath");function Qo(t){try{let e=JSON.parse(t);return typeof e.title=="string"&&e.title.trim()?e.title.trim():void 0}catch{return}}s(Qo,"readManifestTitle");var v=class{ctx;serverServices;async list(){let e=await this.serverServices.projectStore.projects.list(O(this.ctx));this.ctx.respond=!1,f(this.ctx.res,{projects:e})}async create(){let e=this.serverServices,r=O(this.ctx),n=await k(this.ctx.req),o=await e.projectStore.projects.create(r,{title:n.title,files:n.files});await T(o,e);let i={project:o};o.files&&(i.files=o.files),o.warnings&&o.warnings.length>0&&(i.warnings=o.warnings),this.ctx.respond=!1,f(this.ctx.res,i)}async importZip(){let e=this.serverServices,r=O(this.ctx),n=await He(this.ctx.req,Pr),o=xr(n),i=he(this.ctx.query?.title)?.trim()||o.title||"\u5BFC\u5165\u9879\u76EE",a=await e.projectStore.projects.create(r,{title:i,files:o.files});await T(a,e);let c={project:a,files:a.files,imported:{source:"zip",fileCount:o.files.length}};a.warnings&&a.warnings.length>0&&(c.warnings=a.warnings),this.ctx.respond=!1,f(this.ctx.res,c)}async remove(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project;if(this.ctx.respond=!1,e.runtime.runSessions.has(n.id)){S(this.ctx.res,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664");return}await e.projectStore.projects.delete(n,r),await Re(n),await Ft(e,n.id),f(this.ctx.res,{ok:!0,id:n.id})}async updateMeta(){let e=this.serverServices,r=O(this.ctx),n=await k(this.ctx.req),o=await e.projectStore.projects.updateMeta(this.ctx.state.project,{title:n.title},r);this.ctx.respond=!1,f(this.ctx.res,{project:o})}async init(){let e=this.serverServices,r=this.ctx.state.project;this.ctx.respond=!1,await T(r,e);let n=e.execution;await er(r.id,e.workspace,e.projectStore.instances,this.ctx.req,this.ctx.res,(o,i)=>n.bindProjectMachine(o,i)),await ve(e,r,"init")}async getEngine(){let e=this.ctx.state.project,r=this.serverServices.execution,n=await r.getProjectMachine(e.id);if(this.ctx.respond=!1,!n){f(this.ctx.res,{machineId:null,machine:null,status:"unbound"});return}let o=r.isMachineOnline(n),a=(r.listMachines()??[]).find(c=>c.machineId===n);f(this.ctx.res,{machineId:n,machine:a??null,status:o?"online":"offline"})}async bindEngine(){let e=await k(this.ctx.req);if(this.ctx.respond=!1,!e.machineId){S(this.ctx.res,422,"INVALID_INPUT","machineId \u4E0D\u80FD\u4E3A\u7A7A");return}await this.serverServices.execution.bindProjectMachine(this.ctx.state.project.id,e.machineId),f(this.ctx.res,{ok:!0,machineId:e.machineId})}async getAgents(){let e=this.ctx.state.project;this.ctx.respond=!1;let r;try{r=await Or(A(e),{lenientEnv:!0})}catch(o){f(this.ctx.res,{registry:null,agents:[],listError:P(o)});return}let n=r.identity?.registry??null;if(!n){f(this.ctx.res,{registry:null,agents:[]});return}try{let o=await kt({registry:n});f(this.ctx.res,{registry:n,agents:o})}catch(o){f(this.ctx.res,{registry:n,agents:[],listError:P(o)})}}async createAgent(){let e=this.ctx.state.project,r=await k(this.ctx.req);if(this.ctx.respond=!1,!r?.name||!r.name.trim()){S(this.ctx.res,422,"INVALID_INPUT","\u667A\u80FD\u4F53\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");return}let o=(await Or(A(e),{lenientEnv:!0})).identity?.registry;if(!o){S(this.ctx.res,409,"NO_REGISTRY","\u8BE5\u9879\u76EE\u672A\u914D\u7F6E identity.registry\uFF0C\u767B\u8BB0\u8868\u7BA1\u7406\u9762\u4E0D\u53EF\u7528\u3002");return}let{recordId:i}=await It({registry:o,input:r});f(this.ctx.res,{ok:!0,recordId:i})}async listFiles(){let e=this.ctx.state.project,r=await j(e);this.ctx.respond=!1,f(this.ctx.res,{project:e,files:r})}async replaceFiles(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await k(this.ctx.req);if(this.ctx.respond=!1,!Array.isArray(o.files)){S(this.ctx.res,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");return}let i=await e.projectStore.projects.replaceFiles(n,o.files,r),a=await T(n,e);f(this.ctx.res,{project:a.project,files:i})}async patchFiles(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await k(this.ctx.req),i=await e.projectStore.projects.updateFiles(n,{upsert:o.upsert,remove:o.remove},r),a=await T(n,e);this.ctx.respond=!1,f(this.ctx.res,{project:a.project,files:i})}async exportProject(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await e.projectStore.projects.exportProject(n,r),i=yr(o),a=e.projectStore.workflows;if(a){let c=await Promise.all((await a.list(n.id,r)).map(async d=>{let p=await a.exportWorkflow(n.id,d.id,r);return{workflow:p.workflow,files:p.files}}));this.ctx.respond=!1,f(this.ctx.res,{...i,workflows:c});return}this.ctx.respond=!1,f(this.ctx.res,i)}async validate(){let e=this.ctx.state.project,r=await ts({workDir:e.dir,configPath:ne.join(e.dir,"aitable-workflow.config.yml"),workflows:[],workflowPath:ne.join(e.dir,"workflow.yml"),recipeDir:ne.join(e.dir,"recipes")});await nr(e,r),this.ctx.respond=!1,f(this.ctx.res,r)}async getWorkflow(){let e=this.ctx.state.project,r=await rs(e.dir),n=await ns(e,this.serverServices.projectStore.workflows,he(this.ctx.query?.workflowId),O(this.ctx)),o=await Rr(n,{envSource:r}).catch(()=>Rr(n)),i=ne.join(ne.dirname(n),"recipes"),a=o.steps.map(c=>({...c,requires_agent:c.recipe?ir(i,c.recipe):!!c.prompt}));this.ctx.respond=!1,f(this.ctx.res,{workflow:{...o,steps:a}})}async resetWorkflow(){let e=await Ut(this.ctx.state.project),r=await j(e);this.ctx.respond=!1,f(this.ctx.res,{project:e,files:r})}async getState(){let e=this.serverServices,r=this.ctx.state.project,n=await ke(e,r);this.ctx.respond=!1,f(this.ctx.res,n)}async updateTableId(){let e=this.serverServices;this.ctx.respond=!1,await tr(this.ctx.state.project.id,e,this.ctx.req,this.ctx.res)}};s(v,"ProjectsController"),u([Dr()],v.prototype,"ctx",2),u([Dr()],v.prototype,"serverServices",2),u([ce("/")],v.prototype,"list",1),u([me("/")],v.prototype,"create",1),u([me("/import-zip")],v.prototype,"importZip",1),u([es("/:projectId")],v.prototype,"remove",1),u([ct("/:projectId")],v.prototype,"updateMeta",1),u([me("/:projectId/init")],v.prototype,"init",1),u([ce("/:projectId/engine")],v.prototype,"getEngine",1),u([Tr("/:projectId/engine")],v.prototype,"bindEngine",1),u([ce("/:projectId/agents")],v.prototype,"getAgents",1),u([me("/:projectId/agents")],v.prototype,"createAgent",1),u([ce("/:projectId/files")],v.prototype,"listFiles",1),u([Tr("/:projectId/files")],v.prototype,"replaceFiles",1),u([ct("/:projectId/files")],v.prototype,"patchFiles",1),u([ce("/:projectId/export")],v.prototype,"exportProject",1),u([me("/:projectId/validate")],v.prototype,"validate",1),u([ce("/:projectId/workflow")],v.prototype,"getWorkflow",1),u([me("/:projectId/reset-workflow")],v.prototype,"resetWorkflow",1),u([ce("/:projectId/state")],v.prototype,"getState",1),u([ct("/:projectId/table-id")],v.prototype,"updateTableId",1),v=u([Xo("/api/projects")],v);async function ns(t,e,r,n){let o=r&&/^[A-Za-z0-9_-]+$/.test(r)?r:null;if(o&&e){let c=await e.resolve(t.id,o,n);return ne.join(t.dir,c.templatePath)}let i=await j(t);if(o){let c=`workflows/${o}/workflow.yml`;if(i.some(d=>d.path===c))return ne.join(t.dir,c)}if(i.some(c=>c.path==="workflow.yml"))return ne.join(t.dir,"workflow.yml");let a=i.find(c=>/^workflows\/[^/]+\/workflow\.ya?ml$/.test(c.path));return ne.join(t.dir,a?.path??"workflow.yml")}s(ns,"resolvePreviewWorkflowPath");import os from"path";import{Controller as ss,Del as is,Get as Ir,Inject as kr,Patch as as,Post as cs,Put as ds}from"@midwayjs/core";import{loadWorkflowTemplate as ps}from"aitable-workflow-core";var W=class{ctx;serverServices;guardNotConfigured(){return this.serverServices.projectStore.workflows?!1:(this.ctx.respond=!1,S(this.ctx.res,501,"WORKFLOWS_NOT_CONFIGURED","\u5DE5\u4F5C\u6D41\u6301\u4E45\u5316\u672A\u914D\u7F6E\uFF08\u9700\u8981 AITABLE_DB_URL\uFF09"),!0)}async list(){let e=this.serverServices,r=this.ctx.state.project;if(!e.projectStore.workflows){this.ctx.respond=!1,f(this.ctx.res,{workflows:await us(r)});return}let n=O(this.ctx);this.ctx.respond=!1,f(this.ctx.res,{workflows:await e.projectStore.workflows.list(r.id,n)})}async create(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await k(this.ctx.req);if(!o.name||!o.name.trim()){this.ctx.respond=!1,S(this.ctx.res,422,"INVALID_INPUT","\u5DE5\u4F5C\u6D41\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");return}let i=await e.projectStore.workflows.create(n.id,{name:o.name,templatePath:o.templatePath,files:o.files},r);await T(n,e);let a={workflow:i.workflow};i.files&&(a.files=i.files),i.warnings&&i.warnings.length>0&&(a.warnings=i.warnings),this.ctx.respond=!1,f(this.ctx.res,a)}async get(){let e=this.serverServices,r=this.ctx.state.project,n=this.ctx.params.workflowId??"";if(!e.projectStore.workflows){let a=await ls(r,n);if(this.ctx.respond=!1,!a){S(this.ctx.res,404,"WORKFLOW_NOT_FOUND","\u5DE5\u4F5C\u6D41\u4E0D\u5B58\u5728");return}f(this.ctx.res,a);return}let o=O(this.ctx),i=await e.projectStore.workflows.exportWorkflow(r.id,n,o);this.ctx.respond=!1,f(this.ctx.res,{workflow:i.workflow,files:i.files})}async remove(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project;if(e.runtime.runSessions.has(n.id)){this.ctx.respond=!1,S(this.ctx.res,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664\u5DE5\u4F5C\u6D41");return}let o=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r);await e.projectStore.workflows.delete(o,r),await T(n,e),this.ctx.respond=!1,f(this.ctx.res,{ok:!0,id:o.id})}async replaceFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r),i=await k(this.ctx.req);if(!Array.isArray(i.files)){this.ctx.respond=!1,S(this.ctx.res,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");return}let a=await e.projectStore.workflows.replaceFiles(o,i.files,r);await T(n,e),this.ctx.respond=!1,f(this.ctx.res,{workflow:o,files:a})}async updateFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,o=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r),i=await k(this.ctx.req),a=await e.projectStore.workflows.updateFiles(o,{upsert:i.upsert,remove:i.remove},r);await T(n,e),this.ctx.respond=!1,f(this.ctx.res,{workflow:o,files:a})}};s(W,"WorkflowsController"),u([kr()],W.prototype,"ctx",2),u([kr()],W.prototype,"serverServices",2),u([Ir("/:projectId/workflows")],W.prototype,"list",1),u([cs("/:projectId/workflows")],W.prototype,"create",1),u([Ir("/:projectId/workflows/:workflowId")],W.prototype,"get",1),u([is("/:projectId/workflows/:workflowId")],W.prototype,"remove",1),u([ds("/:projectId/workflows/:workflowId/files")],W.prototype,"replaceFiles",1),u([as("/:projectId/workflows/:workflowId/files")],W.prototype,"updateFiles",1),W=u([ss("/api/projects")],W);async function us(t){let e=await j(t),r=br(e);return(await Promise.all(r.map(o=>Fr(t,o,e)))).sort((o,i)=>o.name.localeCompare(i.name))}s(us,"listLocalWorkflows");async function ls(t,e){let r=await j(t),n=br(r).find(c=>Er(c)===e);if(!n)return null;let o=await Fr(t,n,r),i=Ar(n),a=r.filter(c=>_r(c.path,n)).map(c=>({...c,path:c.path.slice(i.length)}));return{workflow:o,files:a}}s(ls,"exportLocalWorkflow");function br(t){return t.map(e=>e.path).filter(e=>e==="workflow.yml"||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(e))}s(br,"localWorkflowTemplatePaths");function Er(t){return t==="workflow.yml"?"main":t.split("/")[1]??"main"}s(Er,"localWorkflowId");function Ar(t){return t==="workflow.yml"?"":t.replace(/workflow\.ya?ml$/,"")}s(Ar,"workflowBase");function _r(t,e){let r=Ar(e);return r?t.startsWith(r):t==="workflow.yml"||t.startsWith("recipes/")}s(_r,"belongsToWorkflow");async function Fr(t,e,r){let n=Er(e),o=await ps(os.join(t.dir,e)).catch(a=>(console.warn(`\u52A0\u8F7D\u672C\u5730\u5DE5\u4F5C\u6D41\u6A21\u677F\u5931\u8D25 [${e}]\uFF1A`,a instanceof Error?a.message:String(a)),null)),i=r.filter(a=>_r(a.path,e)).length;return{id:n,projectId:t.id,name:o?.meta.name??n,domain:o?.meta.domain,templatePath:e,tableId:o?.tracker?.table_id,fileCount:i,createdAt:t.createdAt,updatedAt:t.updatedAt}}s(Fr,"buildLocalWorkflow");import{Controller as di,Get as mt,Inject as tn,Post as ae}from"@midwayjs/core";import{logger as Wr,loadSettings as fs,runWithExecutor as ms}from"aitable-workflow-core";function Lr(t){return{appFactory:t,runSessions:new Map}}s(Lr,"createServerRuntime");async function Mr(t,e,r,n,o,i,a){let c=await b(e,t),d=a,p=n.runSessions.get(t);if(p){Nr(p,o,i);return}let w=await Y.open({project:c,stage:"run",store:r,driver:"run.local",facts:s(()=>Z(c.id,"run",{hasRunSession:s(l=>n.runSessions.has(l),"hasRunSession")}),"facts")}),m=w.state;if(m?.phase==="starting"||m?.phase==="listening"){let l="\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",D=await w.advance({phase:"failed",error:{code:"RUN_SESSION_LOST",message:l,retryable:!0}});i(o,"stage.changed",{type:"stage.changed",stage:"run",stageState:D}),i(o,"error",{type:"error",error:{code:"RUN_SESSION_LOST",message:l}}),o.end();return}let g={taskId:"",subscribers:new Set,events:[],app:null,snapshotWrite:Promise.resolve()};n.runSessions.set(t,g),Nr(g,o,i),gs(c,w,g,n,r,i,d)}s(Mr,"handleRunRuntime");async function gs(t,e,r,n,o,i,a){let c=s(d=>{Ss(r,d,i),hs(d)&&(Wr.info("run-runtime","publish run execution event",ys(d)),r.snapshotWrite=r.snapshotWrite.then(()=>o.appendRunSnapshotEvent(t,d)).catch(p=>{Wr.error("run-runtime","\u5199\u5165\u8FD0\u884C\u5FEB\u7167\u5931\u8D25",{projectId:t.id,event:d.type,error:p instanceof Error?p.message:String(p)})}))},"send");e.emit=d=>c({type:"stage.changed",stage:"run",stageState:d});try{await e.advance({phase:"starting"}),r.taskId=e.taskId??"";let d;if(a){let w;try{w=(await fs(A(t),{lenientEnv:!0})).agent.engine}catch{}d=await a.buildRunExecutor({projectId:t.id,projectDir:t.dir,agent:w})}let p=await n.appFactory(A(t),w=>c(ws(w)));r.app=p,await e.advance({phase:"listening",workflowName:p.workflow.meta.name,stepCount:p.workflow.orderedStepIds.length,intervalMs:p.settings.polling.interval_ms}),await ms(d,async()=>{await p.start()}),await e.advance({phase:"stopped",reason:"user"})}catch(d){await e.advance({phase:"failed",error:{code:Cr(d),message:Br(d),retryable:!0,details:Ur(d)}}),c({type:"error",error:Ds(d)})}finally{n.runSessions.delete(t.id),js(r)}}s(gs,"startRunSession");function ws(t){switch(t.type){case"run.agent_event":return t;case"record.observed":return{type:"run.record.detected",record:t.record};case"step.started":return{type:"run.step.started",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName};case"step.succeeded":return{type:"run.step.succeeded",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,logs:t.logs};case"step.failed":return{type:"run.step.failed",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,error:t.error,logs:t.logs};case"record.blocked":return{type:"run.record.blocked",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,reason:t.reason,logs:t.logs};case"record.completed":return{type:"run.record.completed",itemId:t.itemId}}}s(ws,"toRunEventDTO");function hs(t){return t.type.startsWith("run.record.")||t.type.startsWith("run.step.")}s(hs,"isRunExecutionEvent");function ys(t){return t.type==="run.record.detected"?{type:t.type,itemId:t.record.id,state:t.record.state,currentStep:t.record.currentStep}:t.type==="run.record.completed"?{type:t.type,itemId:t.itemId}:{type:t.type,itemId:t.itemId,stepId:t.stepId}}s(ys,"summarizeRunExecutionEvent");function Nr(t,e,r){t.subscribers.add(e);for(let n of t.events)r(e,n.type,n);e.on("close",()=>{t.subscribers.delete(e)})}s(Nr,"attachRunSubscriber");function Ss(t,e,r){t.events.push(e),xs(t.events);for(let n of t.subscribers){if(n.destroyed||n.writableEnded){t.subscribers.delete(n);continue}try{r(n,e.type,e)}catch{t.subscribers.delete(n)}}}s(Ss,"publishRunEvent");var vs=100,Ps=60;function xs(t){let e=0;for(let r of t)r.type==="run.agent_event"&&(e+=1);for(;e>Ps;){let r=t.findIndex(n=>n.type==="run.agent_event");if(r<0)break;t.splice(r,1),e-=1}for(;t.length>vs;)t.shift()}s(xs,"trimRunReplayEvents");function js(t){for(let e of t.subscribers)e.end();t.subscribers.clear()}s(js,"closeRunSubscribers");function Ds(t){return{code:Cr(t),message:Br(t),details:Ur(t)}}s(Ds,"apiError");function Cr(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}s(Cr,"errorCode");function Br(t){return t instanceof Error?t.message:String(t)}s(Br,"errorMessage");function Ur(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}s(Ur,"errorDetails");function Ts(){let t=process.env.AITABLE_WORKFLOW_SSE_HEARTBEAT_MS,e=typeof t=="string"?t.trim():"";if(!e)return 15e3;let r=Number.parseInt(e,10);return Number.isFinite(r)&&r>0?r:15e3}s(Ts,"readSseHeartbeatMs");function de(t){t.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),Rs(t)}s(de,"startSse");function Rs(t){let e=Ts(),r=setInterval(()=>{if(t.writableEnded||!t.writable){clearInterval(r);return}try{t.write(`:keepalive
10
+ `)}o(at,"writeDesignSse");function Jt(t,e){let r=t.buffer.push(e);for(let n of t.subscribers){if(n.destroyed||n.writableEnded){t.subscribers.delete(n);continue}try{at(n,r.seq,e)}catch{t.subscribers.delete(n)}}}o(Jt,"publishDesignEvent");function Vt(t){he.delete(t);let e=ne.get(t);if(ne.delete(t),!!e){for(me.delete(t),me.set(t,e.buffer);me.size>ns;){let r=me.keys().next();if(r.done)break;me.delete(r.value)}for(let r of e.subscribers)if(!r.writableEnded)try{r.end()}catch{}e.subscribers.clear()}}o(Vt,"closeDesignSession");function Ht(t,e){let r=t.searchParams.get("cursor")??Rt(e.headers["last-event-id"]);if(r==null||r==="")return;let n=Number(r);return Number.isFinite(n)?n:void 0}o(Ht,"parseReconnectCursor");function K(t,e,r){if(e==="design"){let n=ne.get(t);return n?{sessionLocal:!0,cursor:n.buffer.cursor}:{sessionLocal:!1}}return e==="run"?{sessionLocal:r.hasRunSession(t)}:{sessionLocal:!1}}o(K,"stageFactsFor");function zt(t,e){return cs(t,(r,n)=>is({projectId:t.projectId,stage:r,state:n.state,facts:K(t.projectId,r,e)}))}o(zt,"decorateProjectState");async function ke(t,e){let r=await t.projectStore.instances.getRecoverableState(e),n=await ps(t,e,r),s={hasRunSession:o(c=>t.runtime.runSessions.has(c),"hasRunSession")},a=t.execution.runScheduler;if(!a||s.hasRunSession(e.id))return zt(n,s);let i=await a.getStatus(e.id).catch(()=>null);return zt(i?ls(n,i):n,s)}o(ke,"readProjectState");async function ps(t,e,r){if(r.stages.init||!await Promise.all([Gt(_(e)),Gt(us.join(e.dir,"workflow.yml"))]).then(i=>i.some(Boolean)))return r;let s=new Date().toISOString(),a=as("init",null,{phase:"ready",warnings:[],roleFiles:[]},"system");return await t.projectStore.instances.putStageState(e,"init",{identity:{id:`init_import_${e.id}`,projectId:e.id,stage:"init",attempt:1,startedAt:e.createdAt||s,updatedAt:s,completedAt:s},state:a})}o(ps,"backfillImportedInit");function ls(t,e){let r=ss(e),n=t.stages.run;if(!n&&r.phase==="stopped")return t;let s=new Date().toISOString();return os(t,"run",{identity:n?.identity??{id:`run_relay_${t.projectId}`,projectId:t.projectId,stage:"run",attempt:1,startedAt:e.lastHeartbeatAt??s,updatedAt:s},state:r})}o(ls,"injectRelayRunState");function Gt(t){return ds(t).then(()=>!0,()=>!1)}o(Gt,"fileExists");function Qt(t){return{appFactory:t,runSessions:new Map}}o(Qt,"createServerRuntime");async function Xt(t,e,r,n,s,a,i,c){let d=await I(e,t),u=i,w=n.runSessions.get(t);if(w){Zt(w,s,a);return}let m=await G.open({project:d,stage:"run",store:r,driver:"run.local",facts:o(()=>K(d.id,"run",{hasRunSession:o(y=>n.runSessions.has(y),"hasRunSession")}),"facts")}),l=m.state;if(l?.phase==="starting"||l?.phase==="listening"){let y="\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",E=await m.advance({phase:"failed",error:{code:"RUN_SESSION_LOST",message:y,retryable:!0},runMode:l.runMode});a(s,"stage.changed",{type:"stage.changed",stage:"run",stageState:E}),a(s,"error",{type:"error",error:{code:"RUN_SESSION_LOST",message:y}}),s.end();return}let f={taskId:"",eventSequence:0,subscribers:new Set,events:[],app:null,snapshotWrite:Promise.resolve()};n.runSessions.set(t,f),Zt(f,s,a),ws(d,m,f,n,r,a,u,c)}o(Xt,"handleRunRuntime");async function ws(t,e,r,n,s,a,i,c){let d={mode:ye(c)??"local"},u=o(w=>{let m=Ds(w,d),l=Yt(m)?{...m,eventId:`${r.taskId}:${++r.eventSequence}`}:m;Ss(r,l,a),Yt(l)&&(Kt.info("run-runtime","publish run execution event",ys(l)),r.snapshotWrite=r.snapshotWrite.then(()=>s.appendRunSnapshotEvent(t,l)).catch(f=>{Kt.error("run-runtime","\u5199\u5165\u8FD0\u884C\u5FEB\u7167\u5931\u8D25",{projectId:t.id,event:l.type,error:f instanceof Error?f.message:String(f)})}))},"send");e.emit=w=>u({type:"stage.changed",stage:"run",stageState:w});try{await s.resetRunEvents?.(t.id),await e.advance({phase:"starting",runMode:ye(c)}),r.taskId=e.taskId??"";let w;if(i){let f;try{f=(await fs(_(t),{lenientEnv:!0})).agent.engine}catch{}if(f&&(d={...d,agent:f}),c==="server-run-relay-agent"||c==="server-run-relay-recipe")try{let y=await i.getProjectMachine(t.id);y&&(d={...d,machineId:y})}catch{}w=await i.buildRunExecutor({projectId:t.id,projectDir:t.dir,agent:f})}let m;if(i&&c==="server-run-relay-recipe"){if(!i.buildRunRecipeRunner)throw Object.assign(new Error("\u5F53\u524D\u6267\u884C\u9762\u4E0D\u652F\u6301 runMode=server-run-relay-recipe\uFF08\u7F3A\u5C11 RecipeRunner\uFF09"),{code:"RECIPE_TRANSPORT_REQUIRED",status:500});m=await i.buildRunRecipeRunner({projectId:t.id,projectDir:t.dir})}let l=await n.appFactory(_(t),f=>u(hs(f)));r.app=l,await e.advance({phase:"listening",workflowName:l.workflow.meta.name,stepCount:l.workflow.orderedStepIds.length,intervalMs:l.settings.polling.interval_ms,runMode:ye(c)}),await ms(w,async()=>{await gs(m,async()=>{await l.start()})}),await e.advance({phase:"stopped",reason:"user",runMode:ye(c)})}catch(w){await e.advance({phase:"failed",error:{code:er(w),message:tr(w),retryable:!0,details:rr(w)},runMode:ye(c)}),u({type:"error",error:js(w)})}finally{n.runSessions.delete(t.id),Rs(r)}}o(ws,"startRunSession");function hs(t){switch(t.type){case"run.agent_event":return t;case"record.observed":return{type:"run.record.detected",record:t.record};case"step.started":return{type:"run.step.started",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName};case"step.succeeded":return{type:"run.step.succeeded",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,logs:t.logs};case"step.failed":return{type:"run.step.failed",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,error:t.error,logs:t.logs};case"record.blocked":return{type:"run.record.blocked",itemId:t.itemId,stepId:t.stepId,stepName:t.stepName,reason:t.reason,logs:t.logs};case"record.completed":return{type:"run.record.completed",itemId:t.itemId}}}o(hs,"toRunEventDTO");function Yt(t){return t.type.startsWith("run.record.")||t.type.startsWith("run.step.")}o(Yt,"isRunExecutionEvent");function ys(t){return t.type==="run.record.detected"?{type:t.type,itemId:t.record.id,state:t.record.state,currentStep:t.record.currentStep}:t.type==="run.record.completed"?{type:t.type,itemId:t.itemId}:{type:t.type,itemId:t.itemId,stepId:t.stepId}}o(ys,"summarizeRunExecutionEvent");function Zt(t,e,r){t.subscribers.add(e);for(let n of t.events)r(e,n.type,n);e.on("close",()=>{t.subscribers.delete(e)})}o(Zt,"attachRunSubscriber");function Ss(t,e,r){t.events.push(e),xs(t.events);for(let n of t.subscribers){if(n.destroyed||n.writableEnded){t.subscribers.delete(n);continue}try{r(n,e.type,e)}catch{t.subscribers.delete(n)}}}o(Ss,"publishRunEvent");var vs=100,Ps=60;function xs(t){let e=0;for(let r of t)r.type==="run.agent_event"&&(e+=1);for(;e>Ps;){let r=t.findIndex(n=>n.type==="run.agent_event");if(r<0)break;t.splice(r,1),e-=1}for(;t.length>vs;)t.shift()}o(xs,"trimRunReplayEvents");function Rs(t){for(let e of t.subscribers)e.end();t.subscribers.clear()}o(Rs,"closeRunSubscribers");function Ds(t,e){return t.type==="stage.changed"||t.type==="error"?t:{...t,at:new Date().toISOString(),engine:e}}o(Ds,"stampRunEvent");function ye(t){return t==="workflow-pull-claim"?void 0:t}o(ye,"toLocalRunMode");function js(t){return{code:er(t),message:tr(t),details:rr(t)}}o(js,"apiError");function er(t){return typeof t=="object"&&t!==null&&"code"in t&&typeof t.code=="string"?t.code:"INTERNAL_ERROR"}o(er,"errorCode");function tr(t){return t instanceof Error?t.message:String(t)}o(tr,"errorMessage");function rr(t){if(typeof t=="object"&&t!==null&&"details"in t)return t.details}o(rr,"errorDetails");function Ts(){let t=process.env.AITABLE_WORKFLOW_SSE_HEARTBEAT_MS,e=typeof t=="string"?t.trim():"";if(!e)return 15e3;let r=Number.parseInt(e,10);return Number.isFinite(r)&&r>0?r:15e3}o(Ts,"readSseHeartbeatMs");function ae(t){t.writeHead(200,{"content-type":"text/event-stream; charset=utf-8","cache-control":"no-cache, no-transform",connection:"keep-alive"}),Os(t)}o(ae,"startSse");function Os(t){let e=Ts(),r=setInterval(()=>{if(t.writableEnded||!t.writable){clearInterval(r);return}try{t.write(`:keepalive
12
11
 
13
- `)}catch{clearInterval(r)}},e);r.unref?.();let n=s(()=>clearInterval(r),"stop");t.on("close",n),t.on("finish",n)}s(Rs,"startSseHeartbeat");function Ae(t,e,r){t.write(`event: ${e}
12
+ `)}catch{clearInterval(r)}},e);r.unref?.();let n=o(()=>clearInterval(r),"stop");t.on("close",n),t.on("finish",n)}o(Os,"startSseHeartbeat");function Ee(t,e,r){t.write(`event: ${e}
14
13
  `),t.write(`data: ${JSON.stringify(r)}
15
14
 
16
- `)}s(Ae,"writeSse");var dt=class{constructor(e){this.services=e}services;static{s(this,"LocalRunController")}mode="local";async start(e,r){de(r),await Mr(e,this.services.workspace,this.services.projectStore.instances,this.services.runtime,r,Ae,this.services.execution)}async stop(e){let r=this.services.runtime.runSessions.get(e);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(e){let r=this.services.runtime.runSessions.get(e);return{mode:this.mode,running:r!=null,taskId:r?.taskId??null}}async listRecords(e,r){let n=await b(this.services.workspace,e),i=(await this.services.projectStore.instances.getState(n)).runSnapshot?.records??[],a=r?.limit??100;return{items:[...i].sort((d,p)=>p.updatedAt-d.updatedAt).slice(0,a).map(d=>({itemId:d.id,title:d.title,state:d.state,currentStepId:d.currentStepId,doneStepIds:d.doneStepIds,completedAt:d.status==="done"?new Date(d.updatedAt).toISOString():null,updatedAt:new Date(d.updatedAt).toISOString(),status:d.status})),counts:{total:i.length,completed:i.filter(d=>d.status==="done").length}}}},pt=class{constructor(e,r){this.scheduler=e;this.records=r}scheduler;records;static{s(this,"RelayRunController")}mode="relay";async start(e,r){f(r,{mode:this.mode,action:"start",schedule:await this.scheduler.start(e)})}async stop(e){return{mode:this.mode,action:"stop",schedule:await this.scheduler.stop(e)}}async status(e){return{mode:this.mode,action:"status",schedule:await this.scheduler.getStatus(e)}}async listRecords(e,r){return this.records?this.records.listRecords(e,r):{items:[],counts:{total:0,completed:0}}}},$r=["server-run-relay-agent","workflow-pull-claim"];function qr(t){if(t!=null){if($r.includes(t))return t;throw Object.assign(new Error(`\u8BF7\u6C42\u4F53 runMode \u975E\u6CD5\u503C "${String(t)}"\uFF1B\u8BF7\u6C42\u7EA7\u8986\u76D6\u4EC5\u652F\u6301 ${$r.join(" | ")}`),{code:"INVALID_RUN_MODE",status:400})}}s(qr,"parseRequestedRunMode");async function Os(t,e){let r=await t.getStatus(e);return r.desiredState==="running"||r.machineId!=null}s(Os,"hasActiveLease");async function ge(t,e,r){let{execution:n}=t,o=s(()=>{if(!n.runScheduler)throw Object.assign(new Error("runMode=workflow-pull-claim requires execution.runScheduler"),{code:"RUN_SCHEDULER_REQUIRED",status:500});return new pt(n.runScheduler,n.runRecords)},"relayController"),i=r??n.runMode;if(i!=="workflow-pull-claim"&&e&&n.runScheduler&&await Os(n.runScheduler,e)){if(r==="server-run-relay-agent")throw Object.assign(new Error(`\u9879\u76EE ${e} \u5B58\u5728\u6D3B\u8DC3 workflow \u79DF\u7EA6\uFF08daemon \u8BA4\u9886\u6267\u884C\u4E2D\uFF09\uFF0C\u4E0D\u80FD\u5207\u4E3A\u8FDB\u7A0B\u5185\u6267\u884C\uFF1B\u5148 POST /run/stop \u91CA\u653E\u79DF\u7EA6`),{code:"RUN_LEASE_ACTIVE",status:409});return o()}if(e&&r==="workflow-pull-claim"&&t.runtime.runSessions.has(e))throw Object.assign(new Error(`\u9879\u76EE ${e} \u5728\u670D\u52A1\u7AEF\u8FDB\u7A0B\u5185\u6709 run \u4F1A\u8BDD\uFF0C\u5148\u505C\u6B62\u518D\u6309 workflow-pull-claim \u4E0B\u53D1`),{code:"RUN_SESSION_ACTIVE",status:409});return i==="workflow-pull-claim"?o():new dt(t)}s(ge,"resolveRunController");import{collectDesignContext as Jr,runDesign as Is,runClarifyRound as ks,syncFieldsFromWorkflow as bs,summarizeForms as Es,validateFormAnswers as As,pruneHiddenAnswers as _s,nextFor as Fs,isDesignGenerating as Hr,logger as Fe}from"aitable-workflow-core";var _e=class{static{s(this,"DesignEventBuffer")}capacity;events=[];seq=0;constructor(e=100){this.capacity=e>0?e:100}push(e){this.seq+=1;let r={seq:this.seq,event:e};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(e){return e===void 0||Number.isNaN(e)?[...this.events]:this.events.filter(r=>r.seq>e)}};var Vr={hasRunSession:s(()=>!1,"hasRunSession")};async function Ws(t,e,r){return{...(await e.getState(t)).stages.design,state:r,next:Fs({projectId:t.id,stage:"design",state:r,facts:Z(t.id,"design",Vr)})}}s(Ws,"currentEntry");function ut(t,e,r){return Y.open({project:t,stage:"design",store:e,driver:r,facts:s(()=>Z(t.id,"design",Vr),"facts")})}s(ut,"designWriter");async function Gr(t,e,r,n,o){let i=await b(e,t),a=await ut(i,r,"design.discovery"),c=a.state;if(Hr(c)){S(n,409,"DESIGN_IN_PROGRESS","\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u6B63\u5728\u751F\u6210\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F\u518D\u91CD\u65B0\u6F84\u6E05\u9700\u6C42\u3002");return}try{await a.advance({phase:"clarify_probing"});let d=await Jr({configPath:A(i),yes:!0}),p=d.agentType?await ks(d,{...await Kr(o,i,d.agentType),timeoutMs:d.agentTimeoutMs,interactive:!0,judgeOnly:!0}):void 0;if(!p?.form){let m=d.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",g=await a.advance({phase:"precheck",confirmed:{form:{id:"clarify",title:"\u65E0\u9700\u6F84\u6E05",questions:[]},answers:{},clarifications:m,summary:m,...p?.sessionId?{agentSessionId:p.sessionId}:{}}});f(n,{stageState:g});return}let w=await a.advance({phase:"clarify_awaiting",form:p.form,answers:Ns(p.form),...p.sessionId?{agentSessionId:p.sessionId}:{}});f(n,{stageState:w})}catch(d){let p=await a.advance({phase:"clarify_failed",error:{code:"DESIGN_PRECHECK_FAILED",message:P(d),retryable:!0,details:$(d)}});f(n,{stageState:p,error:pe(d)},500)}}s(Gr,"handleDesignDiscovery");async function Kr(t,e,r){let n=await t.buildDesignExecutor({projectId:e.id,agent:r,projectDir:e.dir});return n?{executor:n}:{}}s(Kr,"relayExecutorFor");function Ns(t){let e=Object.fromEntries(t.questions.map(r=>[r.id,r.defaultValue??(r.type==="checkbox"?[]:"")]));return _s(t,e)}s(Ns,"seedAnswers");async function Yr(t,e,r,n,o){let i=await b(e,t),a=await ut(i,r,"design.discovery"),c=a.state;if(Hr(c)){f(o,{stageState:await Ws(i,r,c)});return}if(c?.phase!=="clarify_awaiting"){S(o,409,"DISCOVERY_NOT_READY","\u8BF7\u5148\u751F\u6210\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u786E\u8BA4 Design \u8F93\u5165\u3002");return}let d=n.answers,p=d&&Object.keys(d).length>0?d:c.answers,w=As(c.form,p);if(w.length>0){S(o,400,"DISCOVERY_INVALID_ANSWERS",`\u9700\u6C42\u6F84\u6E05\u7B54\u6848\u4E0D\u5B8C\u6574\uFF1A${w.map(l=>l.message).join("\uFF1B")}`,{issues:w});return}let m=Es([{form:c.form,answers:p}]),g=await a.advance({phase:"precheck",confirmed:{form:c.form,answers:p,clarifications:m,summary:m.replace(/\s+/g," ").trim(),...c.agentSessionId?{agentSessionId:c.agentSessionId}:{}}});f(o,{stageState:g})}s(Yr,"handleDesignDiscoveryConfirm");function Zr(t,e){let r=bt(t);if(!r){f(e,{events:[],lastSeq:0,live:!1,retained:!1});return}let n=r.buffer.replayAfter(void 0);f(e,{events:n.map(o=>o.event),lastSeq:r.buffer.cursor,live:r.live,retained:!0})}s(Zr,"handleDesignEventLog");async function Qr(t,e,r,n,o,i){let a=await b(e,t);try{o.ensureAvailable()}catch(y){S(n,ee(y),F(y),P(y));return}let c=ie.get(a.id);if(c){de(n);for(let y of c.buffer.replayAfter(i))Qe(n,y.seq,y.event);c.subscribers.add(n),n.on("close",()=>c.subscribers.delete(n));return}let d=await ut(a,r,"design.stream"),p=d.state;if(!(p?.phase==="precheck"||p?.phase==="generating"||p?.phase==="validating"||p?.phase==="syncing_schema")&&p?.phase!=="generate_failed"){S(n,409,p?.phase==="clarify_awaiting"?"DISCOVERY_NOT_CONFIRMED":"DESIGN_NOT_READY",p?.phase==="clarify_awaiting"?"\u8BF7\u5148\u786E\u8BA4\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002":"\u8BF7\u5148\u5B8C\u6210\u9700\u6C42\u6F84\u6E05\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002");return}let m=p.confirmed;Se.add(a.id),de(n);let g={buffer:new _e,subscribers:new Set([n])};ie.set(a.id,g),n.on("close",()=>g.subscribers.delete(n));let l=s(y=>Et(g,y),"send");d.emit=y=>l({type:"stage.changed",stage:"design",stageState:y});let D=Date.now(),E=D,I=0,B=[],U=[],_=s((y,N)=>{let L=Date.now(),J=L-D,H=L-E;E=L,B.push({label:y,at:new Date(L).toISOString(),elapsedMs:J,...N?{detail:N}:{}}),B.length>40&&B.shift(),d.setDiagnostics({timeline:B,recentAgentEvents:U}),Fe.info("design-runtime",y,{projectId:a.id,taskId:d.taskId,elapsedMs:J,deltaMs:H,...N?{detail:N}:{}})},"trace"),Te="",q=!1,Q=!1,z=s(async()=>{if(q){Q=!0;return}q=!0;try{do{Q=!1;let N=(await j(a)).filter(L=>L.path!=="project.json").map(L=>`${L.path}:${L.content}`).join("|");if(N&&N!==Te){Te=N;let L=await C(a),J=await j(L);_(`\u540C\u6B65 ${J.length} \u4E2A\u751F\u6210\u6587\u4EF6`,{fileCount:J.length}),l({type:"design.files",files:J})}}while(Q)}finally{q=!1}},"sendFileSnapshot");try{d.state&&d.state.phase!=="precheck"&&(d.state.phase!=="generate_failed"&&await d.advance({phase:"generate_failed",confirmed:m,error:{code:"DESIGN_SESSION_LOST",message:"\u4E0A\u4E00\u6B21\u751F\u6210\u7684\u8FDB\u7A0B\u5DF2\u7ED3\u675F\uFF08\u670D\u52A1\u91CD\u542F\u6216\u591A\u5B9E\u4F8B\uFF09\uFF0C\u672C\u6B21\u91CD\u65B0\u5F00\u59CB\u751F\u6210\u3002",retryable:!0}}),await d.advance({phase:"precheck",confirmed:m})),await z();let y,N;try{_("\u8BFB\u53D6 Design \u914D\u7F6E"),N=A(a),y=await Jr({configPath:N,yes:!0}),_("Design \u914D\u7F6E\u8BFB\u53D6\u5B8C\u6210",{agent:y.agentType,timeoutMs:y.agentTimeoutMs})}catch(h){await d.advance({phase:"generate_failed",confirmed:m,error:{code:"DESIGN_PRECHECK_FAILED",message:P(h),retryable:!0,details:$(h)}}),l({type:"error",error:pe(h)}),n.end();return}y.clarifications=m.clarifications,_("\u542F\u52A8 Coding Agent \u751F\u6210\u6D41\u7A0B\u65B9\u6848",{agent:y.agentType,timeoutSource:"disabled"});let L=!1,J=s(h=>{Fe.warn("design-runtime","\u9636\u6BB5\u72B6\u6001\u5199\u5165\u5931\u8D25",{projectId:a.id,error:P(h)})},"onDetachedError"),H=await Is(y,{...await Kr(o,a,y.agentType),...m.agentSessionId?{resume:{sessionId:m.agentSessionId,answered:[{form:m.form,answers:m.answers}]}}:{},timeoutMs:null,onRoundStart:s((h,oe)=>{_(`\u7B2C ${h} \u8F6E ${oe?"\u4FEE\u6B63":"\u751F\u6210"}\u5F00\u59CB`,{round:h,isFix:oe}),d.advanceDetached({phase:"generating",confirmed:m,round:h,isFix:oe},J)},"onRoundStart"),onEvent:s(h=>{Ls(h)&&(U.push(Ms(h)),U.length>30&&U.shift(),L||(L=!0,_(`\u6536\u5230 Agent \u9996\u4E2A\u4E8B\u4EF6\uFF1A${h.type}`,{eventType:h.type})),h.type==="tool_use"&&_("Agent \u8C03\u7528\u5DE5\u5177",{toolName:h.toolName}),(h.type==="text"||h.type==="thinking")&&Date.now()-I>5e3&&(I=Date.now(),_(h.type==="thinking"?"Agent \u6B63\u5728\u63A8\u7406":"Agent \u8F93\u51FA\u5185\u5BB9",{eventType:h.type,preview:h.content?.replace(/\s+/g," ").slice(0,120)})),l({type:"design.agent_event",event:h}),(h.type==="tool_use"||h.type==="tool_result")&&z())},"onEvent"),onAgentLifecycle:s(h=>{_(Cs(h),Bs(h))},"onAgentLifecycle"),onValidationStart:s(h=>{_("\u5F00\u59CB\u6821\u9A8C\u6D41\u7A0B\u65B9\u6848\u914D\u7F6E",{round:h}),d.advanceDetached({phase:"validating",confirmed:m,round:h,errors:[]},J)},"onValidationStart"),onValidation:s((h,oe)=>{_(h.valid?"\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u901A\u8FC7":`\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u53D1\u73B0 ${h.errors.length} \u4E2A\u95EE\u9898`,{round:oe,valid:h.valid,errorCount:h.errors.length}),d.setDiagnostics({timeline:B,recentAgentEvents:U,validation:h}),d.advanceDetached({phase:"validating",confirmed:m,round:oe,errors:h.errors},J),z()},"onValidation")});if(!H.success){await z(),d.setDiagnostics({timeline:B,recentAgentEvents:U,...H.validation?{validation:H.validation}:{}}),await d.advance({phase:"generate_failed",confirmed:m,error:{code:"DESIGN_VALIDATION_FAILED",message:H.response,retryable:!0}}),await zr(a,d,H.response),n.end();return}await d.advance({phase:"syncing_schema",confirmed:m}),_("\u540C\u6B65\u5B57\u6BB5\u8BA1\u5212\u5230\u914D\u7F6E");for(let h of y.workflows)await bs({workflowPath:h.workflowPath,configPath:N,autoUpdate:!0}).catch(oe=>(Fe.warn("design","\u5B57\u6BB5\u540C\u6B65\u5931\u8D25(\u4E0D\u963B\u65AD)",{workflow:h.id,error:P(oe)}),null));await z(),_("\u5199\u5165 Design \u4EA7\u7269\u6E05\u5355");let gn=await j(a),wt=Us(a,d,gn);await ot(a,wt),d.setDiagnostics({timeline:B,recentAgentEvents:U,...H.validation?{validation:H.validation}:{}}),await d.advance({phase:"ready",confirmed:m,manifest:wt,rounds:H.rounds}),n.end()}catch(y){await z().catch(()=>{}),d.setDiagnostics({timeline:B,recentAgentEvents:U}),await d.advance({phase:"generate_failed",confirmed:m,error:{code:F(y)==="INTERNAL_ERROR"?"DESIGN_GENERATION_FAILED":F(y),message:P(y),retryable:!0,details:$(y)}}).catch(N=>{Fe.warn("design-runtime","\u5199\u5165\u5931\u8D25\u72B6\u6001\u672A\u6210\u529F",{error:P(N)})}),await zr(a,d,P(y)).catch(()=>{}),l({type:"error",error:pe(y)}),n.end()}finally{At(a.id)}}s(Qr,"handleDesign");function Ls(t){return t.type!=="text"&&t.type!=="thinking"?!0:typeof t.content=="string"&&t.content.trim().length>0}s(Ls,"isDisplayableAgentEvent");function Ms(t){return t.type==="tool_use"?{type:t.type,toolName:t.toolName,toolInput:t.toolInput}:t.type==="tool_result"||t.type==="error"||t.type==="text"||t.type==="thinking"?{type:t.type,content:t.content?.replace(/\s+/g," ").slice(0,240)}:{type:t.type}}s(Ms,"summarizeAgentEvent");function Cs(t){switch(t.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(Cs,"agentLifecycleMessage");function Bs(t){return{provider:t.provider,phase:t.phase,elapsedMs:t.elapsedMs,...t.pid?{pid:t.pid}:{},...t.cmd?{cmd:t.cmd}:{},...t.cwd?{cwd:t.cwd}:{},...t.exitCode!==void 0?{exitCode:t.exitCode}:{}}}s(Bs,"sanitizeAgentLifecycle");function Us(t,e,r){let n=r.filter(a=>$s(a.path)).map(a=>({path:a.path,kind:qs(a.path),checksum:Pe(a.content),required:zs(a.path)})),o=n.filter(a=>a.required).map(a=>a.path),i=new Date().toISOString();return{projectId:t.id,taskId:e.taskId??"",designVersion:e.attempt,status:"ready",expected:o,generated:n,validation:{passed:!0,errors:[],warnings:[]},createdAt:e.startedAt??i,updatedAt:i}}s(Us,"buildDesignManifest");function $s(t){return t==="workflow.yml"||t.startsWith("recipes/")||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(t)||/^workflows\/[^/]+\/recipes\/.+\.(ts|js)$/.test(t)}s($s,"isDesignArtifactPath");function qs(t){return t.endsWith("workflow.yml")||t.endsWith("workflow.yaml")?"workflow":"recipe"}s(qs,"designArtifactKind");function zs(t){return!0}s(zs,"isRequiredDesignArtifact");async function zr(t,e,r){let n=new Date().toISOString();await ot(t,{projectId:t.id,taskId:e.taskId??"",designVersion:e.attempt,status:"invalid",expected:["workflow.yml"],generated:[],validation:{passed:!1,errors:[r],warnings:[]},createdAt:e.startedAt??n,updatedAt:n})}s(zr,"writeInvalidDesignManifest");import{loadSettings as en,resolveConfigPath as Qs,loadWorkflowTemplate as Xs,initTable as ei,ensureBaseExists as ti,ensureTableExists as ri,resolveWorkflowTracker as ni,runWithExecutor as oi,runWithDwsRunner as si,DwsError as ii,logger as ai}from"aitable-workflow-core";var Js={singleSelect:"single_select",multipleSelect:"multiple_select",date:"datetime"},Hs={Grid:"grid",FormDesigner:"form",Kanban:"kanban",Calendar:"calendar",Gantt:"gantt"};function Xr(t,e){let r=new Map,n=new Map((t.tracker.field_definitions??[]).map(c=>[c.name,c])),o=s((c,d,p="text",w)=>{if(!c?.trim()||r.has(c))return;let m=n.get(c);r.set(c,{id:Ys(c),name:c,type:Ks(m?.type??p),...m?.options??w?{options:m?.options??w}:{},group:d})},"addField");for(let c of e.referencedFields.userInput)o(c,"business");for(let c of e.referencedFields.output)o(c,"business");for(let c of e.referencedFields.other)o(c,"business");for(let c of t.tracker.field_definitions??[])o(c.name,"business",c.type,c.options);o(t.tracker.fields.title,"business"),o(t.tracker.fields.description,"business"),o(t.tracker.fields.state,"process","singleSelect",Gs(t)),o(t.tracker.fields.current_step,"process"),o(t.tracker.fields.owner,"process","user"),o(t.tracker.fields.deadline,"process","date"),o(t.tracker.fields.event_log,"process");let i=Vs(t.tracker.views??[],e).map(c=>({id:c.id,name:c.name,kind:Hs[c.type]??"grid",desc:c.description??Zs(c)})),a=[...r.values()];return{fieldCount:a.length,viewCount:i.length,fields:a,views:i}}s(Xr,"buildSetupSchemaSummary");function Vs(t,e){let r=[],n=2;for(let o of t){if(!o.for_each_step){r.push(o);continue}let i=e.steps.filter(a=>o.for_each_step==="needs_human"?!!a.needs_human:!0);for(let a of i){let c=String.fromCodePoint(9311+n);r.push({...o,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??o.description,for_each_step:void 0}),n++}}return r}s(Vs,"expandViews");function Gs(t){return[t.tracker.states.initial,...t.tracker.states.active,...t.tracker.states.terminal,t.tracker.states.blocked,t.tracker.states.review].filter((e,r,n)=>!!e&&n.indexOf(e)===r)}s(Gs,"stateOptions");function Ks(t){return Js[t]??t}s(Ks,"displayFieldType");function Ys(t){return`fld_${t.replace(/[^\p{L}\p{N}]+/gu,"_").replace(/^_+|_+$/g,"")||"field"}`}s(Ys,"fieldId");function Zs(t){return t.type==="FormDesigner"?"\u8868\u5355\u5F55\u5165\u89C6\u56FE":t.type==="Kanban"?t.group_by?`\u6309 ${t.group_by} \u5206\u7EC4`:"\u770B\u677F\u89C6\u56FE":t.type==="Calendar"?t.date_field?`\u6309 ${t.date_field} \u67E5\u770B`:"\u65E5\u5386\u89C6\u56FE":t.type==="Gantt"?"\u7518\u7279\u89C6\u56FE":"\u8868\u683C\u89C6\u56FE"}s(Zs,"viewDescription");var lt=new Set;async function ft(t,e,r,n,o){let i=await b(e,t);try{o.ensureAvailable()}catch(g){S(n,ee(g),F(g),P(g));return}if(lt.has(i.id)){S(n,409,"SETUP_IN_PROGRESS","AI \u8868\u683C\u642D\u5EFA\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019\u3002");return}let a=await Y.open({project:i,stage:"setup",store:r,driver:"setup.stream",facts:s(()=>Z(i.id,"setup",{hasRunSession:s(()=>!1,"hasRunSession")}),"facts")});lt.add(i.id),de(n);let c=s(g=>Ae(n,g.type,g),"send");a.emit=g=>c({type:"stage.changed",stage:"setup",stageState:g});let d=s((g,l)=>{ai.info("setup",g,{projectId:i.id,taskId:a.taskId,...l?{detail:l}:{}})},"trace"),p=[],w=o.buildSetupExecutor({projectId:i.id,projectDir:i.dir}),m=o.buildDwsRunner();try{await oi(w,async()=>{await si(m,async()=>{await a.advance({phase:"preflight"}),d("\u52A0\u8F7D\u914D\u7F6E\u4E0E\u5DE5\u4F5C\u6D41\u6A21\u677F");let g=A(i),l=await en(g,{lenientEnv:!0});if(l.multiWorkflow||l.tracker.base_id!=="__placeholder__"){let q=await ti({configPath:g,settings:l,onProgress:s((Q,z)=>d(Q,{checkpoint:z}),"onProgress")});l.tracker.base_id!==q.baseId&&(l=await en(g,{lenientEnv:!0})),d("AI \u8868\u683C Base \u5DF2\u786E\u8BA4",{baseId:q.baseId})}let E=await Xs(l.workflowTemplatePath,{envSource:l.envSource}),I=ni(l,E.tracker);if(!I)throw new Error("\u5F53\u524D\u5DE5\u4F5C\u6D41\u7F3A\u5C11 tracker \u914D\u7F6E\uFF08config.yml \u4E0E workflow.yml \u5747\u672A\u63D0\u4F9B\uFF09");let B=I===l.tracker?l:{...l,tracker:I},U=!I.table_id.trim();if(U){await a.advance({phase:"provisioning_table"});let q=I===l.tracker?await Qs(A(i)):l.workflowTemplatePath,Q=await ri({trackerFilePath:q,settings:B,workflow:E,onProgress:s((z,y)=>d(z,{checkpoint:y}),"onProgress")});B=Q,I=Q.tracker,l={...l,tracker:Q.tracker}}await a.advance({phase:"syncing_schema",warnings:[]}),d("\u5F00\u59CB\u521B\u5EFA\u5B57\u6BB5\u548C\u89C6\u56FE");let _=await ei({settings:B,workflow:E,cleanEmptyRows:!0,tableJustCreated:U});p.push(..._.warnings.map(q=>q.message));let Te=Xr(B,E);await C(i),await a.advance({phase:"ready",tableUrl:qt(I.base_id,I.table_id),baseId:I.base_id,tableId:I.table_id,schema:Te,warnings:p}),n.end()})})}catch(g){if(ci(g)){await a.advance({phase:"auth_awaiting",error:{code:"SETUP_AUTH_REQUIRED",message:`\u6388\u6743\u6216\u6743\u9650\u4E0D\u8DB3\uFF1A${P(g)}`,retryable:!0,details:{help:"\u8BF7\u6267\u884C dws auth login\uFF0C\u5E76\u786E\u8BA4\u5F53\u524D\u8D26\u53F7\u53EF\u8BBF\u95EE\u76EE\u6807 Base/Table\u3002"}}}),n.end();return}await a.advance({phase:"failed",error:{code:F(g),message:P(g),retryable:!0,details:$(g)}}),c({type:"error",error:pe(g)}),n.end()}finally{lt.delete(i.id)}}s(ft,"handleSetup");function ci(t){let e=P(t).toLowerCase(),r=t instanceof ii?t.stderr.toLowerCase():"",n=`${e} ${r}`;return["auth","login","permission","unauthorized","forbidden","access denied"].some(o=>n.includes(o))}s(ci,"isSetupAuthBlocker");var R=class{ctx;serverServices;async taskAction(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project,n=this.ctx.params.stage??"",o=this.ctx.params.taskAction??"",i=o==="start"||o==="continue"||o==="retry";if(i&&n==="setup"){await T(r,e),await ft(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution);return}if(i&&n==="run"){await T(r,e),await(await ge(e,r.id)).start(r.id,this.ctx.res);return}S(this.ctx.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")}async designDiscovery(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e),await Gr(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution)}async designDiscoveryConfirm(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e);let n=await k(this.ctx.req);await Yr(r.id,e.workspace,e.projectStore.instances,n,this.ctx.res)}async design(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e);let n=new URL(this.ctx.req.url??"/","http://localhost"),o=_t(n,this.ctx.req);await Qr(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution,o),await ve(e,r,"design")}async designEvents(){this.ctx.respond=!1,Zr(this.ctx.state.project.id,this.ctx.res)}async setup(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e),await ft(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution),await ve(e,r,"setup")}async runHumanAction(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await T(r,e),await rr(r.id,e.workspace,e.projectStore.instances,e.runtime,this.ctx.params.recordId??"",this.ctx.req,this.ctx.res)}async run(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project,n;try{let o=await k(this.ctx.req);n=await ge(e,r.id,qr(o.runMode))}catch(o){S(this.ctx.res,ee(o),F(o),P(o));return}await T(r,e),await n.start(r.id,this.ctx.res)}async runStop(){let r=await(await ge(this.serverServices,this.ctx.state.project.id)).stop(this.ctx.state.project.id);this.ctx.respond=!1,f(this.ctx.res,r)}async runStatus(){let r=await(await ge(this.serverServices,this.ctx.state.project.id)).status(this.ctx.state.project.id);this.ctx.respond=!1,f(this.ctx.res,r)}async runRecords(){let e=Number(he(this.ctx.query?.limit)),r=Number.isInteger(e)&&e>0?e:void 0,o=await(await ge(this.serverServices,this.ctx.state.project.id)).listRecords(this.ctx.state.project.id,{limit:r});this.ctx.respond=!1,f(this.ctx.res,o)}};s(R,"StagesController"),u([tn()],R.prototype,"ctx",2),u([tn()],R.prototype,"serverServices",2),u([ae("/:projectId/tasks/:stage/:taskAction")],R.prototype,"taskAction",1),u([ae("/:projectId/design/discovery")],R.prototype,"designDiscovery",1),u([ae("/:projectId/design/discovery/confirm")],R.prototype,"designDiscoveryConfirm",1),u([ae("/:projectId/design")],R.prototype,"design",1),u([mt("/:projectId/design/events")],R.prototype,"designEvents",1),u([ae("/:projectId/setup")],R.prototype,"setup",1),u([ae("/:projectId/run/records/:recordId/human-action")],R.prototype,"runHumanAction",1),u([ae("/:projectId/run")],R.prototype,"run",1),u([ae("/:projectId/run/stop")],R.prototype,"runStop",1),u([mt("/:projectId/run/status")],R.prototype,"runStatus",1),u([mt("/:projectId/run/records")],R.prototype,"runRecords",1),R=u([di("/api/projects")],R);import*as ze from"@midwayjs/core";import*as Ui from"@midwayjs/koa";import{createApp as Li,logger as Mi}from"aitable-workflow-core";var Ne=class{static{s(this,"LocalProjectRepository")}workspace;constructor(e){this.workspace=e}async create(e,r){let n=await Bt(this.workspace),o=[];if(r?.files&&r.files.length>0){let i=await Ee(n,r.files);o.push(...i.warnings);let a=await C(n);return r.title&&r.title.trim()&&(a=await le(a,{title:r.title.trim()})),{...a,files:i.written,warnings:o}}if(r?.title&&r.title.trim()){let i=await le(n,{title:r.title.trim()});return o.length?{...i,warnings:o}:{...i}}return o.length?{...n,warnings:o}:{...n}}async list(e){return nt(this.workspace)}async resolve(e,r){return b(this.workspace,e)}async updateMeta(e,r,n){return le(e,r)}async delete(e,r){await Re(e)}async updateFiles(e,r,n){return r.remove&&r.remove.length>0&&await gr(e,r.remove),r.upsert&&r.upsert.length>0&&await Ee(e,r.upsert),await C(e),j(e)}async replaceFiles(e,r,n){return await wr(e,r),await C(e),j(e)}async exportProject(e,r){return hr(e)}async syncHotFields(){}};import{randomUUID as pi}from"crypto";import{mkdir as ui,readFile as li,rm as fi,writeFile as mi}from"fs/promises";import je from"path";import{applyRunExecutionEvent as gi,emptyProjectState as wi,mergeStageIntoState as rn,normalizeProjectState as hi,patchRunSnapshotRecord as yi,recoverDesignFromArtifacts as Si,stageStateOf as vi}from"aitable-workflow-core";var Le=new Map,Pi=/^[a-zA-Z0-9_-]+$/,Me=class{static{s(this,"LocalWorkflowInstanceStore")}workspace;constructor(e){this.workspace=e}getState(e){return we(e)}getRecoverableState(e){return Ii(e)}createStageIdentity(e,r){return Di(e,r)}putStageState(e,r,n){return Ti(e,r,n)}appendRunSnapshotEvent(e,r){return Ri(e,r)}updateRunSnapshotRecord(e,r,n,o){return Oi(e,r,n,o)}deleteProjectState(e){return xi(this.workspace,e)}};async function xi(t,e){an(e);let r=ji(t,e);await fi(je.join(r,"runtime"),{recursive:!0,force:!0})}s(xi,"deleteProjectState");function ji(t,e){return an(e),je.join(t.projectsRoot,e)}s(ji,"projectDir");async function Di(t,e){let n=((await we(t)).stages[e]?.identity.attempt??0)+1,o=new Date().toISOString();return{id:`task_${pi().slice(0,8)}`,projectId:t.id,stage:e,attempt:n,startedAt:o,updatedAt:o}}s(Di,"createStageIdentity");async function Ti(t,e,r){return Ce(t,async()=>{let n=await we(t),o=rn(n,e,r);return await De(t,o),o})}s(Ti,"putStageState");async function we(t){await sn(t);let e=await li(on(t),"utf8").catch(()=>"");if(e.trim()){let r=bi(e),n=hi(t,r);return r.repaired&&await De(t,n),n}return wi(t)}s(we,"getState");async function Ri(t,e){return Ce(t,async()=>{let r=await we(t),n=gi(r.runSnapshot??{records:[],logs:[]},e),o={...r,runSnapshot:n,updatedAt:new Date().toISOString()};return await De(t,o),o})}s(Ri,"appendRunSnapshotEvent");async function Oi(t,e,r,n){return Ce(t,async()=>{let o=await we(t);if(!o.runSnapshot)return o;let i={...o,runSnapshot:yi(o.runSnapshot,e,r,n),updatedAt:new Date().toISOString()};return await De(t,i),i})}s(Oi,"updateRunSnapshotRecord");async function Ii(t){return Ce(t,async()=>{let e=await we(t),r=vi(e,"design"),n=await $t(t),o=Si(r,n);if(!o)return e;let i=e.stages.design;if(!i)return e;let a=new Date().toISOString(),c=rn(e,"design",{...i,state:o,identity:{...i.identity,updatedAt:a,completedAt:i.identity.completedAt??a}});return await De(t,c),c})}s(Ii,"getRecoverableState");function nn(t){return je.join(t.dir,"runtime")}s(nn,"runtimeDir");function ki(t){return je.join(nn(t),"artifacts")}s(ki,"artifactsDir");function on(t){return je.join(nn(t),"state.json")}s(on,"statePath");async function sn(t){await ui(ki(t),{recursive:!0})}s(sn,"ensureRuntimeDirs");async function De(t,e){await sn(t),await mi(on(t),`${JSON.stringify(e,null,2)}
17
- `,"utf8")}s(De,"writeProjectState");async function Ce(t,e){let r=t.dir||t.id,o=(Le.get(r)??Promise.resolve()).catch(()=>{}).then(e),i=o.then(()=>{},()=>{});Le.set(r,i);try{return await o}finally{Le.get(r)===i&&Le.delete(r)}}s(Ce,"withProjectStateWrite");function bi(t){try{return JSON.parse(t)}catch(e){let r=Ei(t);if(!r)throw e;return{...JSON.parse(r),repaired:!0}}}s(bi,"parseProjectStateJson");function Ei(t){let e=t.indexOf("{");if(e<0)return null;let r=0,n=!1,o=!1;for(let i=e;i<t.length;i+=1){let a=t[i];if(n){o?o=!1:a==="\\"?o=!0:a==='"'&&(n=!1);continue}if(a==='"')n=!0;else if(a==="{")r+=1;else if(a==="}"&&(r-=1,r===0))return t.slice(e,i+1)}return null}s(Ei,"extractFirstJsonObject");function an(t){if(!Pi.test(t))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${t}`),{code:"INVALID_PROJECT_ID"})}s(an,"assertProjectId");var Be=class{static{s(this,"LocalProjectStore")}projects;instances;workflows;constructor(e){this.projects=new Ne(e),this.instances=new Me(e)}async prepareWorkdir(e,r){return{project:await C(e),materialized:0,warnings:[]}}async commitWorkdir(e,r){}async cascadeDelete(e){}};import{detectInstalledCodingAgents as Ai}from"aitable-workflow-core";import{hostname as _i,platform as Fi}from"os";var gt="local",Wi=3e4;function Ni(t,e=Date.now()){return{machineId:gt,runtimes:t.map(r=>r.id),hasDws:!0,hostname:_i(),os:Fi(),lastSeen:e}}s(Ni,"buildLocalMachineInfo");var Ue=class{static{s(this,"LocalExecutionBackend")}kind="local";runMode="local";localMachineCache=null;ensureAvailable(){}async buildDesignExecutor(){}buildSetupExecutor(){}async buildRunExecutor(){}buildDwsRunner(){}listMachines(){let e=Date.now();if(!this.localMachineCache||e-this.localMachineCache.at>Wi){let r=[];try{r=Ai()}catch{r=[]}this.localMachineCache={info:Ni(r,e),at:e}}return[this.localMachineCache.info]}isMachineOnline(e){return e===gt}async getProjectMachine(){return gt}async bindProjectMachine(){}async unbindProjectMachine(){}};var $e=class{static{s(this,"LocalIdentityService")}authRequired=!1;async resolveIdentity(e){let r=yt(e);return{credential:r?"api-token":"none",authenticated:r,actor:this.resolveActorId(e)}}resolveActorId(e){let r=e.headers["x-actor-id"],n=Array.isArray(r)?r[0]:r;return n?.trim()?{actorId:n.trim()}:{}}};function cn(t={}){let e=t.workspace??Ct({dataRoot:t.dataRoot});return{workspace:e,runtime:Lr(t.appFactory??((r,n)=>Li(r,{onRunEvent:n}))),projectStore:t.projectStore??new Be(e),execution:t.execution??new Ue,identityService:t.identityService??new $e,webRoot:t.webRoot}}s(cn,"createServerServices");function dn(t=process.env){let e=t.AITABLE_RELAY_BOOTSTRAP_KEY;return typeof e=="string"&&e.trim()!==""?(Mi.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(dn,"warnDeprecatedBootstrapKey");var Ci="127.0.0.1",nu=8787;function qe(t){if(typeof t!="string")return;let e=t.trim();return e||void 0}s(qe,"readEnvString");function Bi(t){let e=qe(t);if(e===void 0)return;let r=Number.parseInt(e,10);return Number.isFinite(r)&&r>0?r:void 0}s(Bi,"readEnvPort");function pn(t={},e=process.env){let r=t.host??qe(e.AITABLE_WORKFLOW_HOST)??Ci,n=t.port??Bi(e.AITABLE_WORKFLOW_PORT)??8787,o=t.dataRoot??qe(e.AITABLE_WORKFLOW_DATA_DIR)??void 0,i=t.webRoot??qe(e.AITABLE_WORKFLOW_WEB_ROOT)??void 0;return{host:r,port:n,dataRoot:o,webRoot:i}}s(pn,"resolveServeConfig");async function cu(t={}){dn();let e=t.silent??process.env.VITEST==="true",r=pn({port:t.port,host:t.host,dataRoot:t.dataRoot,webRoot:t.webRoot}),n=t.services??cn({dataRoot:r.dataRoot,appFactory:t.appFactory,webRoot:r.webRoot}),o=await $i(n,r.host,r.port,{loggerFactory:t.loggerFactory,silent:e});return e||(console.log(`aitable-workflow server listening on http://${r.host}:${r.port}`),console.log(`data root: ${n.workspace.dataRoot}`)),o}s(cu,"startServer");async function $i(t,e,r,n={}){let o=n.loggerFactory??(n.silent?Ji():void 0),i=await qi(()=>ze.initializeGlobalApplicationContext({imports:[Ui,We],moduleDetector:!1,...o?{loggerFactory:o}:{},globalConfig:{keys:["aitable-workflow"],koa:{port:r,hostname:e},bodyParser:{enable:!1}}}));i.registerObject("serverServices",t);let a=await i.getAsync(ze.HTTP_SERVER_KEY);return await zi(a),a}s($i,"bootMidwayKoa");var un=Promise.resolve();async function qi(t){let e=s(async()=>{let n=process.env.MIDWAY_HTTP_PORT;delete process.env.MIDWAY_HTTP_PORT;try{return await t()}finally{n===void 0?delete process.env.MIDWAY_HTTP_PORT:process.env.MIDWAY_HTTP_PORT=n}},"task"),r=un.then(e,e);return un=r,r}s(qi,"withoutLeakedMidwayPortEnv");function zi(t){return t.listening?Promise.resolve():new Promise((e,r)=>{let n=s(()=>{t.removeListener("error",o),e()},"onListening"),o=s(i=>{t.removeListener("listening",n),r(i)},"onError");t.once("listening",n),t.once("error",o)})}s(zi,"waitUntilListening");var ln={debug:s(()=>{},"debug"),info:s(()=>{},"info"),warn:s(()=>{},"warn"),error:s(()=>{},"error"),log:s(()=>{},"log"),trace:s(()=>{},"trace")};function Ji(){return{createLogger:s(()=>ln,"createLogger"),getLogger:s(()=>ln,"getLogger"),close:s(()=>{},"close"),removeLogger:s(()=>{},"removeLogger"),getDefaultMidwayLoggerConfig:s(()=>({midwayLogger:{default:{},clients:{coreLogger:{},appLogger:{}}}}),"getDefaultMidwayLoggerConfig"),createContextLogger:s((t,e)=>e,"createContextLogger"),getClients:s(()=>new Map,"getClients"),getClientKeys:s(()=>[],"getClientKeys")}}s(Ji,"silentLoggerFactory");import fn from"path";function lu(t){let e=fn.normalize(t).split(fn.sep).join("/");return e==="workflow.yml"?"workflow":e.startsWith("recipes/")?"recipe":"other"}s(lu,"workflowFileKind");var mn=class{static{s(this,"LocalProjectMutexStore")}queues=new Map;withProjectLock(e,r){let o=(this.queues.get(e)??Promise.resolve()).then(r,r);return this.queues.set(e,o),o.then(()=>{this.queues.get(e)===o&&this.queues.delete(e)},()=>{this.queues.get(e)===o&&this.queues.delete(e)}).catch(()=>{}),o}};export{Ci as DEFAULT_SERVE_HOST,nu as DEFAULT_SERVE_PORT,gt as LOCAL_MACHINE_ID,Ue as LocalExecutionBackend,$e as LocalIdentityService,mn as LocalProjectMutexStore,Ne as LocalProjectRepository,Be as LocalProjectStore,dt as LocalRunController,Me as LocalWorkflowInstanceStore,Ps as RUN_REPLAY_AGENT_CAP,vs as RUN_REPLAY_EVENT_CAP,pt as RelayRunController,pe as apiError,it as assertSafeProjectPath,pr as assertSafeRelativePath,Mc as assertSafeWorkflowPath,lr as assertWritableKind,qt as buildAITableUrl,Ni as buildLocalMachineInfo,Ft as cascadeDeleteProject,Pe as checksumContent,ve as commitStageOnTerminal,A as configPath,Bt as createProject,Lr as createServerRuntime,cn as createServerServices,Ct as createWorkspace,Re as deleteProject,F as errorCode,$ as errorDetails,P as errorMessage,Ve as errorStack,ee as errorStatus,he as firstQueryValue,Mr as handleRunRuntime,Vi as identityOf,ur as isForbiddenWritable,mr as isLegacyViewsPath,Kn as isStageActiveFor,fr as kindOf,j as listProjectFiles,nt as listProjects,We as midwayComponent,qr as parseRequestedRunMode,T as prepareWorkdirGuarded,He as readBuffer,no as readDesignManifest,k as readJson,Ie as removeLegacyViewsFiles,gr as removeProjectFiles,wr as replaceProjectFiles,Ut as resetProjectWorkflow,b as resolveProject,ge as resolveRunController,pn as resolveServeConfig,O as scopeOf,S as sendError,f as sendJson,Pt as sendText,xt as sendUnauthorized,Ji as silentLoggerFactory,cu as startServer,C as touchProject,xs as trimRunReplayEvents,le as updateProjectMeta,No as validateConfigScene,$t as validateDesignArtifacts,dn as warnDeprecatedBootstrapKey,qi as withoutLeakedMidwayPortEnv,lu as workflowFileKind,ot as writeDesignManifest,Ee as writeProjectFiles};
15
+ `)}o(Ee,"writeSse");var ct=class{constructor(e,r){this.services=e;this.runMode=r}services;runMode;static{o(this,"LocalRunController")}mode="local";async start(e,r){ae(r),await Xt(e,this.services.workspace,this.services.projectStore.instances,this.services.runtime,r,Ee,this.services.execution,this.runMode)}async stop(e){let r=this.services.runtime.runSessions.get(e);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(e){let r=this.services.runtime.runSessions.get(e);return{mode:this.mode,running:r!=null,taskId:r?.taskId??null}}async listRecords(e,r){if(this.services.execution.runRecords)return this.services.execution.runRecords.listRecords(e,r);let n=await I(this.services.workspace,e),a=(await this.services.projectStore.instances.getState(n)).runSnapshot?.records??[],i=r?.limit??100;return{items:[...a].sort((d,u)=>u.updatedAt-d.updatedAt).slice(0,i).map(d=>({itemId:d.id,title:d.title,state:d.state,currentStepId:d.currentStepId,doneStepIds:d.doneStepIds,completedAt:d.status==="done"?new Date(d.updatedAt).toISOString():null,updatedAt:new Date(d.updatedAt).toISOString(),status:d.status})),counts:{total:a.length,completed:a.filter(d=>d.status==="done").length}}}async listEvents(e,r){if(this.services.execution.runEvents)return this.services.execution.runEvents.listEvents(e,r);let n=await I(this.services.workspace,e);return await this.services.projectStore.instances.listRunEvents?.(n,r)??{events:[],lastSeq:r?.afterSeq??0}}},dt=class{constructor(e,r,n){this.scheduler=e;this.records=r;this.events=n}scheduler;records;events;static{o(this,"RelayRunController")}mode="relay";async start(e,r){g(r,{mode:this.mode,action:"start",schedule:await this.scheduler.start(e)})}async stop(e){return{mode:this.mode,action:"stop",schedule:await this.scheduler.stop(e)}}async status(e){return{mode:this.mode,action:"status",schedule:await this.scheduler.getStatus(e)}}async listRecords(e,r){return this.records?this.records.listRecords(e,r):{items:[],counts:{total:0,completed:0}}}async listEvents(e,r){return this.events?this.events.listEvents(e,r):{events:[],lastSeq:r?.afterSeq??0}}},be=["server-run-relay-agent","server-run-relay-recipe","workflow-pull-claim"];function nr(t){if(t!=null){if(be.includes(t))return t;throw Object.assign(new Error(`\u8BF7\u6C42\u4F53 runMode \u975E\u6CD5\u503C "${String(t)}"\uFF1B\u8BF7\u6C42\u7EA7\u8986\u76D6\u4EC5\u652F\u6301 ${be.join(" | ")}`),{code:"INVALID_RUN_MODE",status:400})}}o(nr,"parseRequestedRunMode");async function Is(t,e){let r=await t.getStatus(e);return r.desiredState==="running"||r.machineAssigned}o(Is,"hasActiveLease");function ks(t){if(!(!t||!("runMode"in t)))return t.runMode==="server-run-relay-agent"||t.runMode==="server-run-relay-recipe"?t.runMode:void 0}o(ks,"pickRecoverableRunMode");async function sr(t,e){try{let r=await I(t.workspace,e),n=await t.projectStore.instances.getState(r);return ks(n.stages.run?.state)}catch{return}}o(sr,"recoverPersistedRunMode");async function ce(t,e,r){let{execution:n}=t,s=o(()=>{if(!n.runScheduler)throw Object.assign(new Error("runMode=workflow-pull-claim requires execution.runScheduler"),{code:"RUN_SCHEDULER_REQUIRED",status:500});return new dt(n.runScheduler,n.runRecords,n.runEvents)},"relayController"),a=r??n.runMode;if(a!=="workflow-pull-claim"&&e&&n.runScheduler&&await Is(n.runScheduler,e)){if(r==="server-run-relay-agent"||r==="server-run-relay-recipe")throw Object.assign(new Error(`\u9879\u76EE ${e} \u5B58\u5728\u6D3B\u8DC3 workflow \u79DF\u7EA6\uFF08daemon \u8BA4\u9886\u6267\u884C\u4E2D\uFF09\uFF0C\u4E0D\u80FD\u5207\u4E3A\u8FDB\u7A0B\u5185\u6267\u884C\uFF1B\u5148 POST /run/stop \u91CA\u653E\u79DF\u7EA6`),{code:"RUN_LEASE_ACTIVE",status:409});return s()}if(e&&r==="workflow-pull-claim"&&t.runtime.runSessions.has(e))throw Object.assign(new Error(`\u9879\u76EE ${e} \u5728\u670D\u52A1\u7AEF\u8FDB\u7A0B\u5185\u6709 run \u4F1A\u8BDD\uFF0C\u5148\u505C\u6B62\u518D\u6309 workflow-pull-claim \u4E0B\u53D1`),{code:"RUN_SESSION_ACTIVE",status:409});return a==="workflow-pull-claim"?s():new ct(t,a)}o(ce,"resolveRunController");var C=class{ctx;serverServices;async health(){this.ctx.respond=!1,g(this.ctx.res,{ok:!0})}async checkNode(){this.ctx.respond=!1,jt(this.ctx.res,"success")}async publicConfig(){let e=process.env.RELAY_PUBLIC_GATEWAY_URL?.trim();this.ctx.respond=!1,g(this.ctx.res,{authEnabled:this.serverServices.identityService.authRequired,...e?{relayGatewayUrl:e}:{},runOverrideModes:this.serverServices.execution.kind==="relay"?[...be]:[]})}async agents(){this.ctx.respond=!1,g(this.ctx.res,bs())}async machines(){this.ctx.respond=!1;let e=(this.serverServices.execution.listMachines()??[]).map(({machineId:r,ownerUserId:n,...s})=>s);g(this.ctx.res,{machines:e})}};o(C,"SystemController"),p([or()],C.prototype,"ctx",2),p([or()],C.prototype,"serverServices",2),p([Se("/api/health")],C.prototype,"health",1),p([Se("/check.node")],C.prototype,"checkNode",1),p([Se("/api/public-config")],C.prototype,"publicConfig",1),p([Se("/api/agents")],C.prototype,"agents",1),p([Se("/api/machines")],C.prototype,"machines",1),C=p([Es("/")],C);import ee from"path";import{Controller as Po,Del as xo,Get as de,Inject as Lr,Patch as gt,Post as ge,Put as Cr}from"@midwayjs/core";import{validateDesignArtifacts as Ro,buildEnvSource as Do,loadWorkflowTemplate as Ur,loadSettings as qr}from"aitable-workflow-core";import{DwsClient as ir,dwsPayload as ut,findArrayPayload as ar}from"aitable-workflow-core";function As(t,e){let r={},n=o((s,a)=>{s&&a!==void 0&&(typeof a=="string"&&a.trim()===""||(r[s]=a))},"put");return n(t.name,e.name),n(t.type,e.type),n(t.owner,e.owner),n(t.runtime,e.runtime),n(t.online,e.online),n(t.visibility,e.visibility),n(t.enabled,e.enabled),n(t.description,e.description),r}o(As,"buildRegistryCells");function cr(t){let e=new Map;for(let r of ar(t)){let n=r;n.fieldId&&n.fieldName&&e.set(n.fieldName,n.fieldId)}return e}o(cr,"fieldIdByName");function _s(t,e){let r={};for(let[n,s]of Object.entries(t)){let a=e.get(n);a&&(r[a]=s)}return r}o(_s,"translateCellsToIds");async function dr(t){let{registry:e,input:r}=t,n=t.dws??new ir({bin:"dws"}),s=await n.runJson(["aitable","field","list","--base-id",e.base_id,"--table-id",e.table_id]),a=cr(ut(s)),i=_s(As(e.fields,r),a);if(Object.keys(i).length===0)throw new Error("\u767B\u8BB0\u8868\u5217\u540D\u4E0E identity.registry.fields \u4E0D\u5339\u914D\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u5355\u5143\u683C");let c=await n.runJson(["aitable","record","create","--base-id",e.base_id,"--table-id",e.table_id,"--records",JSON.stringify([{cells:i}]),"--yes"]),u=ut(c)?.newRecordIds?.[0];if(!u)throw new Error("dws \u672A\u8FD4\u56DE\u65B0\u884C recordId");return{recordId:u}}o(dr,"createRegistryAgent");function pt(t){if(t==null)return;if(typeof t=="boolean"||typeof t=="string")return t;if(typeof t=="number")return String(t);if(Array.isArray(t))return t.map(n=>pt(n)).filter(n=>n!==void 0).map(String).join("\u3001");let e=t,r=e.name??e.text??e.value;if(r!==void 0)return pt(r)}o(pt,"cellToScalar");function se(t,e,r){if(!r)return;let n=e.get(r);if(n)return pt(t[n])}o(se,"readColumn");async function ur(t){let{registry:e}=t,r=t.dws??new ir({bin:"dws"}),n=await r.runJson(["aitable","field","list","--base-id",e.base_id,"--table-id",e.table_id]),s=cr(ut(n)),a=await r.runJson(["aitable","record","list","--base-id",e.base_id,"--table-id",e.table_id]),i=[];for(let c of ar(a)){let d=c;if(!d.recordId||!d.cells)continue;let u=d.cells,w=se(u,s,e.fields.enabled);i.push({recordId:d.recordId,name:String(se(u,s,e.fields.name)??""),type:se(u,s,e.fields.type),owner:se(u,s,e.fields.owner),runtime:se(u,s,e.fields.runtime),online:se(u,s,e.fields.online),visibility:se(u,s,e.fields.visibility),enabled:typeof w=="boolean"?w:w===void 0?void 0:!!w,description:se(u,s,e.fields.description)})}return i}o(ur,"listRegistryAgents");import{isTerminalPhase as Fs,logger as Ns}from"aitable-workflow-core";function Ms(t,e){return t.runtime.runSessions.has(e)||he.has(e)}o(Ms,"isStageActiveFor");function b(t,e){return e.projectStore.prepareWorkdir(t,{isStageActive:o(()=>Ms(e,t.id),"isStageActive")})}o(b,"prepareWorkdirGuarded");async function ve(t,e,r){try{let s=(await t.projectStore.instances.getState(e)).stages[r];if(!s||!Fs(r,s.state))return;await t.projectStore.commitWorkdir(e,{stage:r})}catch(n){Ns.warn("stage-sync","stage \u6D41\u56DE\u5199\u6743\u5A01\u6E90\u5931\u8D25",{projectId:e.id,stage:r,error:v(n)})}}o(ve,"commitStageOnTerminal");async function pr(t,e){await t.projectStore.cascadeDelete(e).catch(()=>{}),await t.execution.unbindProjectMachine(e).catch(()=>{})}o(pr,"cascadeDeleteProject");import Ae from"path";import{readFile as lt,writeFile as fr,access as Ws,readdir as Ls}from"fs/promises";import Pe from"yaml";import{scaffold as Cs,writeProfileRoles as Us,isRecord as oe}from"aitable-workflow-core";function lr(t,e=1){let r=t.replace(/\s+/g," ").trim();if(!r)return`\u5DE5\u4F5C\u6D41 #${e}`;let n=r.split(/[。.!!?\n]/u)[0]?.split(/[::,,;;]/u)[0]?.trim();return n?n.length>16?n.slice(0,16):n:`\u5DE5\u4F5C\u6D41 #${e}`}o(lr,"deriveProjectTitleFromSop");async function mr(t,e,r,n,s,a){let i=await I(e,t),c=await A(n),d=await G.open({project:i,stage:"init",store:r,driver:"init.http",facts:o(()=>K(i.id,"init",{hasRunSession:o(()=>!1,"hasRunSession")}),"facts")});await d.advance({phase:"configuring"});try{let u=Bs(c),w=await Cs({answers:u,cwd:i.dir,force:!0}),m=await Us(Ae.join(i.dir,"profile","profile.yml"),c.roles??[]);if(c.agentsSelected&&c.agentsSelected.length>0){let q=c.agentsSelected[0],x=q?Vs(q):void 0;if(x){let U=_(i);try{let D=Pe.parse(await lt(U,"utf8"));oe(D)&&(oe(D.agent)||(D.agent={}),D.agent.engine=x,await fr(U,Pe.stringify(D),"utf8"))}catch{}}}c.machineToken&&a&&await a(t,c.machineToken);let l=await L(i),f=m.skippedKnowledgeBindings.map(q=>`\u89D2\u8272 ${q.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 profile\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${q.knowledge.join(", ")}`);await d.advance({phase:"ready",warnings:f,roleFiles:[]});let y=lr(c.sop,1),E=await fe(l,{title:y});g(s,{project:E,scaffold:w,roleFiles:[],files:await k(l),warnings:f})}catch(u){throw await d.advance({phase:"failed",error:{code:F(u),message:v(u),retryable:!0,details:B(u)}}),u}}o(mr,"handleInit");async function gr(t,e,r,n){let s=await I(e.workspace,t),i=(await A(r)).tableId?.trim()??"";if(!i)throw Object.assign(new Error("Table Id \u4E0D\u80FD\u4E3A\u7A7A"),{code:"TABLE_ID_REQUIRED",status:422});let c=_(s),d=await lt(c,"utf8"),u=Pe.parse(d);if(!oe(u)||!oe(u.tracker)){let m=oe(u)&&oe(u.workflows);throw Object.assign(new Error(m?"\u591A\u5DE5\u4F5C\u6D41\u9879\u76EE\u7684 table_id \u5C5E\u4E8E\u5404\u81EA\u7684 workflows/<id>/workflow.yml\uFF0C\u8BF7\u76F4\u63A5\u6539\u5BF9\u5E94\u6587\u4EF6\u7684 tracker.table_id":"\u914D\u7F6E\u6587\u4EF6\u7F3A\u5C11 tracker\uFF0C\u65E0\u6CD5\u5199\u56DE Table Id"),{code:m?"TABLE_ID_PER_WORKFLOW":"CONFIG_TRACKER_MISSING",status:m?422:500})}u.tracker.table_id=i,await fr(c,Pe.stringify(u),"utf8");let w=await L(s);g(n,{project:w,files:await k(w),state:await ke(e,w)})}o(gr,"handleUpdateProjectTableId");async function wr(t,e,r,n,s,a,i){let c=await I(e,t),d=await A(a);if(d.action!=="confirm"&&d.action!=="terminate")throw Object.assign(new Error("\u4EBA\u5DE5\u64CD\u4F5C\u53EA\u652F\u6301 confirm \u6216 terminate"),{code:"INVALID_HUMAN_ACTION",status:422});let u=n.runSessions.get(t)?.app;if(!u)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 w=d.action==="confirm"?u.settings.tracker.states.active[0]:u.settings.tracker.states.terminal.find(y=>y==="\u5DF2\u5173\u95ED")??u.settings.tracker.states.terminal.at(-1);if(!w)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=d.action==="confirm"?"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EE7\u7EED\u6D41\u7A0B":"\u4EBA\u5DE5\u786E\u8BA4\uFF1A\u7EC8\u6B62\u6D41\u7A0B",l=null;d.action==="confirm"&&(l=await qs(u,s)),await u.tracker.updateState(s,w),l&&await u.tracker.updateCurrentStep(s,l),await u.tracker.appendEvent(s,m);let f=await r.updateRunSnapshotRecord(c,s,d.action==="confirm"?{state:w,status:"running",currentStepId:l??void 0}:{state:w,status:"done",currentStepId:null},m);g(i,{action:d.action,recordId:s,state:f})}o(wr,"handleRunHumanAction");async function qs(t,e){let[r]=await t.tracker.fetchItemsByIds([e]).catch(()=>[]),n=r?.currentStep;if(!n)return null;let s=t.workflow.orderedStepIds.indexOf(n);return s<0?null:t.workflow.orderedStepIds[s+1]??null}o(qs,"resolveNextStepId");function Bs(t){let e=t.tableBaseId.trim(),r=t.llmProvider.trim();return{agentType:Js(t.agentsSelected),scene:$s(t),baseId:e,llmProvider:r,llmModel:r?t.llmModel.trim()||Hs(r):"",llmApiKeyEnv:r?zs(r):"",confirmed:!0}}o(Bs,"toInitAnswers");function $s(t){return t.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"}o($s,"buildScene");function Js(t){return t.includes("qwenwork")?"qwenwork":t.includes("qoder")?"qoder":t.includes("codex")?"codex":"claudecode"}o(Js,"toAgentType");function Vs(t){if(t==="claude"||t==="qoder"||t==="codex"||t==="qwenwork")return t}o(Vs,"agentIdToEngine");function Hs(t){return t==="openai"?"gpt-4o":t==="anthropic"?"claude-sonnet-4-20250514":t==="dashscope"?"qwen-max":"Qwen3.7-Max-DogFooding"}o(Hs,"defaultModel");function zs(t){return t==="openai"?"OPENAI_API_KEY":t==="anthropic"?"ANTHROPIC_API_KEY":t==="dashscope"?"DASHSCOPE_API_KEY":t==="idealab"?"IDEALAB_API_KEY":"LLM_API_KEY"}o(zs,"defaultApiKeyEnv");async function hr(t,e){let r=Ae.join(t.dir,"aitable-workflow.config.yml");try{await Ws(r)}catch{e.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 Gs(t.dir)||e.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")}o(hr,"augmentProjectFileValidation");async function Gs(t){try{let r=Pe.parse(await lt(Ae.join(t,"profile","profile.yml"),"utf8"));if(oe(r)&&oe(r.roles)&&Object.keys(r.roles).length>0)return!0}catch{}return(await Ls(Ae.join(t,"roles")).catch(()=>[])).some(r=>r.endsWith(".role.yml")||r.endsWith(".role.yaml"))}o(Gs,"hasAnyRoleDefinition");import yr from"fs";import Ks from"path";var Ys=/requiresAgent\s*:\s*(true|false)/,Sr=new Map;function vr(t,e){if(!e)return!1;for(let r of[".recipe.ts",".recipe.js"]){let n=Ks.join(t,`${e}${r}`);try{let s=yr.statSync(n);if(!s.isFile())continue;let a=`${s.mtimeMs}:${s.size}`,i=Sr.get(n);if(i?.signature===a)return i.requiresAgent;let d=yr.readFileSync(n,"utf8").match(Ys),u=d?d[1]==="true":!1;return Sr.set(n,{signature:a,requiresAgent:u}),u}catch(s){if(s.code==="ENOENT")continue;return!1}}return!1}o(vr,"readRecipeRequiresAgent");import{rm as xr,mkdir as Zs,writeFile as Qs}from"fs/promises";import xe from"path";import Xs from"yaml";import{isRecord as eo,resolveInsideRoot as to}from"aitable-workflow-core";var Pr=/\.(json|ya?ml|ts|js|md|txt)$/i,ro=new Set(["runtime","traces","node_modules"]),Rr="aitable-workflow.config.yml";function Dr(t,e){try{to(t,e,{allowRoot:!1})}catch{throw Object.assign(new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u76EE\u5F55: ${e}`),{code:"invalid_path",status:400})}}o(Dr,"assertSafeRelativePath");function ft(t,e){Dr(t.dir,e)}o(ft,"assertSafeProjectPath");function nd(t){Dr("/workflow-root",t)}o(nd,"assertSafeWorkflowPath");function jr(t){let r=mt(t).split("/")[0]??"";return ro.has(r)}o(jr,"isForbiddenWritable");function Tr(t){if(Ir(t))throw Object.assign(new Error(`\u5DF2\u5E9F\u5F03\u7684\u89C6\u56FE\u6587\u4EF6\u5FC5\u987B\u5185\u8054\u5230 workflow.yml \u7684 tracker.views: ${t}`),{code:"invalid_path",status:400});if(jr(t))throw Object.assign(new Error(`\u7981\u6B62\u5199\u5165\u53D7\u4FDD\u62A4\u76EE\u5F55: ${t}`),{code:"invalid_path",status:400});if(!Pr.test(t))throw Object.assign(new Error(`\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8\u5199\u5165: ${t}\uFF08\u4EC5\u5141\u8BB8 ${Pr.source}\uFF09`),{code:"invalid_path",status:400})}o(Tr,"assertWritableKind");function Or(t){let e=mt(t);return e===Rr||e.endsWith(".config.yml")?"config":e==="workflow.yml"?"workflow":e.startsWith("recipes/")?"recipe":e.startsWith("roles/")?"role":"other"}o(Or,"kindOf");function Ir(t){let e=mt(t);return e==="views.yml"||e.endsWith("/views.yml")}o(Ir,"isLegacyViewsPath");function mt(t){return xe.posix.normalize(t.replace(/\\/g,"/")).replace(/^\.\//,"")}o(mt,"normalizeLogicalPath");function no(t){let e=[],r;try{r=Xs.parse(t)}catch(s){return e.push(`aitable-workflow.config.yml \u89E3\u6790\u5931\u8D25: ${s instanceof Error?s.message:String(s)}`),e}if(!eo(r))return e.push("aitable-workflow.config.yml \u9876\u5C42\u5E94\u4E3A\u5BF9\u8C61"),e;let n=r.scene;return(typeof n!="string"||n.trim()==="")&&e.push("aitable-workflow.config.yml \u7F3A\u5C11 scene \u5B57\u6BB5\uFF08\u5EFA\u8BAE\u586B\u5199\u4E1A\u52A1\u573A\u666F\u63CF\u8FF0\uFF09"),e}o(no,"validateConfigScene");async function _e(t,e){let r=[],n=[];for(let s of e){ft(t,s.path),Tr(s.path);let a=xe.join(t.dir,s.path);await Zs(xe.dirname(a),{recursive:!0}),await Qs(a,s.content,"utf8"),r.push({path:s.path,content:s.content}),s.path===Rr&&n.push(...no(s.content))}return{written:r,warnings:n}}o(_e,"writeProjectFiles");async function kr(t,e){for(let r of e){if(ft(t,r),jr(r))throw Object.assign(new Error(`\u7981\u6B62\u5220\u9664\u53D7\u4FDD\u62A4\u76EE\u5F55: ${r}`),{code:"invalid_path",status:400});await xr(xe.join(t.dir,r),{force:!0})}}o(kr,"removeProjectFiles");async function Er(t,e){for(let n of e)ft(t,n.path),Tr(n.path);let r=await so(t);for(let n of r)await xr(xe.join(t.dir,n),{force:!0}).catch(()=>{});return await Ie(t.dir),_e(t,e)}o(Er,"replaceProjectFiles");async function so(t){return(await k(t)).map(r=>r.path).filter(r=>Or(r)!=="other"||Ir(r))}o(so,"collectBusinessFiles");function oo(t){return we(t.content)}o(oo,"checksumFile");async function br(t){let e=await k(t),r=e.map(n=>({path:n.path,sha256:oo(n)}));return{project:t,files:e,checksums:r,exportedAt:new Date().toISOString()}}o(br,"buildProjectExport");var io="coding-agents.config.json";function Ar(t){let e=[],r=t.files,n=t.checksums,s=r.findIndex(a=>a.path===io);if(s>=0){let a=r[s],i=a.content;try{let c=JSON.parse(a.content);if(c&&typeof c=="object"&&!Array.isArray(c)){let d=c.agents;if(d&&typeof d=="object"&&!Array.isArray(d)){let u=!1;for(let w of Object.keys(d)){let m=d[w];if(!m||typeof m!="object"||Array.isArray(m))continue;let l=m.env;if(l&&typeof l=="object"&&!Array.isArray(l)){let f=l;if(Object.values(f).some(E=>typeof E=="string"&&E!=="")){for(let E of Object.keys(f))f[E]="";u=!0}}}u&&(i=JSON.stringify(c,null,2)+`
16
+ `)}}}catch{}if(i!==a.content){let c={path:a.path,content:i};r=r.map((u,w)=>w===s?c:u);let d=we(i);n=n.map((u,w)=>w===s?{path:u.path,sha256:d}:u),e.push(a.path)}}return{...t,files:r,checksums:n,redacted:e.length>0?e:t.redacted}}o(Ar,"redactExportBundle");import _r from"path";import{strFromU8 as Fr,unzipSync as ao}from"fflate";var co=/\.(json|ya?ml|ts|js|md|txt)$/i,uo=new Set(["runtime","traces","node_modules"]),po=new Set(["__MACOSX"]),lo=/(^|\/)\.(_|DS_Store)/,fo="project-manifest.json",mo="project.json",Nr=20*1024*1024,go=5e3,wo=100*1024*1024;function Mr(t,e={}){let r=e.maxEntries??go,n=e.maxTotalUncompressedBytes??wo,s=0,a=0,i,c;try{c=ao(new Uint8Array(t),{filter:o(f=>f.name.endsWith("/")||i?!1:(s+=1,a+=f.originalSize,s>r?(i=`zip \u6761\u76EE\u6570\u8D85\u8FC7\u4E0A\u9650\uFF08${r}\uFF09`,!1):a>n?(i=`zip \u89E3\u538B\u540E\u603B\u5927\u5C0F\u8D85\u8FC7\u4E0A\u9650\uFF08${n} \u5B57\u8282\uFF09`,!1):!0),"filter")})}catch(f){throw i?Object.assign(new Error(`zip \u8D85\u8FC7\u5BFC\u5165\u5BB9\u91CF\u4E0A\u9650\uFF1A${i}`),{code:"ZIP_TOO_LARGE",status:413}):Object.assign(new Error(`zip \u89E3\u6790\u5931\u8D25: ${f instanceof Error?f.message:String(f)}`),{code:"INVALID_ZIP",status:400})}if(i)throw Object.assign(new Error(`zip \u8D85\u8FC7\u5BFC\u5165\u5BB9\u91CF\u4E0A\u9650\uFF1A${i}`),{code:"ZIP_TOO_LARGE",status:413});let d=Object.entries(c).filter(([f])=>!f.endsWith("/")).map(([f,y])=>({path:ho(f),data:y})).filter(f=>!!f.path),u=yo(d.map(f=>f.path)),w=new Map,m;for(let f of d){let y=u(f.path);if(y===fo){let q=Fr(f.data);m=vo(q)??m;continue}if(!y||So(y))continue;let E=Fr(f.data);w.set(y,{path:y,content:E})}let l=Array.from(w.values()).sort((f,y)=>f.path.localeCompare(y.path));if(l.length===0)throw Object.assign(new Error("zip \u4E2D\u672A\u89E3\u6790\u5230\u53EF\u5BFC\u5165\u7684\u9879\u76EE\u6587\u4EF6\uFF08\u4EC5\u652F\u6301 .json/.yml/.yaml/.ts/.js/.md/.txt\uFF0C\u4E14\u4E0D\u80FD\u4F4D\u4E8E runtime/traces/node_modules\uFF09"),{code:"EMPTY_ZIP_PROJECT",status:422});return{files:l,title:m}}o(Mr,"parseProjectZip");function ho(t){let e=t.replace(/\\/g,"/").replace(/^\/+/,"");if(!e||e.includes("\0"))return null;let r=_r.posix.normalize(e).replace(/^\.\//,"");return!r||r==="."||r===".."||r.startsWith("../")||_r.posix.isAbsolute(r)?null:r}o(ho,"normalizeZipPath");function yo(t){let e=t.filter(i=>!Wr(i)),r=new Set,n=!1;for(let i of e){let c=i.split("/",2),d=c[0],u=c[1];if(!d||!u){n=!0;break}r.add(d)}if(n||r.size!==1)return i=>i;let[s]=Array.from(r);if(!s)return i=>i;let a=`${s}/`;return i=>i.startsWith(a)?i.slice(a.length):i}o(yo,"detectSingleTopDir");function So(t){if(!t||t===mo||Wr(t))return!0;let e=t.split("/")[0]??"";return uo.has(e)?!0:!co.test(t)}o(So,"shouldSkipPath");function Wr(t){let e=t.split("/")[0]??"";return po.has(e)||lo.test(t)}o(Wr,"isJunkPath");function vo(t){try{let e=JSON.parse(t);return typeof e.title=="string"&&e.title.trim()?e.title.trim():void 0}catch{return}}o(vo,"readManifestTitle");var R=class{ctx;serverServices;async list(){let e=await this.serverServices.projectStore.projects.list(O(this.ctx));this.ctx.respond=!1,g(this.ctx.res,{projects:e})}async create(){let e=this.serverServices,r=O(this.ctx),n=await A(this.ctx.req),s=await e.projectStore.projects.create(r,{title:n.title,files:n.files});await b(s,e);let a={project:s};s.files&&(a.files=s.files),s.warnings&&s.warnings.length>0&&(a.warnings=s.warnings),this.ctx.respond=!1,g(this.ctx.res,a)}async importZip(){let e=this.serverServices,r=O(this.ctx),n=await Ze(this.ctx.req,Nr),s=Mr(n),a=ie(this.ctx.query?.title)?.trim()||s.title||"\u5BFC\u5165\u9879\u76EE",i=await e.projectStore.projects.create(r,{title:a,files:s.files});await b(i,e);let c={project:i,files:i.files,imported:{source:"zip",fileCount:s.files.length}};i.warnings&&i.warnings.length>0&&(c.warnings=i.warnings),this.ctx.respond=!1,g(this.ctx.res,c)}async remove(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project;if(this.ctx.respond=!1,e.runtime.runSessions.has(n.id)){S(this.ctx.res,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664");return}await e.projectStore.projects.delete(n,r),await Te(n),await pr(e,n.id),g(this.ctx.res,{ok:!0,id:n.id})}async updateMeta(){let e=this.serverServices,r=O(this.ctx),n=await A(this.ctx.req),s=await e.projectStore.projects.updateMeta(this.ctx.state.project,{title:n.title},r);this.ctx.respond=!1,g(this.ctx.res,{project:s})}async init(){let e=this.serverServices,r=this.ctx.state.project;this.ctx.respond=!1,await b(r,e);let n=e.execution;await mr(r.id,e.workspace,e.projectStore.instances,this.ctx.req,this.ctx.res,async(s,a)=>{let i=O(this.ctx).ownerUserId;if(!i)throw Object.assign(new Error("\u9700\u8981\u767B\u5F55\u540E\u624D\u80FD\u7ED1\u5B9A\u6267\u884C\u5F15\u64CE"),{code:"UNAUTHENTICATED",status:401});let c=await n.resolveMachineToken(a,i);if(!c)throw Object.assign(new Error("\u6267\u884C\u5F15\u64CE\u4E0D\u5B58\u5728\u6216 token \u5DF2\u5931\u6548"),{code:"MACHINE_NOT_FOUND",status:404});await n.bindProjectMachine(s,c)}),await ve(e,r,"init")}async getEngine(){let e=this.ctx.state.project,r=this.serverServices.execution,n=await r.getProjectMachine(e.id);if(this.ctx.respond=!1,!n){g(this.ctx.res,{machineToken:null,machine:null,status:"unbound"});return}let s=r.isMachineOnline(n),i=(r.listMachines()??[]).find(d=>d.machineId===n),c=await r.getMachineToken(n);g(this.ctx.res,{machineToken:c,machine:i?{runtimes:i.runtimes,hasDws:i.hasDws,hostname:i.hostname,os:i.os,lastSeen:i.lastSeen}:null,status:s?"online":"offline"})}async bindEngine(){let e=await A(this.ctx.req);if(this.ctx.respond=!1,!e.machineToken?.trim()){S(this.ctx.res,422,"INVALID_INPUT","machineToken \u4E0D\u80FD\u4E3A\u7A7A");return}let r=O(this.ctx).ownerUserId;if(!r){S(this.ctx.res,401,"UNAUTHENTICATED","\u9700\u8981\u767B\u5F55\u540E\u624D\u80FD\u7ED1\u5B9A\u6267\u884C\u5F15\u64CE");return}let n=await this.serverServices.execution.resolveMachineToken(e.machineToken.trim(),r);if(!n){S(this.ctx.res,404,"MACHINE_NOT_FOUND","\u6267\u884C\u5F15\u64CE\u4E0D\u5B58\u5728\u6216 token \u5DF2\u5931\u6548");return}await this.serverServices.execution.bindProjectMachine(this.ctx.state.project.id,n),g(this.ctx.res,{ok:!0,machineToken:e.machineToken.trim()})}async getAgents(){let e=this.ctx.state.project;this.ctx.respond=!1;let r;try{r=await qr(_(e),{lenientEnv:!0})}catch(s){g(this.ctx.res,{registry:null,agents:[],listError:v(s)});return}let n=r.identity?.registry??null;if(!n){g(this.ctx.res,{registry:null,agents:[]});return}try{let s=await ur({registry:n});g(this.ctx.res,{registry:n,agents:s})}catch(s){g(this.ctx.res,{registry:n,agents:[],listError:v(s)})}}async createAgent(){let e=this.ctx.state.project,r=await A(this.ctx.req);if(this.ctx.respond=!1,!r?.name||!r.name.trim()){S(this.ctx.res,422,"INVALID_INPUT","\u667A\u80FD\u4F53\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");return}let s=(await qr(_(e),{lenientEnv:!0})).identity?.registry;if(!s){S(this.ctx.res,409,"NO_REGISTRY","\u8BE5\u9879\u76EE\u672A\u914D\u7F6E identity.registry\uFF0C\u767B\u8BB0\u8868\u7BA1\u7406\u9762\u4E0D\u53EF\u7528\u3002");return}let{recordId:a}=await dr({registry:s,input:r});g(this.ctx.res,{ok:!0,recordId:a})}async listFiles(){let e=this.ctx.state.project,r=await k(e);this.ctx.respond=!1,g(this.ctx.res,{project:e,files:r})}async replaceFiles(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,s=await A(this.ctx.req);if(this.ctx.respond=!1,!Array.isArray(s.files)){S(this.ctx.res,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");return}let a=await e.projectStore.projects.replaceFiles(n,s.files,r),i=await b(n,e);g(this.ctx.res,{project:i.project,files:a})}async patchFiles(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,s=await A(this.ctx.req),a=await e.projectStore.projects.updateFiles(n,{upsert:s.upsert,remove:s.remove},r),i=await b(n,e);this.ctx.respond=!1,g(this.ctx.res,{project:i.project,files:a})}async exportProject(){let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,s=await e.projectStore.projects.exportProject(n,r),a=Ar(s),i=e.projectStore.workflows;if(i){let c=await Promise.all((await i.list(n.id,r)).map(async d=>{let u=await i.exportWorkflow(n.id,d.id,r);return{workflow:u.workflow,files:u.files}}));this.ctx.respond=!1,g(this.ctx.res,{...a,workflows:c});return}this.ctx.respond=!1,g(this.ctx.res,a)}async validate(){let e=this.ctx.state.project,r=await Ro({workDir:e.dir,configPath:ee.join(e.dir,"aitable-workflow.config.yml"),workflows:[],workflowPath:ee.join(e.dir,"workflow.yml"),recipeDir:ee.join(e.dir,"recipes")});await hr(e,r),this.ctx.respond=!1,g(this.ctx.res,r)}async getWorkflow(){let e=this.ctx.state.project,r=await Do(e.dir),n=await jo(e,this.serverServices.projectStore.workflows,ie(this.ctx.query?.workflowId),O(this.ctx)),s=await Ur(n,{envSource:r}).catch(()=>Ur(n)),a=ee.join(ee.dirname(n),"recipes"),i=s.steps.map(c=>({...c,requires_agent:c.recipe?vr(a,c.recipe):!!c.prompt}));this.ctx.respond=!1,g(this.ctx.res,{workflow:{...s,steps:i}})}async resetWorkflow(){let e=await _t(this.ctx.state.project),r=await k(e);this.ctx.respond=!1,g(this.ctx.res,{project:e,files:r})}async getState(){let e=this.serverServices,r=this.ctx.state.project,n=await ke(e,r);this.ctx.respond=!1,g(this.ctx.res,n)}async updateTableId(){let e=this.serverServices;this.ctx.respond=!1,await gr(this.ctx.state.project.id,e,this.ctx.req,this.ctx.res)}};o(R,"ProjectsController"),p([Lr()],R.prototype,"ctx",2),p([Lr()],R.prototype,"serverServices",2),p([de("/")],R.prototype,"list",1),p([ge("/")],R.prototype,"create",1),p([ge("/import-zip")],R.prototype,"importZip",1),p([xo("/:projectId")],R.prototype,"remove",1),p([gt("/:projectId")],R.prototype,"updateMeta",1),p([ge("/:projectId/init")],R.prototype,"init",1),p([de("/:projectId/engine")],R.prototype,"getEngine",1),p([Cr("/:projectId/engine")],R.prototype,"bindEngine",1),p([de("/:projectId/agents")],R.prototype,"getAgents",1),p([ge("/:projectId/agents")],R.prototype,"createAgent",1),p([de("/:projectId/files")],R.prototype,"listFiles",1),p([Cr("/:projectId/files")],R.prototype,"replaceFiles",1),p([gt("/:projectId/files")],R.prototype,"patchFiles",1),p([de("/:projectId/export")],R.prototype,"exportProject",1),p([ge("/:projectId/validate")],R.prototype,"validate",1),p([de("/:projectId/workflow")],R.prototype,"getWorkflow",1),p([ge("/:projectId/reset-workflow")],R.prototype,"resetWorkflow",1),p([de("/:projectId/state")],R.prototype,"getState",1),p([gt("/:projectId/table-id")],R.prototype,"updateTableId",1),R=p([Po("/api/projects")],R);async function jo(t,e,r,n){let s=r&&/^[A-Za-z0-9_-]+$/.test(r)?r:null;if(s&&e){let c=await e.resolve(t.id,s,n);return ee.join(t.dir,c.templatePath)}let a=await k(t);if(s){let c=`workflows/${s}/workflow.yml`;if(a.some(d=>d.path===c))return ee.join(t.dir,c)}if(a.some(c=>c.path==="workflow.yml"))return ee.join(t.dir,"workflow.yml");let i=a.find(c=>/^workflows\/[^/]+\/workflow\.ya?ml$/.test(c.path));return ee.join(t.dir,i?.path??"workflow.yml")}o(jo,"resolvePreviewWorkflowPath");import To from"path";import{Controller as Oo,Del as Io,Get as Br,Inject as $r,Patch as ko,Post as Eo,Put as bo}from"@midwayjs/core";import{loadWorkflowTemplate as Ao}from"aitable-workflow-core";var N=class{ctx;serverServices;guardNotConfigured(){return this.serverServices.projectStore.workflows?!1:(this.ctx.respond=!1,S(this.ctx.res,501,"WORKFLOWS_NOT_CONFIGURED","\u5DE5\u4F5C\u6D41\u6301\u4E45\u5316\u672A\u914D\u7F6E\uFF08\u9700\u8981 AITABLE_DB_URL\uFF09"),!0)}async list(){let e=this.serverServices,r=this.ctx.state.project;if(!e.projectStore.workflows){this.ctx.respond=!1,g(this.ctx.res,{workflows:await _o(r)});return}let n=O(this.ctx);this.ctx.respond=!1,g(this.ctx.res,{workflows:await e.projectStore.workflows.list(r.id,n)})}async create(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,s=await A(this.ctx.req);if(!s.name||!s.name.trim()){this.ctx.respond=!1,S(this.ctx.res,422,"INVALID_INPUT","\u5DE5\u4F5C\u6D41\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");return}let a=await e.projectStore.workflows.create(n.id,{name:s.name,templatePath:s.templatePath,files:s.files},r);await b(n,e);let i={workflow:a.workflow};a.files&&(i.files=a.files),a.warnings&&a.warnings.length>0&&(i.warnings=a.warnings),this.ctx.respond=!1,g(this.ctx.res,i)}async get(){let e=this.serverServices,r=this.ctx.state.project,n=this.ctx.params.workflowId??"";if(!e.projectStore.workflows){let i=await Fo(r,n);if(this.ctx.respond=!1,!i){S(this.ctx.res,404,"WORKFLOW_NOT_FOUND","\u5DE5\u4F5C\u6D41\u4E0D\u5B58\u5728");return}g(this.ctx.res,i);return}let s=O(this.ctx),a=await e.projectStore.workflows.exportWorkflow(r.id,n,s);this.ctx.respond=!1,g(this.ctx.res,{workflow:a.workflow,files:a.files})}async remove(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project;if(e.runtime.runSessions.has(n.id)){this.ctx.respond=!1,S(this.ctx.res,409,"project_busy","\u9879\u76EE\u5B58\u5728\u6D3B\u8DC3\u7684\u8FD0\u884C\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u5220\u9664\u5DE5\u4F5C\u6D41");return}let s=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r);await e.projectStore.workflows.delete(s,r),await b(n,e),this.ctx.respond=!1,g(this.ctx.res,{ok:!0,id:s.id})}async replaceFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,s=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r),a=await A(this.ctx.req);if(!Array.isArray(a.files)){this.ctx.respond=!1,S(this.ctx.res,422,"INVALID_INPUT","files \u4E0D\u80FD\u4E3A\u7A7A");return}let i=await e.projectStore.workflows.replaceFiles(s,a.files,r);await b(n,e),this.ctx.respond=!1,g(this.ctx.res,{workflow:s,files:i})}async updateFiles(){if(this.guardNotConfigured())return;let e=this.serverServices,r=O(this.ctx),n=this.ctx.state.project,s=await e.projectStore.workflows.resolve(n.id,this.ctx.params.workflowId??"",r),a=await A(this.ctx.req),i=await e.projectStore.workflows.updateFiles(s,{upsert:a.upsert,remove:a.remove},r);await b(n,e),this.ctx.respond=!1,g(this.ctx.res,{workflow:s,files:i})}};o(N,"WorkflowsController"),p([$r()],N.prototype,"ctx",2),p([$r()],N.prototype,"serverServices",2),p([Br("/:projectId/workflows")],N.prototype,"list",1),p([Eo("/:projectId/workflows")],N.prototype,"create",1),p([Br("/:projectId/workflows/:workflowId")],N.prototype,"get",1),p([Io("/:projectId/workflows/:workflowId")],N.prototype,"remove",1),p([bo("/:projectId/workflows/:workflowId/files")],N.prototype,"replaceFiles",1),p([ko("/:projectId/workflows/:workflowId/files")],N.prototype,"updateFiles",1),N=p([Oo("/api/projects")],N);async function _o(t){let e=await k(t),r=Jr(e);return(await Promise.all(r.map(s=>Gr(t,s,e)))).sort((s,a)=>s.name.localeCompare(a.name))}o(_o,"listLocalWorkflows");async function Fo(t,e){let r=await k(t),n=Jr(r).find(c=>Vr(c)===e);if(!n)return null;let s=await Gr(t,n,r),a=Hr(n),i=r.filter(c=>zr(c.path,n)).map(c=>({...c,path:c.path.slice(a.length)}));return{workflow:s,files:i}}o(Fo,"exportLocalWorkflow");function Jr(t){return t.map(e=>e.path).filter(e=>e==="workflow.yml"||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(e))}o(Jr,"localWorkflowTemplatePaths");function Vr(t){return t==="workflow.yml"?"main":t.split("/")[1]??"main"}o(Vr,"localWorkflowId");function Hr(t){return t==="workflow.yml"?"":t.replace(/workflow\.ya?ml$/,"")}o(Hr,"workflowBase");function zr(t,e){let r=Hr(e);return r?t.startsWith(r):t==="workflow.yml"||t.startsWith("recipes/")}o(zr,"belongsToWorkflow");async function Gr(t,e,r){let n=Vr(e),s=await Ao(To.join(t.dir,e)).catch(i=>(console.warn(`\u52A0\u8F7D\u672C\u5730\u5DE5\u4F5C\u6D41\u6A21\u677F\u5931\u8D25 [${e}]\uFF1A`,i instanceof Error?i.message:String(i)),null)),a=r.filter(i=>zr(i.path,e)).length;return{id:n,projectId:t.id,name:s?.meta.name??n,domain:s?.meta.domain,templatePath:e,tableId:s?.tracker?.table_id,fileCount:a,createdAt:t.createdAt,updatedAt:t.updatedAt}}o(Gr,"buildLocalWorkflow");import{Controller as fi,Get as We,Inject as an,Post as te}from"@midwayjs/core";import{collectDesignContext as Yr,runDesign as No,runClarifyRound as Mo,syncFieldsFromWorkflow as Wo,summarizeForms as Lo,validateFormAnswers as Co,pruneHiddenAnswers as Uo,nextFor as qo,isDesignGenerating as Zr,logger as Ne}from"aitable-workflow-core";var Fe=class{static{o(this,"DesignEventBuffer")}capacity;events=[];seq=0;constructor(e=100){this.capacity=e>0?e:100}push(e){this.seq+=1;let r={seq:this.seq,event:e};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(e){return e===void 0||Number.isNaN(e)?[...this.events]:this.events.filter(r=>r.seq>e)}};var Qr={hasRunSession:o(()=>!1,"hasRunSession")};async function Bo(t,e,r){return{...(await e.getState(t)).stages.design,state:r,next:qo({projectId:t.id,stage:"design",state:r,facts:K(t.id,"design",Qr)})}}o(Bo,"currentEntry");function wt(t,e,r){return G.open({project:t,stage:"design",store:e,driver:r,facts:o(()=>K(t.id,"design",Qr),"facts")})}o(wt,"designWriter");async function Xr(t,e,r,n,s){let a=await I(e,t),i=await wt(a,r,"design.discovery"),c=i.state;if(Zr(c)){S(n,409,"DESIGN_IN_PROGRESS","\u5DE5\u4F5C\u6D41\u8BBE\u8BA1\u6B63\u5728\u751F\u6210\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u672C\u8F6E\u7ED3\u675F\u518D\u91CD\u65B0\u6F84\u6E05\u9700\u6C42\u3002");return}try{await i.advance({phase:"clarify_probing"});let d=await Yr({configPath:_(a),yes:!0}),u=d.agentType?await Mo(d,{...await en(s,a,d.agentType),timeoutMs:d.agentTimeoutMs,interactive:!0,judgeOnly:!0}):void 0;if(!u?.form){let m=d.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",l=await i.advance({phase:"precheck",confirmed:{form:{id:"clarify",title:"\u65E0\u9700\u6F84\u6E05",questions:[]},answers:{},clarifications:m,summary:m,...u?.sessionId?{agentSessionId:u.sessionId}:{}}});g(n,{stageState:l});return}let w=await i.advance({phase:"clarify_awaiting",form:u.form,answers:$o(u.form),...u.sessionId?{agentSessionId:u.sessionId}:{}});g(n,{stageState:w})}catch(d){let u=await i.advance({phase:"clarify_failed",error:{code:"DESIGN_PRECHECK_FAILED",message:v(d),retryable:!0,details:B(d)}});g(n,{stageState:u,error:le(d)},500)}}o(Xr,"handleDesignDiscovery");async function en(t,e,r){let n=await t.buildDesignExecutor({projectId:e.id,agent:r,projectDir:e.dir});return n?{executor:n}:{}}o(en,"relayExecutorFor");function $o(t){let e=Object.fromEntries(t.questions.map(r=>[r.id,r.defaultValue??(r.type==="checkbox"?[]:"")]));return Uo(t,e)}o($o,"seedAnswers");async function tn(t,e,r,n,s){let a=await I(e,t),i=await wt(a,r,"design.discovery"),c=i.state;if(Zr(c)){g(s,{stageState:await Bo(a,r,c)});return}if(c?.phase!=="clarify_awaiting"){S(s,409,"DISCOVERY_NOT_READY","\u8BF7\u5148\u751F\u6210\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u786E\u8BA4 Design \u8F93\u5165\u3002");return}let d=n.answers,u=d&&Object.keys(d).length>0?d:c.answers,w=Co(c.form,u);if(w.length>0){S(s,400,"DISCOVERY_INVALID_ANSWERS",`\u9700\u6C42\u6F84\u6E05\u7B54\u6848\u4E0D\u5B8C\u6574\uFF1A${w.map(f=>f.message).join("\uFF1B")}`,{issues:w});return}let m=Lo([{form:c.form,answers:u}]),l=await i.advance({phase:"precheck",confirmed:{form:c.form,answers:u,clarifications:m,summary:m.replace(/\s+/g," ").trim(),...c.agentSessionId?{agentSessionId:c.agentSessionId}:{}}});g(s,{stageState:l})}o(tn,"handleDesignDiscoveryConfirm");function rn(t,e){let r=$t(t);if(!r){g(e,{events:[],lastSeq:0,live:!1,retained:!1});return}let n=r.buffer.replayAfter(void 0);g(e,{events:n.map(s=>s.event),lastSeq:r.buffer.cursor,live:r.live,retained:!0})}o(rn,"handleDesignEventLog");async function nn(t,e,r,n,s,a){let i=await I(e,t);try{s.ensureAvailable()}catch(P){S(n,Z(P),F(P),v(P));return}let c=ne.get(i.id);if(c){ae(n);for(let P of c.buffer.replayAfter(a))at(n,P.seq,P.event);c.subscribers.add(n),n.on("close",()=>c.subscribers.delete(n));return}let d=await wt(i,r,"design.stream"),u=d.state;if(!(u?.phase==="precheck"||u?.phase==="generating"||u?.phase==="validating"||u?.phase==="syncing_schema")&&u?.phase!=="generate_failed"){S(n,409,u?.phase==="clarify_awaiting"?"DISCOVERY_NOT_CONFIRMED":"DESIGN_NOT_READY",u?.phase==="clarify_awaiting"?"\u8BF7\u5148\u786E\u8BA4\u9700\u6C42\u6F84\u6E05\u5361\u7247\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002":"\u8BF7\u5148\u5B8C\u6210\u9700\u6C42\u6F84\u6E05\uFF0C\u518D\u5F00\u59CB\u751F\u6210\u5DE5\u4F5C\u6D41\u65B9\u6848\u3002");return}let m=u.confirmed;he.add(i.id),ae(n);let l={buffer:new Fe,subscribers:new Set([n])};ne.set(i.id,l),n.on("close",()=>l.subscribers.delete(n));let f=o(P=>Jt(l,P),"send");d.emit=P=>f({type:"stage.changed",stage:"design",stageState:P});let y=Date.now(),E=y,q=0,x=[],U=[],D=o((P,M)=>{let W=Date.now(),$=W-y,J=W-E;E=W,x.push({label:P,at:new Date(W).toISOString(),elapsedMs:$,...M?{detail:M}:{}}),x.length>40&&x.shift(),d.setDiagnostics({timeline:x,recentAgentEvents:U}),Ne.info("design-runtime",P,{projectId:i.id,taskId:d.taskId,elapsedMs:$,deltaMs:J,...M?{detail:M}:{}})},"trace"),je="",Ge=!1,Ke=!1,pe=o(async()=>{if(Ge){Ke=!0;return}Ge=!0;try{do{Ke=!1;let M=(await k(i)).filter(W=>W.path!=="project.json").map(W=>`${W.path}:${W.content}`).join("|");if(M&&M!==je){je=M;let W=await L(i),$=await k(W);D(`\u540C\u6B65 ${$.length} \u4E2A\u751F\u6210\u6587\u4EF6`,{fileCount:$.length}),f({type:"design.files",files:$})}}while(Ke)}finally{Ge=!1}},"sendFileSnapshot");try{d.state&&d.state.phase!=="precheck"&&(d.state.phase!=="generate_failed"&&await d.advance({phase:"generate_failed",confirmed:m,error:{code:"DESIGN_SESSION_LOST",message:"\u4E0A\u4E00\u6B21\u751F\u6210\u7684\u8FDB\u7A0B\u5DF2\u7ED3\u675F\uFF08\u670D\u52A1\u91CD\u542F\u6216\u591A\u5B9E\u4F8B\uFF09\uFF0C\u672C\u6B21\u91CD\u65B0\u5F00\u59CB\u751F\u6210\u3002",retryable:!0}}),await d.advance({phase:"precheck",confirmed:m})),await pe();let P,M;try{D("\u8BFB\u53D6 Design \u914D\u7F6E"),M=_(i),P=await Yr({configPath:M,yes:!0}),D("Design \u914D\u7F6E\u8BFB\u53D6\u5B8C\u6210",{agent:P.agentType,timeoutMs:P.agentTimeoutMs})}catch(h){await d.advance({phase:"generate_failed",confirmed:m,error:{code:"DESIGN_PRECHECK_FAILED",message:v(h),retryable:!0,details:B(h)}}),f({type:"error",error:le(h)}),n.end();return}P.clarifications=m.clarifications,D("\u542F\u52A8 Coding Agent \u751F\u6210\u6D41\u7A0B\u65B9\u6848",{agent:P.agentType,timeoutSource:"disabled"});let W=!1,$=o(h=>{Ne.warn("design-runtime","\u9636\u6BB5\u72B6\u6001\u5199\u5165\u5931\u8D25",{projectId:i.id,error:v(h)})},"onDetachedError"),J=await No(P,{...await en(s,i,P.agentType),...m.agentSessionId?{resume:{sessionId:m.agentSessionId,answered:[{form:m.form,answers:m.answers}]}}:{},timeoutMs:null,onRoundStart:o((h,re)=>{D(`\u7B2C ${h} \u8F6E ${re?"\u4FEE\u6B63":"\u751F\u6210"}\u5F00\u59CB`,{round:h,isFix:re}),d.advanceDetached({phase:"generating",confirmed:m,round:h,isFix:re},$)},"onRoundStart"),onEvent:o(h=>{Jo(h)&&(U.push(Vo(h)),U.length>30&&U.shift(),W||(W=!0,D(`\u6536\u5230 Agent \u9996\u4E2A\u4E8B\u4EF6\uFF1A${h.type}`,{eventType:h.type})),h.type==="tool_use"&&D("Agent \u8C03\u7528\u5DE5\u5177",{toolName:h.toolName}),(h.type==="text"||h.type==="thinking")&&Date.now()-q>5e3&&(q=Date.now(),D(h.type==="thinking"?"Agent \u6B63\u5728\u63A8\u7406":"Agent \u8F93\u51FA\u5185\u5BB9",{eventType:h.type,preview:h.content?.replace(/\s+/g," ").slice(0,120)})),f({type:"design.agent_event",event:h}),(h.type==="tool_use"||h.type==="tool_result")&&pe())},"onEvent"),onAgentLifecycle:o(h=>{D(Ho(h),zo(h))},"onAgentLifecycle"),onValidationStart:o(h=>{D("\u5F00\u59CB\u6821\u9A8C\u6D41\u7A0B\u65B9\u6848\u914D\u7F6E",{round:h}),d.advanceDetached({phase:"validating",confirmed:m,round:h,errors:[]},$)},"onValidationStart"),onValidation:o((h,re)=>{D(h.valid?"\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u901A\u8FC7":`\u6D41\u7A0B\u65B9\u6848\u6821\u9A8C\u53D1\u73B0 ${h.errors.length} \u4E2A\u95EE\u9898`,{round:re,valid:h.valid,errorCount:h.errors.length}),d.setDiagnostics({timeline:x,recentAgentEvents:U,validation:h}),d.advanceDetached({phase:"validating",confirmed:m,round:re,errors:h.errors},$),pe()},"onValidation")});if(!J.success){await pe(),d.setDiagnostics({timeline:x,recentAgentEvents:U,...J.validation?{validation:J.validation}:{}}),await d.advance({phase:"generate_failed",confirmed:m,error:{code:"DESIGN_VALIDATION_FAILED",message:J.response,retryable:!0}}),await Kr(i,d,J.response),n.end();return}await d.advance({phase:"syncing_schema",confirmed:m}),D("\u540C\u6B65\u5B57\u6BB5\u8BA1\u5212\u5230\u914D\u7F6E");for(let h of P.workflows)await Wo({workflowPath:h.workflowPath,configPath:M,autoUpdate:!0}).catch(re=>(Ne.warn("design","\u5B57\u6BB5\u540C\u6B65\u5931\u8D25(\u4E0D\u963B\u65AD)",{workflow:h.id,error:v(re)}),null));await pe(),D("\u5199\u5165 Design \u4EA7\u7269\u6E05\u5355");let vn=await k(i),vt=Go(i,d,vn);await it(i,vt),d.setDiagnostics({timeline:x,recentAgentEvents:U,...J.validation?{validation:J.validation}:{}}),await d.advance({phase:"ready",confirmed:m,manifest:vt,rounds:J.rounds}),n.end()}catch(P){await pe().catch(()=>{}),d.setDiagnostics({timeline:x,recentAgentEvents:U}),await d.advance({phase:"generate_failed",confirmed:m,error:{code:F(P)==="INTERNAL_ERROR"?"DESIGN_GENERATION_FAILED":F(P),message:v(P),retryable:!0,details:B(P)}}).catch(M=>{Ne.warn("design-runtime","\u5199\u5165\u5931\u8D25\u72B6\u6001\u672A\u6210\u529F",{error:v(M)})}),await Kr(i,d,v(P)).catch(()=>{}),f({type:"error",error:le(P)}),n.end()}finally{Vt(i.id)}}o(nn,"handleDesign");function Jo(t){return t.type!=="text"&&t.type!=="thinking"?!0:typeof t.content=="string"&&t.content.trim().length>0}o(Jo,"isDisplayableAgentEvent");function Vo(t){return t.type==="tool_use"?{type:t.type,toolName:t.toolName,toolInput:t.toolInput}:t.type==="tool_result"||t.type==="error"||t.type==="text"||t.type==="thinking"?{type:t.type,content:t.content?.replace(/\s+/g," ").slice(0,240)}:{type:t.type}}o(Vo,"summarizeAgentEvent");function Ho(t){switch(t.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"}}o(Ho,"agentLifecycleMessage");function zo(t){return{provider:t.provider,phase:t.phase,elapsedMs:t.elapsedMs,...t.pid?{pid:t.pid}:{},...t.cmd?{cmd:t.cmd}:{},...t.cwd?{cwd:t.cwd}:{},...t.exitCode!==void 0?{exitCode:t.exitCode}:{}}}o(zo,"sanitizeAgentLifecycle");function Go(t,e,r){let n=r.filter(i=>Ko(i.path)).map(i=>({path:i.path,kind:Yo(i.path),checksum:we(i.content),required:Zo(i.path)})),s=n.filter(i=>i.required).map(i=>i.path),a=new Date().toISOString();return{projectId:t.id,taskId:e.taskId??"",designVersion:e.attempt,status:"ready",expected:s,generated:n,validation:{passed:!0,errors:[],warnings:[]},createdAt:e.startedAt??a,updatedAt:a}}o(Go,"buildDesignManifest");function Ko(t){return t==="workflow.yml"||t.startsWith("recipes/")||/^workflows\/[^/]+\/workflow\.ya?ml$/.test(t)||/^workflows\/[^/]+\/recipes\/.+\.(ts|js)$/.test(t)}o(Ko,"isDesignArtifactPath");function Yo(t){return t.endsWith("workflow.yml")||t.endsWith("workflow.yaml")?"workflow":"recipe"}o(Yo,"designArtifactKind");function Zo(t){return!0}o(Zo,"isRequiredDesignArtifact");async function Kr(t,e,r){let n=new Date().toISOString();await it(t,{projectId:t.id,taskId:e.taskId??"",designVersion:e.attempt,status:"invalid",expected:["workflow.yml"],generated:[],validation:{passed:!1,errors:[r],warnings:[]},createdAt:e.startedAt??n,updatedAt:n})}o(Kr,"writeInvalidDesignManifest");import oi from"path";import{runSetupTables as ii,runWithExecutor as ai,runWithDwsRunner as ci,DwsError as di,logger as Me}from"aitable-workflow-core";var Qo={singleSelect:"single_select",multipleSelect:"multiple_select",date:"datetime"},Xo={Grid:"grid",FormDesigner:"form",Kanban:"kanban",Calendar:"calendar",Gantt:"gantt"};function sn(t,e){let r=new Map,n=new Map((t.tracker.field_definitions??[]).map(c=>[c.name,c])),s=o((c,d,u="text",w)=>{if(!c?.trim()||r.has(c))return;let m=n.get(c);r.set(c,{id:ni(c),name:c,type:ri(m?.type??u),...m?.options??w?{options:m?.options??w}:{},group:d})},"addField");for(let c of e.referencedFields.userInput)s(c,"business");for(let c of e.referencedFields.output)s(c,"business");for(let c of e.referencedFields.other)s(c,"business");for(let c of t.tracker.field_definitions??[])s(c.name,"business",c.type,c.options);s(t.tracker.fields.title,"business"),s(t.tracker.fields.description,"business"),s(t.tracker.fields.state,"process","singleSelect",ti(t)),s(t.tracker.fields.current_step,"process"),s(t.tracker.fields.owner,"process","user"),s(t.tracker.fields.deadline,"process","date"),s(t.tracker.fields.event_log,"process");let a=ei(t.tracker.views??[],e).map(c=>({id:c.id,name:c.name,kind:Xo[c.type]??"grid",desc:c.description??si(c)})),i=[...r.values()];return{fieldCount:i.length,viewCount:a.length,fields:i,views:a}}o(sn,"buildSetupSchemaSummary");function ei(t,e){let r=[],n=2;for(let s of t){if(!s.for_each_step){r.push(s);continue}let a=e.steps.filter(i=>s.for_each_step==="needs_human"?!!i.needs_human:!0);for(let i of a){let c=String.fromCodePoint(9311+n);r.push({...s,id:`step_${i.id}`,name:`${c} ${i.name}`,visible_fields:[...Object.values(i.input_mapping??{}),...Object.values(i.output_mapping??{})],description:i.needs_human?.reason??s.description,for_each_step:void 0}),n++}}return r}o(ei,"expandViews");function ti(t){return[t.tracker.states.initial,...t.tracker.states.active,...t.tracker.states.terminal,t.tracker.states.blocked,t.tracker.states.review].filter((e,r,n)=>!!e&&n.indexOf(e)===r)}o(ti,"stateOptions");function ri(t){return Qo[t]??t}o(ri,"displayFieldType");function ni(t){return`fld_${t.replace(/[^\p{L}\p{N}]+/gu,"_").replace(/^_+|_+$/g,"")||"field"}`}o(ni,"fieldId");function si(t){return t.type==="FormDesigner"?"\u8868\u5355\u5F55\u5165\u89C6\u56FE":t.type==="Kanban"?t.group_by?`\u6309 ${t.group_by} \u5206\u7EC4`:"\u770B\u677F\u89C6\u56FE":t.type==="Calendar"?t.date_field?`\u6309 ${t.date_field} \u67E5\u770B`:"\u65E5\u5386\u89C6\u56FE":t.type==="Gantt"?"\u7518\u7279\u89C6\u56FE":"\u8868\u683C\u89C6\u56FE"}o(si,"viewDescription");import{runCheck as pi,writeBack as li}from"aitable-workflow-core";var ht=new Set;async function yt(t,e,r,n,s){let a=await I(e,t);try{s.ensureAvailable()}catch(l){S(n,Z(l),F(l),v(l));return}if(ht.has(a.id)){S(n,409,"SETUP_IN_PROGRESS","AI \u8868\u683C\u642D\u5EFA\u6B63\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019\u3002");return}let i=await G.open({project:a,stage:"setup",store:r,driver:"setup.stream",facts:o(()=>K(a.id,"setup",{hasRunSession:o(()=>!1,"hasRunSession")}),"facts")});ht.add(a.id),ae(n);let c=o(l=>Ee(n,l.type,l),"send");i.emit=l=>c({type:"stage.changed",stage:"setup",stageState:l});let d=o((l,f)=>{Me.info("setup",l,{projectId:a.id,taskId:i.taskId,...f?{detail:f}:{}})},"trace"),u=[],w=s.buildSetupExecutor({projectId:a.id,projectDir:a.dir}),m=await s.buildDwsRunner({projectId:a.id});try{await ai(w,async()=>{await ci(m,async()=>{await i.advance({phase:"verifying"}),d("\u5F00\u59CB\u914D\u7F6E\u6821\u9A8C");let l=await s.getProjectMachine(a.id);if(!l){await i.advance({phase:"verify_failed",error:{code:"ENGINE_NOT_BOUND",message:"\u9879\u76EE\u672A\u7ED1\u5B9A\u6267\u884C\u5F15\u64CE\uFF0C\u8BF7\u5148\u5728\u914D\u7F6E\u9636\u6BB5\u9009\u62E9\u6267\u884C\u5F15\u64CE",retryable:!0}}),d("\u6267\u884C\u5F15\u64CE\u672A\u7ED1\u5B9A"),n.end();return}if(!s.isMachineOnline(l)){await i.advance({phase:"verify_failed",error:{code:"ENGINE_OFFLINE",message:`\u7ED1\u5B9A\u7684\u6267\u884C\u5F15\u64CE\uFF08${l}\uFF09\u5F53\u524D\u79BB\u7EBF\uFF0C\u8BF7\u542F\u52A8 daemon \u540E\u91CD\u8BD5`,retryable:!0}}),d("\u6267\u884C\u5F15\u64CE\u79BB\u7EBF",{machineId:l}),n.end();return}let y=_(a);try{let{runCheck:x}=await import("aitable-workflow-core"),U=l?(s.listMachines()??[]).find(je=>je.machineId===l):void 0,D=await x({configPath:y,executionRuntimes:U?.runtimes});if(!D.ok){await i.advance({phase:"verify_failed",error:{code:"CONFIG_VERIFY_FAILED",message:`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25\uFF1A${D.summary.errors} \u9879\u963B\u65AD`,retryable:!0,details:D},verifyResult:D}),d("\u914D\u7F6E\u6821\u9A8C\u5931\u8D25",{errors:D.summary.errors}),n.end();return}d("\u914D\u7F6E\u6821\u9A8C\u901A\u8FC7",{modules:D.summary.passedModules,warnings:D.summary.warnings})}catch(x){await i.advance({phase:"verify_failed",error:{code:"CONFIG_VERIFY_ERROR",message:`\u914D\u7F6E\u6821\u9A8C\u5F02\u5E38\uFF1A${v(x)}`,retryable:!0}}),d("\u914D\u7F6E\u6821\u9A8C\u5F02\u5E38",{error:v(x)}),n.end();return}await i.advance({phase:"preflight"}),d("\u52A0\u8F7D\u914D\u7F6E\u4E0E\u5DE5\u4F5C\u6D41\u6A21\u677F"),await i.advance({phase:"provisioning_table"});let E=await ii({config:_(a),baseName:a.title,log:o(x=>d(x),"log")});await i.advance({phase:"syncing_schema",warnings:[]}),d("\u521B\u5EFA\u5B57\u6BB5\u548C\u89C6\u56FE\u5B8C\u6210\uFF0C\u6C47\u603B\u5404\u8868\u7ED3\u6784");let q=E.tables.map(x=>({workflowId:x.workflowId,label:x.label,baseId:x.baseId,tableId:x.tableId,tableUrl:Nt(x.baseId,x.tableId),schema:sn(x.perSettings,x.workflow)}));u.push(...E.tables.flatMap(x=>x.warnings)),await L(a),await i.advance({phase:"ready",tables:q,warnings:u}),n.end()})})}catch(l){let f=o(async y=>{try{await i.advance(y)}catch(E){Me.warn("setup","\u5931\u8D25\u76F8\u53D8\u88AB\u72B6\u6001\u673A\u62D2\u7EDD\uFF0C\u4FDD\u7559\u539F\u843D\u76D8\u72B6\u6001",{projectId:a.id,currentPhase:i.state?.phase??null,rejected:v(E),original:v(l)})}},"settle");if(ui(l)){await f({phase:"auth_awaiting",error:{code:"SETUP_AUTH_REQUIRED",message:`\u6388\u6743\u6216\u6743\u9650\u4E0D\u8DB3\uFF1A${v(l)}`,retryable:!0,details:{help:"\u8BF7\u6267\u884C dws auth login\uFF0C\u5E76\u786E\u8BA4\u5F53\u524D\u8D26\u53F7\u53EF\u8BBF\u95EE\u76EE\u6807 Base/Table\u3002"}}}),n.end();return}await f({phase:"failed",error:{code:F(l),message:v(l),retryable:!0,details:B(l)}}),c({type:"error",error:le(l)}),n.end()}finally{ht.delete(a.id)}}o(yt,"handleSetup");function ui(t){let e=v(t).toLowerCase(),r=t instanceof di?t.stderr.toLowerCase():"",n=`${e} ${r}`;return["auth","login","permission","unauthorized","forbidden","access denied","does not have","org_doc_token_mismatch"].some(s=>n.includes(s))}o(ui,"isSetupAuthBlocker");async function on(t,e,r,n,s){let a=await I(e,t),i=_(a);try{let c="";for await(let l of r)c+=l;let d={};if(c.trim())try{d=JSON.parse(c)}catch{S(n,400,"INVALID_JSON","\u8BF7\u6C42\u4F53 JSON \u89E3\u6790\u5931\u8D25");return}if(d.patches&&d.patches.length>0){let l=oi.dirname(i);for(let f of d.patches)try{let y=f.value,E=typeof y=="string"?y:JSON.stringify(y)??"";await li(f.writeTarget,E,l)}catch(y){Me.warn("setup-verify","\u5199\u56DE\u914D\u7F6E\u5931\u8D25",{projectId:a.id,writeTarget:f.writeTarget,error:v(y)})}}let u=await s.getProjectMachine(a.id),w=u?(s.listMachines()??[]).find(l=>l.machineId===u):void 0,m=await pi({configPath:i,executionRuntimes:w?.runtimes});n.setHeader("Content-Type","application/json"),n.statusCode=200,n.end(JSON.stringify(m))}catch(c){Me.error("setup-verify","\u914D\u7F6E\u6821\u9A8C\u5931\u8D25",{projectId:a.id,error:v(c)}),S(n,500,"VERIFY_FAILED",`\u914D\u7F6E\u6821\u9A8C\u5931\u8D25: ${v(c)}`)}}o(on,"handleSetupVerify");var T=class{ctx;serverServices;async taskAction(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project,n=this.ctx.params.stage??"",s=this.ctx.params.taskAction??"",a=s==="start"||s==="continue"||s==="retry";if(a&&n==="setup"){await b(r,e),await yt(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution);return}if(a&&n==="run"){await b(r,e);let i=await sr(e,r.id);await(await ce(e,r.id,i)).start(r.id,this.ctx.res);return}S(this.ctx.res,404,"NOT_FOUND","\u63A5\u53E3\u4E0D\u5B58\u5728")}async designDiscovery(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await b(r,e),await Xr(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution)}async designDiscoveryConfirm(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await b(r,e);let n=await A(this.ctx.req);await tn(r.id,e.workspace,e.projectStore.instances,n,this.ctx.res)}async design(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await b(r,e);let n=new URL(this.ctx.req.url??"/","http://localhost"),s=Ht(n,this.ctx.req);await nn(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution,s),await ve(e,r,"design")}async designEvents(){this.ctx.respond=!1,rn(this.ctx.state.project.id,this.ctx.res)}async setup(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await b(r,e),await yt(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution),await ve(e,r,"setup")}async setupVerify(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await on(r.id,e.workspace,this.ctx.req,this.ctx.res,e.execution)}async runHumanAction(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project;await b(r,e),await wr(r.id,e.workspace,e.projectStore.instances,e.runtime,this.ctx.params.recordId??"",this.ctx.req,this.ctx.res)}async run(){this.ctx.respond=!1;let e=this.serverServices,r=this.ctx.state.project,n;try{let s=await A(this.ctx.req);n=await ce(e,r.id,nr(s.runMode))}catch(s){S(this.ctx.res,Z(s),F(s),v(s));return}await b(r,e),await n.start(r.id,this.ctx.res)}async runStop(){let r=await(await ce(this.serverServices,this.ctx.state.project.id)).stop(this.ctx.state.project.id);this.ctx.respond=!1,g(this.ctx.res,r)}async runStatus(){let r=await(await ce(this.serverServices,this.ctx.state.project.id)).status(this.ctx.state.project.id);this.ctx.respond=!1,g(this.ctx.res,r)}async runRecords(){let e=Number(ie(this.ctx.query?.limit)),r=Number.isInteger(e)&&e>0?e:void 0,s=await(await ce(this.serverServices,this.ctx.state.project.id)).listRecords(this.ctx.state.project.id,{limit:r});this.ctx.respond=!1,g(this.ctx.res,s)}async runEvents(){let e=Number(ie(this.ctx.query?.afterSeq)),r=Number(ie(this.ctx.query?.limit)),n=Number.isInteger(e)&&e>=0?e:0,s=Number.isInteger(r)&&r>0?Math.min(1e3,r):void 0,i=await(await ce(this.serverServices,this.ctx.state.project.id)).listEvents(this.ctx.state.project.id,{afterSeq:n,limit:s});this.ctx.respond=!1,g(this.ctx.res,i)}};o(T,"StagesController"),p([an()],T.prototype,"ctx",2),p([an()],T.prototype,"serverServices",2),p([te("/:projectId/tasks/:stage/:taskAction")],T.prototype,"taskAction",1),p([te("/:projectId/design/discovery")],T.prototype,"designDiscovery",1),p([te("/:projectId/design/discovery/confirm")],T.prototype,"designDiscoveryConfirm",1),p([te("/:projectId/design")],T.prototype,"design",1),p([We("/:projectId/design/events")],T.prototype,"designEvents",1),p([te("/:projectId/setup")],T.prototype,"setup",1),p([te("/:projectId/setup/verify")],T.prototype,"setupVerify",1),p([te("/:projectId/run/records/:recordId/human-action")],T.prototype,"runHumanAction",1),p([te("/:projectId/run")],T.prototype,"run",1),p([te("/:projectId/run/stop")],T.prototype,"runStop",1),p([We("/:projectId/run/status")],T.prototype,"runStatus",1),p([We("/:projectId/run/records")],T.prototype,"runRecords",1),p([We("/:projectId/run/events")],T.prototype,"runEvents",1),T=p([fi("/api/projects")],T);import*as ze from"@midwayjs/core";import*as Vi from"@midwayjs/koa";import{createApp as qi,logger as Bi}from"aitable-workflow-core";var Ce=class{static{o(this,"LocalProjectRepository")}workspace;constructor(e){this.workspace=e}async create(e,r){let n=await At(this.workspace),s=[];if(r?.files&&r.files.length>0){let a=await _e(n,r.files);s.push(...a.warnings);let i=await L(n);return r.title&&r.title.trim()&&(i=await fe(i,{title:r.title.trim()})),{...i,files:a.written,warnings:s}}if(r?.title&&r.title.trim()){let a=await fe(n,{title:r.title.trim()});return s.length?{...a,warnings:s}:{...a}}return s.length?{...n,warnings:s}:{...n}}async list(e){return ot(this.workspace)}async resolve(e,r){return I(this.workspace,e)}async updateMeta(e,r,n){return fe(e,r)}async delete(e,r){await Te(e)}async updateFiles(e,r,n){return r.remove&&r.remove.length>0&&await kr(e,r.remove),r.upsert&&r.upsert.length>0&&await _e(e,r.upsert),await L(e),k(e)}async replaceFiles(e,r,n){return await Er(e,r),await L(e),k(e)}async exportProject(e,r){return br(e)}async syncHotFields(){}};import{randomUUID as mi}from"crypto";import{mkdir as gi,readFile as wi,rm as hi,writeFile as yi}from"fs/promises";import Re from"path";import{applyRunExecutionEvent as Si,emptyProjectState as vi,mergeStageIntoState as cn,normalizeProjectState as Pi,patchRunSnapshotRecord as xi,recoverDesignFromArtifacts as Ri,stageStateOf as Di}from"aitable-workflow-core";var Ue=new Map,ji=/^[a-zA-Z0-9_-]+$/,qe=class{static{o(this,"LocalWorkflowInstanceStore")}workspace;constructor(e){this.workspace=e}getState(e){return ue(e)}getRecoverableState(e){return Ai(e)}createStageIdentity(e,r){return Ii(e,r)}putStageState(e,r,n){return ki(e,r,n)}appendRunSnapshotEvent(e,r){return Ei(e,r)}async listRunEvents(e,r={}){let s=(await ue(e)).runSnapshot?.logs??[],a=r.afterSeq??0,i=Math.min(1e3,r.limit??200),c=s.map((d,u)=>({seq:d.seq??u+1,type:"run.log",itemId:d.itemId,stepId:d.stepId,payload:{level:d.level,text:d.text,logId:d.id},at:new Date(d.ts).toISOString()})).filter(d=>d.seq>a).slice(0,i);return{events:c,lastSeq:c.at(-1)?.seq??a}}async resetRunEvents(e){}updateRunSnapshotRecord(e,r,n,s){return bi(e,r,n,s)}deleteProjectState(e){return Ti(this.workspace,e)}};async function Ti(t,e){ln(e);let r=Oi(t,e);await hi(Re.join(r,"runtime"),{recursive:!0,force:!0})}o(Ti,"deleteProjectState");function Oi(t,e){return ln(e),Re.join(t.projectsRoot,e)}o(Oi,"projectDir");async function Ii(t,e){let n=((await ue(t)).stages[e]?.identity.attempt??0)+1,s=new Date().toISOString();return{id:`task_${mi().slice(0,8)}`,projectId:t.id,stage:e,attempt:n,startedAt:s,updatedAt:s}}o(Ii,"createStageIdentity");async function ki(t,e,r){return Be(t,async()=>{let n=await ue(t),s=cn(n,e,r);return await De(t,s),s})}o(ki,"putStageState");async function ue(t){await pn(t);let e=await wi(un(t),"utf8").catch(()=>"");if(e.trim()){let r=Fi(e),n=Pi(t,r);return r.repaired&&await De(t,n),n}return vi(t)}o(ue,"getState");async function Ei(t,e){return Be(t,async()=>{let r=await ue(t),n=Si(r.runSnapshot??{records:[],logs:[]},e),s={...r,runSnapshot:n,updatedAt:new Date().toISOString()};return await De(t,s),s})}o(Ei,"appendRunSnapshotEvent");async function bi(t,e,r,n){return Be(t,async()=>{let s=await ue(t);if(!s.runSnapshot)return s;let a={...s,runSnapshot:xi(s.runSnapshot,e,r,n),updatedAt:new Date().toISOString()};return await De(t,a),a})}o(bi,"updateRunSnapshotRecord");async function Ai(t){return Be(t,async()=>{let e=await ue(t),r=Di(e,"design"),n=await Ft(t),s=Ri(r,n);if(!s)return e;let a=e.stages.design;if(!a)return e;let i=new Date().toISOString(),c=cn(e,"design",{...a,state:s,identity:{...a.identity,updatedAt:i,completedAt:a.identity.completedAt??i}});return await De(t,c),c})}o(Ai,"getRecoverableState");function dn(t){return Re.join(t.dir,"runtime")}o(dn,"runtimeDir");function _i(t){return Re.join(dn(t),"artifacts")}o(_i,"artifactsDir");function un(t){return Re.join(dn(t),"state.json")}o(un,"statePath");async function pn(t){await gi(_i(t),{recursive:!0})}o(pn,"ensureRuntimeDirs");async function De(t,e){await pn(t),await yi(un(t),`${JSON.stringify(e,null,2)}
17
+ `,"utf8")}o(De,"writeProjectState");async function Be(t,e){let r=t.dir||t.id,s=(Ue.get(r)??Promise.resolve()).catch(()=>{}).then(e),a=s.then(()=>{},()=>{});Ue.set(r,a);try{return await s}finally{Ue.get(r)===a&&Ue.delete(r)}}o(Be,"withProjectStateWrite");function Fi(t){try{return JSON.parse(t)}catch(e){let r=Ni(t);if(!r)throw e;return{...JSON.parse(r),repaired:!0}}}o(Fi,"parseProjectStateJson");function Ni(t){let e=t.indexOf("{");if(e<0)return null;let r=0,n=!1,s=!1;for(let a=e;a<t.length;a+=1){let i=t[a];if(n){s?s=!1:i==="\\"?s=!0:i==='"'&&(n=!1);continue}if(i==='"')n=!0;else if(i==="{")r+=1;else if(i==="}"&&(r-=1,r===0))return t.slice(e,a+1)}return null}o(Ni,"extractFirstJsonObject");function ln(t){if(!ji.test(t))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${t}`),{code:"INVALID_PROJECT_ID"})}o(ln,"assertProjectId");var $e=class{static{o(this,"LocalProjectStore")}projects;instances;workflows;constructor(e){this.projects=new Ce(e),this.instances=new qe(e)}async prepareWorkdir(e,r){return{project:await L(e),materialized:0,warnings:[]}}async commitWorkdir(e,r){}async cascadeDelete(e){}};import{detectInstalledCodingAgents as Mi}from"aitable-workflow-core";import{hostname as Wi,platform as Li}from"os";var St="local",Ci=3e4;function Ui(t,e=Date.now()){return{machineId:St,runtimes:t.map(r=>r.id),hasDws:!0,hostname:Wi(),os:Li(),lastSeen:e}}o(Ui,"buildLocalMachineInfo");var Je=class{static{o(this,"LocalExecutionBackend")}kind="local";runMode="local";localMachineCache=null;ensureAvailable(){}async buildDesignExecutor(){}buildSetupExecutor(){}async buildRunExecutor(){}buildDwsRunner(e){return Promise.resolve(void 0)}listMachines(){let e=Date.now();if(!this.localMachineCache||e-this.localMachineCache.at>Ci){let r=[];try{r=Mi()}catch{r=[]}this.localMachineCache={info:Ui(r,e),at:e}}return[this.localMachineCache.info]}isMachineOnline(e){return e===St}async getProjectMachine(){return St}async resolveMachineToken(){return null}async getMachineToken(){return null}async bindProjectMachine(){}async unbindProjectMachine(){}};var Ve=class{static{o(this,"LocalIdentityService")}authRequired=!1;async resolveIdentity(e){let r=xt(e);return{credential:r?"api-token":"none",authenticated:r,actor:this.resolveActorId(e)}}resolveActorId(e){let r=e.headers["x-actor-id"],n=Array.isArray(r)?r[0]:r;return n?.trim()?{actorId:n.trim()}:{}}};function fn(t={}){let e=t.workspace??bt({dataRoot:t.dataRoot});return{workspace:e,runtime:Qt(t.appFactory??((r,n)=>qi(r,{onRunEvent:n}))),projectStore:t.projectStore??new $e(e),execution:t.execution??new Je,identityService:t.identityService??new Ve,webRoot:t.webRoot}}o(fn,"createServerServices");function mn(t=process.env){let e=t.AITABLE_RELAY_BOOTSTRAP_KEY;return typeof e=="string"&&e.trim()!==""?(Bi.warn("server","AITABLE_RELAY_BOOTSTRAP_KEY \u5DF2\u5E9F\u5F03\u5E76\u88AB\u5FFD\u7565\uFF1Abootstrap \u8BA4\u8BC1\u5DF2\u79FB\u9664\uFF0C\u8BF7\u5728\u8D26\u53F7\u4E2D\u5FC3\u521B\u5EFA\u6267\u884C\u5F15\u64CE\u5E76\u4F7F\u7528\u5176 machine token"),!0):!1}o(mn,"warnDeprecatedBootstrapKey");var $i="127.0.0.1",up=8787;function He(t){if(typeof t!="string")return;let e=t.trim();return e||void 0}o(He,"readEnvString");function Ji(t){let e=He(t);if(e===void 0)return;let r=Number.parseInt(e,10);return Number.isFinite(r)&&r>0?r:void 0}o(Ji,"readEnvPort");function gn(t={},e=process.env){let r=t.host??He(e.AITABLE_WORKFLOW_HOST)??$i,n=t.port??Ji(e.AITABLE_WORKFLOW_PORT)??8787,s=t.dataRoot??He(e.AITABLE_WORKFLOW_DATA_DIR)??void 0,a=t.webRoot??He(e.AITABLE_WORKFLOW_WEB_ROOT)??void 0;return{host:r,port:n,dataRoot:s,webRoot:a}}o(gn,"resolveServeConfig");async function gp(t={}){mn();let e=t.silent??process.env.VITEST==="true",r=gn({port:t.port,host:t.host,dataRoot:t.dataRoot,webRoot:t.webRoot}),n=t.services??fn({dataRoot:r.dataRoot,appFactory:t.appFactory,webRoot:r.webRoot}),s=await Hi(n,r.host,r.port,{loggerFactory:t.loggerFactory,silent:e});return e||(console.log(`aitable-workflow server listening on http://${r.host}:${r.port}`),console.log(`data root: ${n.workspace.dataRoot}`)),s}o(gp,"startServer");async function Hi(t,e,r,n={}){let s=n.loggerFactory??(n.silent?Ki():void 0),a=await zi(()=>ze.initializeGlobalApplicationContext({imports:[Vi,Le],moduleDetector:!1,...s?{loggerFactory:s}:{},globalConfig:{keys:["aitable-workflow"],koa:{port:r,hostname:e},bodyParser:{enable:!1}}}));a.registerObject("serverServices",t);let i=await a.getAsync(ze.HTTP_SERVER_KEY);return await Gi(i),i}o(Hi,"bootMidwayKoa");var wn=Promise.resolve();async function zi(t){let e=o(async()=>{let n=process.env.MIDWAY_HTTP_PORT;delete process.env.MIDWAY_HTTP_PORT;try{return await t()}finally{n===void 0?delete process.env.MIDWAY_HTTP_PORT:process.env.MIDWAY_HTTP_PORT=n}},"task"),r=wn.then(e,e);return wn=r,r}o(zi,"withoutLeakedMidwayPortEnv");function Gi(t){return t.listening?Promise.resolve():new Promise((e,r)=>{let n=o(()=>{t.removeListener("error",s),e()},"onListening"),s=o(a=>{t.removeListener("listening",n),r(a)},"onError");t.once("listening",n),t.once("error",s)})}o(Gi,"waitUntilListening");var hn={debug:o(()=>{},"debug"),info:o(()=>{},"info"),warn:o(()=>{},"warn"),error:o(()=>{},"error"),log:o(()=>{},"log"),trace:o(()=>{},"trace")};function Ki(){return{createLogger:o(()=>hn,"createLogger"),getLogger:o(()=>hn,"getLogger"),close:o(()=>{},"close"),removeLogger:o(()=>{},"removeLogger"),getDefaultMidwayLoggerConfig:o(()=>({midwayLogger:{default:{},clients:{coreLogger:{},appLogger:{}}}}),"getDefaultMidwayLoggerConfig"),createContextLogger:o((t,e)=>e,"createContextLogger"),getClients:o(()=>new Map,"getClients"),getClientKeys:o(()=>[],"getClientKeys")}}o(Ki,"silentLoggerFactory");import yn from"path";function Sp(t){let e=yn.normalize(t).split(yn.sep).join("/");return e==="workflow.yml"?"workflow":e.startsWith("recipes/")?"recipe":"other"}o(Sp,"workflowFileKind");var Sn=class{static{o(this,"LocalProjectMutexStore")}queues=new Map;withProjectLock(e,r){let s=(this.queues.get(e)??Promise.resolve()).then(r,r);return this.queues.set(e,s),s.then(()=>{this.queues.get(e)===s&&this.queues.delete(e)},()=>{this.queues.get(e)===s&&this.queues.delete(e)}).catch(()=>{}),s}};export{$i as DEFAULT_SERVE_HOST,up as DEFAULT_SERVE_PORT,St as LOCAL_MACHINE_ID,Je as LocalExecutionBackend,Ve as LocalIdentityService,Sn as LocalProjectMutexStore,Ce as LocalProjectRepository,$e as LocalProjectStore,ct as LocalRunController,qe as LocalWorkflowInstanceStore,be as REQUESTED_RUN_MODES,Ps as RUN_REPLAY_AGENT_CAP,vs as RUN_REPLAY_EVENT_CAP,dt as RelayRunController,le as apiError,ft as assertSafeProjectPath,Dr as assertSafeRelativePath,nd as assertSafeWorkflowPath,Tr as assertWritableKind,Nt as buildAITableUrl,Ui as buildLocalMachineInfo,pr as cascadeDeleteProject,we as checksumContent,ve as commitStageOnTerminal,_ as configPath,At as createProject,Qt as createServerRuntime,fn as createServerServices,bt as createWorkspace,Te as deleteProject,F as errorCode,B as errorDetails,v as errorMessage,Qe as errorStack,Z as errorStatus,ie as firstQueryValue,Xt as handleRunRuntime,Zi as identityOf,jr as isForbiddenWritable,Ir as isLegacyViewsPath,Ms as isStageActiveFor,Or as kindOf,k as listProjectFiles,ot as listProjects,Le as midwayComponent,nr as parseRequestedRunMode,ks as pickRecoverableRunMode,b as prepareWorkdirGuarded,Ze as readBuffer,Qn as readDesignManifest,A as readJson,sr as recoverPersistedRunMode,Ie as removeLegacyViewsFiles,kr as removeProjectFiles,Er as replaceProjectFiles,_t as resetProjectWorkflow,I as resolveProject,ce as resolveRunController,gn as resolveServeConfig,O as scopeOf,S as sendError,g as sendJson,jt as sendText,Tt as sendUnauthorized,Ki as silentLoggerFactory,Ds as stampRunEvent,gp as startServer,L as touchProject,xs as trimRunReplayEvents,fe as updateProjectMeta,no as validateConfigScene,Ft as validateDesignArtifacts,mn as warnDeprecatedBootstrapKey,zi as withoutLeakedMidwayPortEnv,Sp as workflowFileKind,it as writeDesignManifest,_e as writeProjectFiles};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aitable-workflow-server",
3
- "version": "0.1.28",
3
+ "version": "0.1.29-beta.1790670244714",
4
4
  "description": "aitable-workflow 服务端(server):纯 local 的 HTTP design/setup/run API(Midway component)。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.28",
25
+ "aitable-workflow-core": "0.1.29-beta.1790670244714",
26
26
  "@midwayjs/core": "^3.20.4",
27
27
  "@midwayjs/koa": "^3.20.4",
28
28
  "fflate": "^0.8.2",