aitable-workflow-server 0.1.28 → 0.1.29-beta.1790736949347
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 +106 -15
- package/dist/index.js +11 -11
- package/package.json +2 -2
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 模式由
|
|
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" | "
|
|
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
|
|
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;
|
|
@@ -283,6 +297,8 @@ interface RelayMachineInfo {
|
|
|
283
297
|
os: string;
|
|
284
298
|
/** 认证出的属主 userId(若已知);供 per-owner 连接配额跨实例聚合。 */
|
|
285
299
|
ownerUserId?: string;
|
|
300
|
+
/** daemon 本机 trace HTTP 端口(ready 帧上报,仅在线快照携带、不落库);Web 据此渲染「本机执行详情」入口。 */
|
|
301
|
+
tracePort?: number;
|
|
286
302
|
lastSeen: number;
|
|
287
303
|
}
|
|
288
304
|
/** run 阶段调度状态快照(relay 模式,workflow-pull-claim §3.2)。契约在 core(前端共享)。 */
|
|
@@ -315,6 +331,12 @@ interface RunRecordsReader {
|
|
|
315
331
|
limit?: number;
|
|
316
332
|
}): Promise<RunRecordsPageDTO>;
|
|
317
333
|
}
|
|
334
|
+
interface RunEventsReader {
|
|
335
|
+
listEvents(projectId: string, opts?: {
|
|
336
|
+
afterSeq?: number;
|
|
337
|
+
limit?: number;
|
|
338
|
+
}): Promise<RunEventsPageDTO>;
|
|
339
|
+
}
|
|
318
340
|
interface ExecutionBackend {
|
|
319
341
|
readonly kind: "local" | "relay";
|
|
320
342
|
/**
|
|
@@ -353,14 +375,32 @@ interface ExecutionBackend {
|
|
|
353
375
|
projectDir: string;
|
|
354
376
|
agent?: AgentType;
|
|
355
377
|
}): Promise<AgentExecutor | undefined>;
|
|
356
|
-
/**
|
|
357
|
-
|
|
378
|
+
/**
|
|
379
|
+
* run 阶段 recipe 单步下发 transport(方案三 server-run-relay-recipe)。
|
|
380
|
+
* 仅在生效模式为 `server-run-relay-recipe` 时被 run-runtime 调用;
|
|
381
|
+
* local / 未启用返回 undefined → core 默认使用本地 runner。
|
|
382
|
+
*/
|
|
383
|
+
buildRunRecipeRunner?(ctx: {
|
|
384
|
+
projectId: string;
|
|
385
|
+
projectDir: string;
|
|
386
|
+
}): Promise<RecipeRunner | undefined>;
|
|
387
|
+
/**
|
|
388
|
+
* setup 阶段 dws runner;local 返回 undefined → dws 本机 spawn。
|
|
389
|
+
* relay 绑定优先(路由契约 §3.2-G3):project 绑定机在线且有 dws 用它,否则回退能力匹配。
|
|
390
|
+
*/
|
|
391
|
+
buildDwsRunner(ctx: {
|
|
392
|
+
projectId: string;
|
|
393
|
+
}): Promise<DwsRunner | undefined>;
|
|
358
394
|
/** 在线机器列表;local 合成单元素「本机运行时」(管理面 engine 选择器用)。 */
|
|
359
395
|
listMachines(): RelayMachineInfo[] | undefined;
|
|
360
396
|
/** 指定机器是否在线;local 仅本机这一台恒 true。 */
|
|
361
397
|
isMachineOnline(machineId: string): boolean;
|
|
362
398
|
/** 项目当前绑定的执行机器;local 恒返回 LOCAL_MACHINE_ID(engine 面视为 bound)。 */
|
|
363
399
|
getProjectMachine(projectId: string): Promise<string | null>;
|
|
400
|
+
/** Resolve a presented machine token to the internal ID, enforcing owner scope when supplied. */
|
|
401
|
+
resolveMachineToken(machineToken: string, ownerUserId: string): Promise<string | null>;
|
|
402
|
+
/** Return the current token for an internal machine ID; never expose the ID to Web callers. */
|
|
403
|
+
getMachineToken(machineId: string): Promise<string | null>;
|
|
364
404
|
/** 绑定项目到执行机器;local 幂等接受(只有本机可选,无需真实绑定)。 */
|
|
365
405
|
bindProjectMachine(projectId: string, machineId: string): Promise<void>;
|
|
366
406
|
/** 解绑项目的执行机器(项目删除级联);local no-op。 */
|
|
@@ -375,6 +415,8 @@ interface ExecutionBackend {
|
|
|
375
415
|
* gateway)→ `GET /run/records` 由 LocalRunController 读 runSnapshot。
|
|
376
416
|
*/
|
|
377
417
|
readonly runRecords?: RunRecordsReader;
|
|
418
|
+
/** Gateway run event ledger; local mode reads the project state file instead. */
|
|
419
|
+
readonly runEvents?: RunEventsReader;
|
|
378
420
|
}
|
|
379
421
|
/** local 模式合成出的「本机运行时」标识:无 relay,引擎即本进程所在机器。 */
|
|
380
422
|
declare const LOCAL_MACHINE_ID = "local";
|
|
@@ -392,7 +434,9 @@ declare class LocalExecutionBackend implements ExecutionBackend {
|
|
|
392
434
|
buildDesignExecutor(): Promise<AgentExecutor | undefined>;
|
|
393
435
|
buildSetupExecutor(): AgentExecutor | undefined;
|
|
394
436
|
buildRunExecutor(): Promise<AgentExecutor | undefined>;
|
|
395
|
-
buildDwsRunner(
|
|
437
|
+
buildDwsRunner(_ctx?: {
|
|
438
|
+
projectId: string;
|
|
439
|
+
}): Promise<DwsRunner | undefined>;
|
|
396
440
|
/**
|
|
397
441
|
* local 无 relay,但管理面仍要能展示「本机运行时」而非空列表(plan:engine unbound→bound)。
|
|
398
442
|
* 探测带 TTL 缓存;spawn 失败降级为空 runtimes,不让 GET 整条挂掉。
|
|
@@ -402,6 +446,8 @@ declare class LocalExecutionBackend implements ExecutionBackend {
|
|
|
402
446
|
isMachineOnline(machineId: string): boolean;
|
|
403
447
|
/** local 无「绑定」概念,直接把每个 project 的引擎视为跑在本机。 */
|
|
404
448
|
getProjectMachine(): Promise<string | null>;
|
|
449
|
+
resolveMachineToken(): Promise<string | null>;
|
|
450
|
+
getMachineToken(): Promise<string | null>;
|
|
405
451
|
/** local 恒等于本机,绑定动作是幂等接受(前端选择器只会给出 LOCAL_MACHINE_ID)。 */
|
|
406
452
|
bindProjectMachine(): Promise<void>;
|
|
407
453
|
unbindProjectMachine(): Promise<void>;
|
|
@@ -412,6 +458,7 @@ type RunExecutionEvent = Parameters<RunEventSink>[0];
|
|
|
412
458
|
type RunAppFactory = (configPath: string, onRunEvent?: (event: RunExecutionEvent) => void) => Promise<App>;
|
|
413
459
|
type RunSession = {
|
|
414
460
|
taskId: string;
|
|
461
|
+
eventSequence: number;
|
|
415
462
|
subscribers: Set<ServerResponse>;
|
|
416
463
|
events: RunEventDTO[];
|
|
417
464
|
app: App | null;
|
|
@@ -423,7 +470,7 @@ type ServerRuntime = {
|
|
|
423
470
|
};
|
|
424
471
|
type RunSseWriter = (res: ServerResponse, event: string, data: unknown) => void;
|
|
425
472
|
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>;
|
|
473
|
+
declare function handleRunRuntime(projectId: string, workspace: Workspace, projectStateStore: WorkflowInstanceStore, runtime: ServerRuntime, res: ServerResponse, writeSse: RunSseWriter, execution?: ExecutionBackend, runMode?: RunMode): Promise<void>;
|
|
427
474
|
/** 重放缓冲总上限(沿用原实现的 100)。 */
|
|
428
475
|
declare const RUN_REPLAY_EVENT_CAP = 100;
|
|
429
476
|
/** 重放缓冲里逐轮工具流的单独上限:超了先从最旧一条 agent_event 丢弃。 */
|
|
@@ -437,6 +484,12 @@ declare const RUN_REPLAY_AGENT_CAP = 60;
|
|
|
437
484
|
* 2. 再守总量上限,保持原有「最多重放 100 条」的语义不变。
|
|
438
485
|
*/
|
|
439
486
|
declare function trimRunReplayEvents(events: RunEventDTO[]): void;
|
|
487
|
+
/**
|
|
488
|
+
* 遗留③出口统一打戳:给工单/步骤/逐轮事件补产生时刻(`at`)与执行引擎标签(`engine`)。
|
|
489
|
+
* `stage.changed` / `error` 不打:前者是阶段状态机事实(自带落盘语义),后者是协议帧。
|
|
490
|
+
* 导出的纯函数:SSE 直播、重放缓冲与 runSnapshot 落盘共享同一份戳,刷新续流不假时间。
|
|
491
|
+
*/
|
|
492
|
+
declare function stampRunEvent(event: RunEventDTO, engine: RunEngineTag): RunEventDTO;
|
|
440
493
|
|
|
441
494
|
/** 带内容创建工作流的初始载荷。 */
|
|
442
495
|
type CreateWorkflowInit = {
|
|
@@ -549,7 +602,7 @@ type ServerServices = {
|
|
|
549
602
|
projectStore: ProjectStore;
|
|
550
603
|
/** ② 执行域:design/setup 的 agent/dws 执行 + 项目↔机器绑定(local spawn / relay 投递)。 */
|
|
551
604
|
execution: ExecutionBackend;
|
|
552
|
-
/** ③ 身份域:请求鉴权 + actor 归属解析(local API token / gateway JWT+
|
|
605
|
+
/** ③ 身份域:请求鉴权 + actor 归属解析(local API token / gateway JWT+machine token)。 */
|
|
553
606
|
identityService: IdentityService;
|
|
554
607
|
/** 本地 web 静态资源目录;配置时 StaticWebMiddleware 托管前端页面。 */
|
|
555
608
|
webRoot?: string;
|
|
@@ -577,7 +630,7 @@ declare function createServerServices(options?: ServerServicesOptions): ServerSe
|
|
|
577
630
|
/**
|
|
578
631
|
* 启动期一次性废弃告警:§3 已彻底移除 bootstrap 认证及其配置项。若部署环境仍配置了
|
|
579
632
|
* `AITABLE_RELAY_BOOTSTRAP_KEY`,打印 warn 提示"已废弃、被忽略",**不参与任何认证/装配逻辑**
|
|
580
|
-
*
|
|
633
|
+
* (daemon 认证由账号中心预先创建的 per-machine token 负责)。
|
|
581
634
|
*
|
|
582
635
|
* @param env 环境变量来源,缺省 `process.env`(测试可注入)。
|
|
583
636
|
* @returns 是否发出了告警(便于单测断言)。
|
|
@@ -600,7 +653,13 @@ declare class SystemController {
|
|
|
600
653
|
checkNode(): Promise<void>;
|
|
601
654
|
/**
|
|
602
655
|
* 公开只读端点:下发运行时前端配置——是否启用登录(authEnabled,前端据此决定
|
|
603
|
-
* 是否展示登录页)+ 可选 relay 网关地址(RELAY_PUBLIC_GATEWAY_URL
|
|
656
|
+
* 是否展示登录页)+ 可选 relay 网关地址(RELAY_PUBLIC_GATEWAY_URL 注入)
|
|
657
|
+
* + 请求级运行方式可选项(runOverrideModes)。
|
|
658
|
+
*
|
|
659
|
+
* runOverrideModes 仅 relay 形态非空:覆盖值都依赖 relay 执行基建
|
|
660
|
+
* (pull-claim 要 RunScheduler/lease,server-run 要 daemon 投递);local 形态
|
|
661
|
+
* 硬选 pull-claim 只会被 RUN_SCHEDULER_REQUIRED 拒掉(500),server-run 则
|
|
662
|
+
* 退化为与本进程执行无差别。前端据此不渲染覆盖下拉,避免诱导选择必败/无效项。
|
|
604
663
|
*/
|
|
605
664
|
publicConfig(): Promise<void>;
|
|
606
665
|
/**
|
|
@@ -689,6 +748,7 @@ declare class StagesController {
|
|
|
689
748
|
*/
|
|
690
749
|
designEvents(): Promise<void>;
|
|
691
750
|
setup(): Promise<void>;
|
|
751
|
+
setupVerify(): Promise<void>;
|
|
692
752
|
runHumanAction(): Promise<void>;
|
|
693
753
|
/**
|
|
694
754
|
* 启动 run。可选请求体 `{runMode}`(Phase 1.0 快速切片,per-project 配置落地前的验证入口):
|
|
@@ -700,6 +760,8 @@ declare class StagesController {
|
|
|
700
760
|
runStatus(): Promise<void>;
|
|
701
761
|
/** 工单列表:两模式同构读模型(local=runSnapshot / lease=PG work_items 投影)。 */
|
|
702
762
|
runRecords(): Promise<void>;
|
|
763
|
+
/** 事件时间线:从统一 RunController 读取,local/Gateway 的存储源由后端选择。 */
|
|
764
|
+
runEvents(): Promise<void>;
|
|
703
765
|
}
|
|
704
766
|
|
|
705
767
|
declare class CorsMiddleware {
|
|
@@ -1022,11 +1084,18 @@ interface RunController {
|
|
|
1022
1084
|
listRecords(projectId: string, opts?: {
|
|
1023
1085
|
limit?: number;
|
|
1024
1086
|
}): Promise<RunRecordsPageDTO>;
|
|
1087
|
+
/** 事件时间线(两模式同构;数据来源由服务端执行面选择)。 */
|
|
1088
|
+
listEvents(projectId: string, opts?: {
|
|
1089
|
+
afterSeq?: number;
|
|
1090
|
+
limit?: number;
|
|
1091
|
+
}): Promise<RunEventsPageDTO>;
|
|
1025
1092
|
}
|
|
1026
1093
|
declare class LocalRunController implements RunController {
|
|
1027
1094
|
private readonly services;
|
|
1095
|
+
private readonly runMode?;
|
|
1028
1096
|
readonly mode: "local";
|
|
1029
|
-
|
|
1097
|
+
/** runMode 缺省 = 不做 recipe 单步下发(P0/local 现状);显式选中方案三时透传给 run-runtime。 */
|
|
1098
|
+
constructor(services: ServerServices, runMode?: RunMode | undefined);
|
|
1030
1099
|
start(projectId: string, outgoing: ServerResponse): Promise<void>;
|
|
1031
1100
|
stop(projectId: string): Promise<RunControlResult>;
|
|
1032
1101
|
status(projectId: string): Promise<RunControlResult>;
|
|
@@ -1037,18 +1106,27 @@ declare class LocalRunController implements RunController {
|
|
|
1037
1106
|
listRecords(projectId: string, opts?: {
|
|
1038
1107
|
limit?: number;
|
|
1039
1108
|
}): Promise<RunRecordsPageDTO>;
|
|
1109
|
+
listEvents(projectId: string, opts?: {
|
|
1110
|
+
afterSeq?: number;
|
|
1111
|
+
limit?: number;
|
|
1112
|
+
}): Promise<RunEventsPageDTO>;
|
|
1040
1113
|
}
|
|
1041
1114
|
declare class RelayRunController implements RunController {
|
|
1042
1115
|
private readonly scheduler;
|
|
1043
1116
|
private readonly records?;
|
|
1117
|
+
private readonly events?;
|
|
1044
1118
|
readonly mode: "relay";
|
|
1045
|
-
constructor(scheduler: RunScheduler, records?: RunRecordsReader | undefined);
|
|
1119
|
+
constructor(scheduler: RunScheduler, records?: RunRecordsReader | undefined, events?: RunEventsReader | undefined);
|
|
1046
1120
|
start(projectId: string, outgoing: ServerResponse): Promise<void>;
|
|
1047
1121
|
stop(projectId: string): Promise<RunControlResult>;
|
|
1048
1122
|
status(projectId: string): Promise<RunControlResult>;
|
|
1049
1123
|
listRecords(projectId: string, opts?: {
|
|
1050
1124
|
limit?: number;
|
|
1051
1125
|
}): Promise<RunRecordsPageDTO>;
|
|
1126
|
+
listEvents(projectId: string, opts?: {
|
|
1127
|
+
afterSeq?: number;
|
|
1128
|
+
limit?: number;
|
|
1129
|
+
}): Promise<RunEventsPageDTO>;
|
|
1052
1130
|
}
|
|
1053
1131
|
/**
|
|
1054
1132
|
* 请求级显式指定的执行模式(Phase 1.0 快速切片:per-project 配置落地前的临时入口,
|
|
@@ -1057,8 +1135,21 @@ declare class RelayRunController implements RunController {
|
|
|
1057
1135
|
* 不是请求可选项。
|
|
1058
1136
|
*/
|
|
1059
1137
|
type RequestedRunMode = Exclude<RunMode, "local">;
|
|
1138
|
+
/** 请求级可覆盖的 relay 模式(public-config 下发给前端决定是否渲染覆盖下拉)。 */
|
|
1139
|
+
declare const REQUESTED_RUN_MODES: readonly RequestedRunMode[];
|
|
1060
1140
|
/** 校验请求体 `runMode`;缺省(无字段/空 body)返回 undefined 走部署默认。 */
|
|
1061
1141
|
declare function parseRequestedRunMode(value: unknown): RequestedRunMode | undefined;
|
|
1142
|
+
/**
|
|
1143
|
+
* 纯函数:从落盘的 run 阶段 phase 里取「可恢复的进程内 relay 模式」。
|
|
1144
|
+
* 只认两个进程内 relay 模式;`local` / 缺省 / pull-claim 一律返回 undefined
|
|
1145
|
+
* (pull-claim 的真源是 lease 行,由 hasActiveLease 粘性处理,不在此恢复)。
|
|
1146
|
+
*/
|
|
1147
|
+
declare function pickRecoverableRunMode(run: RunState | undefined): RequestedRunMode | undefined;
|
|
1148
|
+
/**
|
|
1149
|
+
* 从落盘的 run 阶段状态恢复「上一次进程内 run 用的执行粒度」,供 retry / 服务重启后
|
|
1150
|
+
* 的续跑使用——否则 retry 会回落部署缺省(gateway 上恒为 P0),把 recipe 下发跑成 agent 下发。
|
|
1151
|
+
*/
|
|
1152
|
+
declare function recoverPersistedRunMode(services: ServerServices, projectId: string): Promise<RequestedRunMode | undefined>;
|
|
1062
1153
|
/**
|
|
1063
1154
|
* 按执行域 runMode 装配控制器(P0/P1 分化 + Phase 1.0 project/request 粒度覆盖)。
|
|
1064
1155
|
*
|
|
@@ -1075,4 +1166,4 @@ declare function parseRequestedRunMode(value: unknown): RequestedRunMode | undef
|
|
|
1075
1166
|
*/
|
|
1076
1167
|
declare function resolveRunController(services: ServerServices, projectId?: string, requestedMode?: RequestedRunMode): Promise<RunController>;
|
|
1077
1168
|
|
|
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 };
|
|
1169
|
+
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
|
|
2
|
-
`)}
|
|
3
|
-
`)}
|
|
4
|
-
`));return}
|
|
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 xt(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(xt,"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 Rt(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(Rt,"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 Dt(t){return Array.isArray(t)?t[0]:t}o(Dt,"headerValue");function jt(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(jt,"isAuthExempt");var Y=class{resolve(){return async(e,r)=>{if(xt(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 Tt(t,e,r=200){t.writeHead(r,{"content-type":"text/plain; charset=UTF-8"}),t.end(e)}o(Tt,"sendText");function S(t,e,r,n,s){g(t,{error:{code:r,message:n,details:s}},e)}o(S,"sendError");function Ot(t){t.writeHead(401,{"content-type":"application/json; charset=utf-8"}),t.end(`${JSON.stringify({error:"unauthorized"})}
|
|
3
|
+
`)}o(Ot,"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(jt(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}Ot(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 qn}from"fs/promises";import{resolveInsideRoot as Un}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 It(t,e,r,n){let s=et.resolve(t),a=et.join(s,"index.html"),i=decodeURIComponent(e).replace(/^\/+/,""),c;try{c=i===""?a:Un(s,i,{allowRoot:!1})}catch{c=a}try{await qn(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(It,"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 It(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 ct,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 kt,writeFile as Et}from"fs/promises";import j from"path";var Kn=j.resolve(process.cwd(),".sandbox","aitable-workflow-server"),bt=/^[a-zA-Z0-9_-]+$/,Yn=/\.(json|ya?ml|ts|js|md|txt)$/i,Zn=["workflow.yml","recipes","traces"];function At(t={}){let e=j.resolve(t.dataRoot??process.env.AITABLE_WORKFLOW_DATA_DIR??Kn);return{dataRoot:e,projectsRoot:j.join(e,"projects")}}o(At,"createWorkspace");async function _t(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=Ct(t,n.id),await tt(n.dir,{recursive:!0}),await Oe(n),n}o(_t,"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()&&bt.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){qt(e);let r=Ct(t,e);if(!(await kt(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 Ft(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(Ft,"resetProjectWorkflow");async function Te(t){await st(t.dir,{recursive:!0,force:!0})}o(Te,"deleteProject");async function Qn(t){let e=await nt(Lt(t),"utf8").catch(()=>"");return e.trim()?JSON.parse(e):null}o(Qn,"readDesignManifest");async function it(t,e){await tt(Wt(t),{recursive:!0}),await Et(Lt(t),`${JSON.stringify(e,null,2)}
|
|
5
|
+
`,"utf8")}o(it,"writeDesignManifest");async function Nt(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 kt(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(Nt,"validateDesignArtifacts");function we(t){return zn("sha256").update(t).digest("hex")}o(we,"checksumContent");async function k(t){let e=[];return await Bt(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 Mt(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(Mt,"buildAITableUrl");function Xn(t){return j.join(t.dir,"runtime")}o(Xn,"runtimeDir");function Wt(t){return j.join(Xn(t),"artifacts")}o(Wt,"artifactsDir");function Lt(t){return j.join(Wt(t),"design-manifest.json")}o(Lt,"designManifestPath");function Ct(t,e){return qt(e),j.join(t.projectsRoot,e)}o(Ct,"projectDir");function qt(t){if(!bt.test(t))throw Object.assign(new Error(`\u975E\u6CD5\u9879\u76EE ID: ${t}`),{code:"INVALID_PROJECT_ID"})}o(qt,"assertProjectId");async function Oe(t){await Et(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 Bt(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 Bt(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(Bt,"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 $t,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&&$t(n,this.currentState),d=new Date().toISOString(),u=c?await s.createStageIdentity(r,n):{...this.identity,updatedAt:d},m={identity:$t(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 Jt(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(Jt,"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
|
-
`)}
|
|
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 Vt(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(Vt,"publishDesignEvent");function Ht(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(Ht,"closeDesignSession");function zt(t,e){let r=t.searchParams.get("cursor")??Dt(e.headers["last-event-id"]);if(r==null||r==="")return;let n=Number(r);return Number.isFinite(n)?n:void 0}o(zt,"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 Gt(t,e){return cs(t,(r,n)=>is({projectId:t.projectId,stage:r,state:n.state,facts:K(t.projectId,r,e)}))}o(Gt,"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 Gt(n,s);let i=await a.getStatus(e.id).catch(()=>null);return Gt(i?ls(n,i):n,s)}o(ke,"readProjectState");async function ps(t,e,r){if(r.stages.init||!await Promise.all([Kt(_(e)),Kt(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 Kt(t){return ds(t).then(()=>!0,()=>!1)}o(Kt,"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"){ct.warn("run-runtime","\u68C0\u6D4B\u5230\u50F5\u5C38 run \u4F1A\u8BDD\uFF08\u670D\u52A1\u91CD\u542F\uFF09\uFF0C\u81EA\u52A8\u91CD\u542F",{projectId:t,stalePhase:l.phase}),c??=l.runMode;let y=await m.advance({phase:"failed",error:{code:"RUN_SESSION_LOST",message:"\u540E\u7AEF\u8FD0\u884C\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF08\u670D\u52A1\u91CD\u542F\uFF09\uFF0C\u5DF2\u81EA\u52A8\u91CD\u542F\u8FD0\u884C\u3002",retryable:!0},runMode:l.runMode});a(s,"stage.changed",{type:"stage.changed",stage:"run",stageState:y})}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)&&(ct.info("run-runtime","publish run execution event",ys(l)),r.snapshotWrite=r.snapshotWrite.then(()=>s.appendRunSnapshotEvent(t,l)).catch(f=>{ct.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=
|
|
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 dt=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}}},ut=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 ut(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 dt(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,Tt(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 wt,Post as ge,Put as Cr}from"@midwayjs/core";import{validateDesignArtifacts as Ro,buildEnvSource as Do,loadWorkflowTemplate as qr,loadSettings as Ur}from"aitable-workflow-core";import{DwsClient as ir,dwsPayload as pt,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(pt(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=pt(c)?.newRecordIds?.[0];if(!u)throw new Error("dws \u672A\u8FD4\u56DE\u65B0\u884C recordId");return{recordId:u}}o(dr,"createRegistryAgent");function lt(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=>lt(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 lt(r)}o(lt,"cellToScalar");function se(t,e,r){if(!r)return;let n=e.get(r);if(n)return lt(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(pt(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 E(t,e){return e.projectStore.prepareWorkdir(t,{isStageActive:o(()=>Ms(e,t.id),"isStageActive")})}o(E,"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 ft,writeFile as fr,access as Ws,readdir as Ls}from"fs/promises";import Pe from"yaml";import{scaffold as Cs,writeProfileRoles as qs,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 qs(Ae.join(i.dir,"profile","profile.yml"),c.roles??[]);if(c.agentsSelected&&c.agentsSelected.length>0){let U=c.agentsSelected[0],x=U?Vs(U):void 0;if(x){let q=_(i);try{let D=Pe.parse(await ft(q,"utf8"));oe(D)&&(oe(D.agent)||(D.agent={}),D.agent.engine=x,await fr(q,Pe.stringify(D),"utf8"))}catch{}}}c.machineToken&&a&&await a(t,c.machineToken);let l=await L(i),f=m.skippedKnowledgeBindings.map(U=>`\u89D2\u8272 ${U.roleId} \u7684\u77E5\u8BC6\u5E93\u7ED1\u5B9A\u672A\u5199\u5165 profile\uFF0C\u540E\u7EED\u5E94\u4E0B\u6C89\u5230\u90E8\u7F72 Binding\uFF1A${U.knowledge.join(", ")}`);await d.advance({phase:"ready",warnings:f,roleFiles:[]});let y=lr(c.sop,1),b=await fe(l,{title:y});g(s,{project:b,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 ft(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 Us(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 Us(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(Us,"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 ft(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 mt(t,e){Dr(t.dir,e)}o(mt,"assertSafeProjectPath");function nd(t){Dr("/workflow-root",t)}o(nd,"assertSafeWorkflowPath");function jr(t){let r=gt(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=gt(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=gt(t);return e==="views.yml"||e.endsWith("/views.yml")}o(Ir,"isLegacyViewsPath");function gt(t){return xe.posix.normalize(t.replace(/\\/g,"/")).replace(/^\.\//,"")}o(gt,"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){mt(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(mt(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)mt(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(b=>typeof b=="string"&&b!=="")){for(let b of Object.keys(f))f[b]="";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 U=Fr(f.data);m=vo(U)??m;continue}if(!y||So(y))continue;let b=Fr(f.data);w.set(y,{path:y,content:b})}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 E(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 E(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 E(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,tracePort:i.tracePort,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 Ur(_(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 Ur(_(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 E(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 E(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 qr(n,{envSource:r}).catch(()=>qr(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 Ft(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([wt("/: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([wt("/: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([wt("/: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 E(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 E(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 E(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 E(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 qo,nextFor as Uo,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:Uo({projectId:t.id,stage:"design",state:r,facts:K(t.id,"design",Qr)})}}o(Bo,"currentEntry");function ht(t,e,r){return G.open({project:t,stage:"design",store:e,driver:r,facts:o(()=>K(t.id,"design",Qr),"facts")})}o(ht,"designWriter");async function Xr(t,e,r,n,s){let a=await I(e,t),i=await ht(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 qo(t,e)}o($o,"seedAnswers");async function tn(t,e,r,n,s){let a=await I(e,t),i=await ht(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=Jt(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 ht(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=>Vt(l,P),"send");d.emit=P=>f({type:"stage.changed",stage:"design",stageState:P});let y=Date.now(),b=y,U=0,x=[],q=[],D=o((P,M)=>{let W=Date.now(),$=W-y,J=W-b;b=W,x.push({label:P,at:new Date(W).toISOString(),elapsedMs:$,...M?{detail:M}:{}}),x.length>40&&x.shift(),d.setDiagnostics({timeline:x,recentAgentEvents:q}),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)&&(q.push(Vo(h)),q.length>30&&q.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()-U>5e3&&(U=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:q,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:q,...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),Pt=Go(i,d,vn);await it(i,Pt),d.setDiagnostics({timeline:x,recentAgentEvents:q,...J.validation?{validation:J.validation}:{}}),await d.advance({phase:"ready",confirmed:m,manifest:Pt,rounds:J.rounds}),n.end()}catch(P){await pe().catch(()=>{}),d.setDiagnostics({timeline:x,recentAgentEvents:q}),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{Ht(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 yt=new Set;async function St(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(yt.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")});yt.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"),q=l?(s.listMachines()??[]).find(je=>je.machineId===l):void 0,D=await x({configPath:y,executionRuntimes:q?.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 b=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 U=b.tables.map(x=>({workflowId:x.workflowId,label:x.label,baseId:x.baseId,tableId:x.tableId,tableUrl:Mt(x.baseId,x.tableId),schema:sn(x.perSettings,x.workflow)}));u.push(...b.tables.flatMap(x=>x.warnings)),await L(a),await i.advance({phase:"ready",tables:U,warnings:u}),n.end()})})}catch(l){let f=o(async y=>{try{await i.advance(y)}catch(b){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(b),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{yt.delete(a.id)}}o(St,"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,b=typeof y=="string"?y:JSON.stringify(y)??"";await li(f.writeTarget,b,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 E(r,e),await St(r.id,e.workspace,e.projectStore.instances,this.ctx.res,e.execution);return}if(a&&n==="run"){await E(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 E(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 E(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 E(r,e);let n=new URL(this.ctx.req.url??"/","http://localhost"),s=zt(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 E(r,e),await St(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 E(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 E(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 Ui,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 _t(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 qe=new Map,ji=/^[a-zA-Z0-9_-]+$/,Ue=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 Nt(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=(qe.get(r)??Promise.resolve()).catch(()=>{}).then(e),a=s.then(()=>{},()=>{});qe.set(r,a);try{return await s}finally{qe.get(r)===a&&qe.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 Ue(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 vt="local",Ci=3e4;function qi(t,e=Date.now()){return{machineId:vt,runtimes:t.map(r=>r.id),hasDws:!0,hostname:Wi(),os:Li(),lastSeen:e}}o(qi,"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:qi(r,e),at:e}}return[this.localMachineCache.info]}isMachineOnline(e){return e===vt}async getProjectMachine(){return vt}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=Rt(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??At({dataRoot:t.dataRoot});return{workspace:e,runtime:Qt(t.appFactory??((r,n)=>Ui(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,vt as LOCAL_MACHINE_ID,Je as LocalExecutionBackend,Ve as LocalIdentityService,Sn as LocalProjectMutexStore,Ce as LocalProjectRepository,$e as LocalProjectStore,dt as LocalRunController,Ue as LocalWorkflowInstanceStore,be as REQUESTED_RUN_MODES,Ps as RUN_REPLAY_AGENT_CAP,vs as RUN_REPLAY_EVENT_CAP,ut as RelayRunController,le as apiError,mt as assertSafeProjectPath,Dr as assertSafeRelativePath,nd as assertSafeWorkflowPath,Tr as assertWritableKind,Mt as buildAITableUrl,qi as buildLocalMachineInfo,pr as cascadeDeleteProject,we as checksumContent,ve as commitStageOnTerminal,_ as configPath,_t as createProject,Qt as createServerRuntime,fn as createServerServices,At 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,E as prepareWorkdirGuarded,Ze as readBuffer,Qn as readDesignManifest,A as readJson,sr as recoverPersistedRunMode,Ie as removeLegacyViewsFiles,kr as removeProjectFiles,Er as replaceProjectFiles,Ft as resetProjectWorkflow,I as resolveProject,ce as resolveRunController,gn as resolveServeConfig,O as scopeOf,S as sendError,g as sendJson,Tt as sendText,Ot as sendUnauthorized,Ki as silentLoggerFactory,Ds as stampRunEvent,gp as startServer,L as touchProject,xs as trimRunReplayEvents,fe as updateProjectMeta,no as validateConfigScene,Nt 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.
|
|
3
|
+
"version": "0.1.29-beta.1790736949347",
|
|
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.
|
|
25
|
+
"aitable-workflow-core": "0.1.29-beta.1790736949347",
|
|
26
26
|
"@midwayjs/core": "^3.20.4",
|
|
27
27
|
"@midwayjs/koa": "^3.20.4",
|
|
28
28
|
"fflate": "^0.8.2",
|